diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX
--- a/Documentation/00-INDEX	Sun Nov 17 20:30:12 2002
+++ b/Documentation/00-INDEX	Sun Nov 17 20:30:12 2002
@@ -32,8 +32,6 @@
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 README.moxa
 	- release notes for Moxa mutiport serial card.
-README.nsp_cs.eng
-	- info on WorkBiT NinjaSCSI-3/32Bi driver.
 SAK.txt
 	- info on Secure Attention Keys.
 SubmittingDrivers
@@ -188,10 +186,8 @@
 	- directory with info on using Linux on the IBM S390.
 sh/
 	- directory with info on porting Linux to a new architecture.
-scsi-generic.txt
-	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
-scsi.txt
-	- short blurb on using SCSI support as a module.
+scsi/
+	- directory with info on Linux scsi support.
 serial-console.txt
 	- how to set up Linux with a serial line console as the default.
 sgi-visws.txt
diff -Nru a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
--- a/Documentation/DocBook/procfs_example.c	Sun Nov 17 20:30:16 2002
+++ b/Documentation/DocBook/procfs_example.c	Sun Nov 17 20:30:16 2002
@@ -75,13 +75,9 @@
 {
 	int len;
 
-	MOD_INC_USE_COUNT;
-	
 	len = sprintf(page, "jiffies = %ld\n",
                       jiffies);
 
-	MOD_DEC_USE_COUNT;
-
 	return len;
 }
 
@@ -93,13 +89,10 @@
 	int len;
 	struct fb_data_t *fb_data = (struct fb_data_t *)data;
 
-	MOD_INC_USE_COUNT;
-	
+	/* DON'T DO THAT - buffer overruns are bad */
 	len = sprintf(page, "%s = '%s'\n", 
 		      fb_data->name, fb_data->value);
 
-	MOD_DEC_USE_COUNT;
-
 	return len;
 }
 
@@ -112,21 +105,15 @@
 	int len;
 	struct fb_data_t *fb_data = (struct fb_data_t *)data;
 
-	MOD_INC_USE_COUNT;
-
 	if(count > FOOBAR_LEN)
 		len = FOOBAR_LEN;
 	else
 		len = count;
 
-	if(copy_from_user(fb_data->value, buffer, len)) {
-		MOD_DEC_USE_COUNT;
+	if(copy_from_user(fb_data->value, buffer, len))
 		return -EFAULT;
-	}
 
 	fb_data->value[len] = '\0';
-
-	MOD_DEC_USE_COUNT;
 
 	return len;
 }
diff -Nru a/Documentation/README.nsp_cs.eng b/Documentation/README.nsp_cs.eng
--- a/Documentation/README.nsp_cs.eng	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,130 +0,0 @@
-
-         WorkBiT NinjaSCSI-3/32Bi driver for Linux
-
-1. Comment
- This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3
-(http://www.workbit.co.jp/ts/z_nj3r.html) and NinjaSCSI-32Bi
-(http://www.workbit.co.jp/ts/z_njsc32bi.html) PCMCIA card driver module
-for Linux.
-
-2. My Linux environment
-Linux kernel: 2.4.7 / 2.2.19
-pcmcia-cs:    3.1.27
-gcc:          gcc-2.95.4
-PC card:      I-O data PCSC-F (NinjaSCSI-3)
-              I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi)
-SCSI device:  I-O data CDPS-PX24 (CD-ROM drive)
-              Media Intelligent MMO-640GT (Optical disk drive)
-
-3. Install
-[1] Check your PC card is true "NinjaSCSI-3" card.
-    If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN
-    card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to
-    your console or log file.
-    You can also use "cardctl" program (this program is in pcmcia-cs source
-    code) to get more info.
-
-# cat /var/log/messgaes
-...
-Jan  2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1
-Jan  2 03:45:06 lindberg cardmgr[78]:   product info: "WBT", "NinjaSCSI-3", "R1.0"
-...
-# cardctl ident
-Socket 0:
-  no product info available
-Socket 1:
-  product info: "IO DATA", "CBSC16       ", "1"
-
-
-[2] Get Linux kernel source, and extract it to /usr/src.
-    Because NinjaSCSI driver requiers some SCSI header files in Linux kernel
-    source.
-    I recomend rebuilding your kernel. This eliminate some versioning problem.
-$ cd /usr/src
-$ tar -zxvf linux-x.x.x.tar.gz
-$ cd linux
-$ make config
-...
-
-[3] If you use this driver with Kernel 2.2, Unpack pcmcia-cs in some directory
-    and make & install. This driver requies pcmcia-cs header file.
-$ cd /usr/src
-$ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz
-...
-
-[4] Extract this driver's archive somewhere, and edit Makefile, then do make.
-$ tar -zxvf nsp_cs-x.x.tar.gz
-$ cd nsp_cs-x.x
-$ emacs Makefile
-...
-$ make
-
-[5] Copy nsp_cs.o to suitable plase, like /lib/modules/<Kernel version>/pcmcia/ .
-
-[6] Add these lines to /etc/pcmcia/config .
-    If you yse pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file.
-    So, you don't need to edit file. Just copy to /etc/pcmcia/ .
-
--------------------------------------
-device "nsp_cs"
-  class "scsi" module "nsp_cs"
-
-card "WorkBit NinjaSCSI-3"
-  version "WBT", "NinjaSCSI-3", "R1.0"
-  bind "nsp_cs"
-
-card "WorkBit NinjaSCSI-32Bi (16bit)"
-  version "WORKBIT", "UltraNinja-16", "1"
-  bind "nsp_cs"
-
-# OEM
-card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA"
-  version "IO DATA", "CBSC16       ", "1"
-  bind "nsp_cs"
-
-# OEM
-card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1"
-  version "KME    ", "SCSI-CARD-001", "1"
-  bind "nsp_cs"
-card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2"
-  version "KME    ", "SCSI-CARD-002", "1"
-  bind "nsp_cs"
-card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3"
-  version "KME    ", "SCSI-CARD-003", "1"
-  bind "nsp_cs"
-card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4"
-  version "KME    ", "SCSI-CARD-004", "1"
-  bind "nsp_cs"
--------------------------------------
-
-[7] Start (or restart) pcmcia-cs.
-# /etc/rc.d/rc.pcmcia start        (BSD style)
-or
-# /etc/init.d/pcmcia start         (SYSV style)
-
-
-4. History
-See README.nin_cs .
-
-5. Caution
- If you eject card when doing some operation for your SCSI device or suspend
-your computer, you encount some *BAD* error like disk crash.
- It works good when I using this driver right way. But I'm not guarantee
-your data. Please backup your data when you use this driver.
-
-6. Known Bugs
- In 2.4 kernel, you can't use 640MB Optical disk. This error comes from
-high level SCSI driver.
-
-7. Testing
- Please send me some reports(bug reports etc..) of this software.
-When you send report, please tell me these or more.
-	card name
-	kernel version
-	your SCSI device name(hard drive, CD-ROM, etc...)
-
-8. Copyright
- See GPL.
-
-
-2001/08/08 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi>
diff -Nru a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/00-INDEX	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,68 @@
+00-INDEX
+	- this file
+53c700.txt
+	- info on driver for 53c700 based adapters
+AM53C974.txt
+	- info on driver for AM53c974 based adapters
+BusLogic.txt
+	- info on driver for adapters with BusLogic chips
+ChangeLog
+	- Changes to scsi files, if not listed elsewhere
+ChangeLog.ips
+	- IBM ServeRAID driver Changelog
+ChangeLog.ncr53c8xx
+	- Changes to ncr53c8xx driver
+ChangeLog.sym53c8xx
+	- Changes to sym53c8xx driver
+ChangeLog.sym53c8xx_2
+	- Changes to second generation of sym53c8xx driver
+FlashPoint.txt
+	- info on driver for BusLogic FlashPoint adapters
+LICENSE.FlashPoint
+	- Licence of the Flashpoint driver
+Mylex.txt
+	- info on driver for Mylex adapters
+NinjaSCSI.txt
+	- info on WorkBiT NinjaSCSI-32/32Bi driver
+aha152x.txt
+	- info on driver for Adaptec AHA152x based adapters
+aic7xxx.txt
+	- info on driver for Adaptec controllers
+aic7xxx_old.txt
+	- info on driver for Adaptec controllers, old generation
+cpqfc.txt
+	- info on driver for Compaq Tachyon TS adapters
+dpti.txt
+	- info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters
+dtc3x80.txt
+	- info on driver for DTC 2x80 based adapters
+g_NCR5380.txt
+	- info on driver for NCR5380 and NCR53c400 based adapters
+ibmmca.txt
+	- info on driver for IBM adapters with MCA bus
+in2000.txt
+	- info on in2000 driver
+ncr53c7xx.txt
+	- info on driver for NCR53c7xx based adapters
+ncr53c8xx.txt
+	- info on driver for NCR53c8xx based adapters
+osst.txt
+	- info on driver for OnStream SC-x0 SCSI tape
+ppa.txt
+	- info on driver for IOmega zip drive
+qlogicfas.txt
+	- info on driver for QLogic FASxxx based adapters
+qlogicisp.txt
+	- info on driver for QLogic ISP 1020 based adapters
+scsi-generic.txt
+	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
+scsi.txt
+	- short blurb on using SCSI support as a module.
+scsi_mid_low_api.txt
+	- info on API between SCSI layer and low level drivers
+st.txt
+	- info on scsi tape driver
+sym53c8xx_2.txt
+	- info on second generation driver for sym53c8xx based adapters
+tmscsim.txt
+	- info on driver for AM53c974 based adapters
diff -Nru a/Documentation/scsi/53c700.txt b/Documentation/scsi/53c700.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/53c700.txt	Sun Nov 17 20:30:14 2002
@@ -0,0 +1,154 @@
+General Description
+===================
+
+This driver supports the 53c700 and 53c700-66 chips.  It also supports
+the 53c710 but only in 53c700 emulation mode.  It is full featured and
+does sync (-66 and 710 only), disconnects and tag command queueing.
+
+Since the 53c700 must be interfaced to a bus, you need to wrapper the
+card detector around this driver.  For an example, see the
+NCR_D700.[ch] or lasi700.[ch] files.
+
+The comments in the 53c700.[ch] files tell you which parts you need to
+fill in to get the driver working.
+
+
+Compile Time Flags
+==================
+
+The driver may be either io mapped or memory mapped.  This is
+selectable by configuration flags:
+
+CONFIG_53C700_MEM_MAPPED
+
+define if the driver is memory mapped.
+
+CONFIG_53C700_IO_MAPPED
+
+define if the driver is to be io mapped.
+
+One or other of the above flags *must* be defined.
+
+Other flags are:
+
+CONFIG_53C700_LE_ON_BE
+
+define if the chipset must be supported in little endian mode on a big
+endian architecture (used for the 700 on parisc).
+
+CONFIG_53C700_USE_CONSISTENT
+
+allocate consistent memory (should only be used if your architecture
+has a mixture of consistent and inconsistent memory).  Fully
+consistent or fully inconsistent architectures should not define this.
+
+
+Using the Chip Core Driver
+==========================
+
+In order to plumb the 53c700 chip core driver into a working SCSI
+driver, you need to know three things about the way the chip is wired
+into your system (or expansion card).
+
+1. The clock speed of the SCSI core
+2. The interrupt line used
+3. The memory (or io space) location of the 53c700 registers.
+
+Optionally, you may also need to know other things, like how to read
+the SCSI Id from the card bios or whether the chip is wired for
+differential operation.
+
+Usually you can find items 2. and 3. from general spec. documents or
+even by examining the configuration of a working driver under another
+operating system.
+
+The clock speed is usually buried deep in the technical literature.
+It is required because it is used to set up both the synchronous and
+asynchronous dividers for the chip.  As a general rule of thumb,
+manufacturers set the clock speed at the lowest possible setting
+consistent with the best operation of the chip (although some choose
+to drive it off the CPU or bus clock rather than going to the expense
+of an extra clock chip).  The best operation clock speeds are:
+
+53c700 - 25MHz
+53c700-66 - 50MHz
+53c710 - 40Mhz
+
+Writing Your Glue Driver
+========================
+
+This will be a standard SCSI driver (I don't know of a good document
+describing this, just copy from some other driver) with at least a
+detect and release entry.
+
+In the detect routine, you need to allocate a struct
+NCR_700_Host_Parameters sized memory area and clear it (so that the
+default values for everything are 0).  Then you must fill in the
+parameters that matter to you (see below), plumb the NCR_700_intr
+routine into the interrupt line and call NCR_700_detect with the host
+template and the new parameters as arguments.  You should also call
+the relevant request_*_region function and place the register base
+address into the `base' pointer of the host parameters.
+
+In the release routine, you must free the NCR_700_Host_Parameters that
+you allocated, call the corresponding release_*_region and free the
+interrupt.
+
+Handling Interrupts
+-------------------
+
+In general, you should just plumb the card's interrupt line in with 
+
+request_irq(irq, NCR_700_intr, <irq flags>, <driver name>, host);
+
+where host is the return from the relevant NCR_700_detect() routine.
+
+You may also write your own interrupt handling routine which calls
+NCR_700_intr() directly.  However, you should only really do this if
+you have a card with more than one chip on it and you can read a
+register to tell which set of chips wants the interrupt.
+
+Settable NCR_700_Host_Parameters
+--------------------------------
+
+The following are a list of the user settable parameters:
+
+clock: (MANDATORY)
+
+Set to the clock speed of the chip in MHz.
+
+base: (MANDATORY)
+
+set to the base of the io or mem region for the register set. On 64
+bit architectures this is only 32 bits wide, so the registers must be
+mapped into the low 32 bits of memory.
+
+pci_dev: (OPTIONAL)
+
+set to the PCI board device.  Leave NULL for a non-pci board.  This is
+used for the pci_alloc_consistent() and pci_map_*() functions.
+
+dmode_extra: (OPTIONAL, 53c710 only)
+
+extra flags for the DMODE register.  These are used to control bus
+output pins on the 710.  The settings should be a combination of
+DMODE_FC1 and DMODE_FC2.  What these pins actually do is entirely up
+to the board designer.  Usually it is safe to ignore this setting.
+
+differential: (OPTIONAL)
+
+set to 1 if the chip drives a differential bus.
+
+force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set)
+
+set to 1 if the chip is operating in little endian mode on a big
+endian architecture.
+
+chip710: (OPTIONAL)
+
+set to 1 if the chip is a 53c710.
+
+burst_disable: (OPTIONAL, 53c710 only)
+
+disable 8 byte bursting for DMA transfers.
+
diff -Nru a/Documentation/scsi/AM53C974.txt b/Documentation/scsi/AM53C974.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/AM53C974.txt	Sun Nov 17 20:30:12 2002
@@ -0,0 +1,246 @@
+SUBJECT
+-------
+AM53/79C974 PC-SCSI Driver
+
+
+DISCLAIMER
+----------
+***  THIS SHOULD BE CONSIDERED AS BETA SOFTWARE  ***
+***  USE AT YOUR OWN RISK!                       ***
+
+
+Copyright
+---------
+The architecture and much of the code of this device driver was 
+originally developed by Drew Eckhardt for the NCR5380. The 
+following copyrights apply:
+
+For the architecture and all pieces of code which can also be found 
+in the NCR5380 device driver:
+Copyright 1993, Drew Eckhardt
+  Visionary Computing 
+  (Unix and Linux consulting and custom programming)
+  drew@colorado.edu
+  +1 (303) 666-5836
+ 
+The AM53C974_nobios_detect code was originally developed by
+Robin Cutshaw (robin@xfree86.org) and is used here in a 
+slightly modified form.
+ 
+For the remaining code:
+  Copyright 1994, D. Frieauff
+  EMail: fri@rsx42sun0.dofn.de
+  Phone: x49-7545-8-2256 , x49-7541-42305
+
+
+Version
+-------
+AM53/79C974 (PC-SCSI) Linux driver ALPHA release 0.5, 19 November 1995
+
+
+Changelog
+---------
+0.1 -> 0.2: 
+  - Extended message handling re-written to eliminate 'invalid message 17' bug
+  - Parameters of AM53C974_intr adapted
+  - Debug messages structured
+  - Spelling improved
+0.2 -> 0.3:
+  - README file updated -- please read this file up to the end!
+  - Automatic scanning of io_port and irq implemented; no need for BIOS32 
+    anymore
+  - Improved configuration (now via LILO parameter string)
+  - Cleanup of probing and initialization code
+  - Improved sync. negotiation (can be setup individually for every device)
+  - Improved/ debugged code for reception of ext. messages
+0.3 -> 0.4:
+  - Improved PCI probing and initialization code
+  - Compatibility changes for Linux 1.3.x
+0.4 -> 0.5:
+  - Compatibility changes for Linux 1.3.42
+
+
+Bugs & Todo
+-----------
+ - Add proc info function
+ - Support SCSI-2 tagged queuing
+ - Finalize abort code 
+
+
+Features
+--------
+This driver supports asynchronous and synchronous SCSI-I and SCSI-II
+devices.  It is capable of transfer rate and synchronous negotiation
+(see below).  The driver supports scatter-gather.  Transfers are DMA
+based, but do not (yet) make use of the AM53/79C974 MDL mode.
+Max. transfer rate is 10MHz (whatever this is in real life).  The
+transfer rate is negotiated with each device (see dmesg output).  The
+AM53/79C974 has a 96-byte DMA FIFO to the PCI bus and a 16-byte SCSI
+FIFO.  It provides active negation and glitch suppression functions.
+Burst DMA transfer rate is 132 MBytes/sec.
+
+
+Configuration
+-------------
+
+The following communication characteristics can be set individually
+for every SCSI device on the bus:
+
+  - enable/disable sync. negotiation
+  - transfer rate
+  - asynchronous or synchronous communication
+  - in case of sync. communication, the sync. offset
+
+The sync. offset specifies the number of bytes that can be sent or 
+received from the SCSI bus without ACK resp. REQ signal.
+CAUTION: USING SYNCHRONOUS MODE ON LONG SCSI CABLES MAY CAUSE 
+         COMMUNICATION PROBLEMS LEADING TO LOSS OF DATA. 
+
+The default setting of the SCSI communication parameters is as follows:
+  - no negotiation
+  - 5.0 MHz transfer rate
+  - asynchronous mode
+  - zero offset
+
+The parameters can be modified by passing a string with the following
+syntax to the kernel:
+
+	AM53C974=host-scsi-id,target-scsi-id,max-rate,max-offset
+
+The parameters will be used by the driver as negotiation basis.  The
+range of the rate parameter is 3 to 10 MHz.  The range of the
+sync. offset parameter is 0 to 15 bytes. A value of 0 denotes
+asynchronous comm. mode.  If the target cannot cope with the specified
+transfer rate, sync. mode or sync.  offset, the negotiation result
+will differ from the specified values.  The negotiation result is
+printed out at the end of the negotiation process (to read it, use the
+dmesg program or the appropriate syslog).  The parameter strings
+(blank separated) can be passed to the kernel at the LILO prompt, or
+as part of the LILO configuration file.
+
+For example, the string "AM53C974=7,2,8,15" would be interpreted as
+follows:
+
+For communication between the controller with SCSI-ID 7 and the
+device with SCSI-ID 2 a transfer rate of 8MHz in synchronous mode with
+max. 15 bytes offset should be negotiated.
+
+As an example, here my LILO configuration file:
+  boot = /dev/sda
+  compact
+  #prompt
+  delay = 50	# optional, for systems that boot very quickly
+  vga = normal	# force sane state
+  ramdisk = 0	# paranoia setting
+  root = current  # use "current" root
+  image = /usr/src/linux/arch/i386/boot/zImage
+    label = linux
+    append = "AM53C974=7,0,10,0 AM53C974=7,1,10,0 AM53C974=7,2,10,15 AM53C974=7,4,10,0 AM53C974=7,5,10,0"
+    read-only
+  other = /dev/sda4
+    label = os2
+  other = /dev/sdb3
+    loader = /boot/any_d.b
+    table = /dev/sdb
+    label = setup
+
+The same parameters at the LILO prompt:
+
+  LILO boot: linux AM53C974=7,0,10,0 AM53C974=7,1,10,0 AM53C974=7,2,10,15 AM53C974=7,4,10,0 AM53C974=7,5,10,0
+
+You can override parameters specified in the LILO configuration file
+by parameters specified on the LILO command line.
+
+
+BIOS usage
+----------
+Version 0.4 of the driver will use the BIOS, if available. Otherwise
+it will try its internal PCI scan and access routines.  The driver
+assumes that the controller's SCSI-ID (usually 7) has been correctly
+loaded by the BIOS into the controller's register during system
+boot. If the driver detects that the controller's SCSI ID is not '7'
+it will print out a warning. If this happens to you please correct
+setting of the controller's SCSI-ID. If it is wrong, then edit the
+AM53C974_SCSI_ID definition in file AM53C974.h accordingly.
+
+
+Test environment
+----------------
+This driver was tested on a Compaq XL566 with the following SCSI configuration:
+2 x HP C2247 fixed disk (internal, rate=10MHz, async.)
+1 x Micropolis 1624 fixed disk (external, rate=8MHz, sync., offset=15 bytes)
+1 x Wangtek W5525ES cartridge streamer (internal, rate=5MHz, async.)
+1 x Toshiba XM-3301B CD-ROM (external, rate=5MHz, async.)
+
+
+Known problems
+--------------
+ - Compaq/Matsushita CD-ROM:
+   Use of this device with AM53C974 driver version 0.2 caused the kernel to
+   hang during Linux boot. If you encounter the problem, don't enable sync.
+   negotiation with the CD-ROM, i.e. simply don't specify comm. parameters 
+   for this device on the LILO command line or configuration file. 
+   The driver will thus use its default for the CD-ROM, which is 5MHz 
+   transfer rate async and no sync. negotiation.
+ - Some disks cause problems.
+
+
+What to do if there is a SCSI problem possibly related to the driver
+--------------------------------------------------------------------
+
+Read Klaus Liedl's WWW page (http://www-c724.uibk.ac.at/XL/).  In case
+this does not help: Send me a complete description of the problem,
+including your SCSI configuration plus as much debugging information
+as possible.  Don't wait until I ask you for this information. To
+enable the generation of debugging output, remove the comments from
+the following definitions in the AM53C974.h file:
+
+    AM53C974_DEBUG
+    AM53C974_DEBUG_MSG
+    AM53C974_DEBUG_KEYWAIT
+    AM53C974_DEBUG_INFO
+    AM53C974_DEBUG_INTR
+
+With these definitions enabled, the driver will enter single-step mode
+during Linux boot. Use the spacebar for stepping.  Take note of at
+least the last 10 printout sections (marked by dashes) before the
+crash/hangup or whatever happens and send me all of this information
+via email. If the system can boot, use the syslogd daemon to record
+the debugging output. Maybe you can use the ramdisk for this purpose
+too (if necessary, kindly ask K. Liedl (Klaus.Liedl@uibk.ac.at) for
+support, he knows how to do it -- I never tried). Stay in email
+contact with me. Be aware that the following weeks/months could be the
+worst of your life.  Note: If single-stepping takes up too much time,
+you can try to let the driver catch the problem by pressing the 'r'
+key. The driver will automatically enter single-step mode if it has
+detected something weird.
+
+
+Author's Contact Address
+-----------------------
+Email: fri@rsx42sun0.dofn.de
+Phone: x49-7545-2256 (office), x49-7541-42305 (home)
+Home address: D. Frieauff, Stockerholzstr. 27, 88048 Friedrichshafen, Germany
+
+
+!!!! Important Notice !!!!
+-----------------------------
+- Klaus Liedl maintains an excellent WWW page about Linux on Compaq XL.
+  It includes an FAQ, lots of tips & tricks as well as downloadable 
+  boot disk images. The URL is: http://www-c724.uibk.ac.at/XL/
+- Volunteer wanted for further maintenance of this driver software. I
+  don't have the time anymore to do serious support as some of you will know.
+
+
+Literature
+----------
+ - AMD AM53C974 PC-SCSI Technical Manual, publication #18624B
+ - Amendment to the AMD AM53C974 PC-SCSI Technical Manual
+ - AMD AM79C974 PC-NET Datasheet, publication #18681
+ - Amendment to the AMD AM79C974 PC-NET Datasheet
+
+
+THANKS to
+---------
+ - Drew Eckhardt, Robin Cutshaw, K. Liedl, Robert J. Pappas, A. Grenier, 
+   Mark Stockton, David C. Niemi, Ben Craft, and many others who have helped
diff -Nru a/Documentation/scsi/BusLogic.txt b/Documentation/scsi/BusLogic.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/BusLogic.txt	Sun Nov 17 20:30:12 2002
@@ -0,0 +1,613 @@
+	   BusLogic MultiMaster and FlashPoint SCSI Driver for Linux
+
+			 Version 2.0.15 for Linux 2.0
+			 Version 2.1.15 for Linux 2.1
+
+			      PRODUCTION RELEASE
+
+				17 August 1998
+
+			       Leonard N. Zubkoff
+			       Dandelion Digital
+			       lnz@dandelion.com
+
+	 Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+
+				 INTRODUCTION
+
+BusLogic, Inc. designed and manufactured a variety of high performance SCSI
+host adapters which share a common programming interface across a diverse
+collection of bus architectures by virtue of their MultiMaster ASIC technology.
+BusLogic was acquired by Mylex Corporation in February 1996, but the products
+supported by this driver originated under the BusLogic name and so that name is
+retained in the source code and documentation.
+
+This driver supports all present BusLogic MultiMaster Host Adapters, and should
+support any future MultiMaster designs with little or no modification.  More
+recently, BusLogic introduced the FlashPoint Host Adapters, which are less
+costly and rely on the host CPU, rather than including an onboard processor.
+Despite not having an onboard CPU, the FlashPoint Host Adapters perform very
+well and have very low command latency.  BusLogic has recently provided me with
+the FlashPoint Driver Developer's Kit, which comprises documentation and freely
+redistributable source code for the FlashPoint SCCB Manager.  The SCCB Manager
+is the library of code that runs on the host CPU and performs functions
+analogous to the firmware on the MultiMaster Host Adapters.  Thanks to their
+having provided the SCCB Manager, this driver now supports the FlashPoint Host
+Adapters as well.
+
+My primary goals in writing this completely new BusLogic driver for Linux are
+to achieve the full performance that BusLogic SCSI Host Adapters and modern
+SCSI peripherals are capable of, and to provide a highly robust driver that can
+be depended upon for high performance mission critical applications.  All of
+the major performance and error recovery features can be configured from the
+Linux kernel command line or at module initialization time, allowing individual
+installations to tune driver performance and error recovery to their particular
+needs.
+
+The latest information on Linux support for BusLogic SCSI Host Adapters, as
+well as the most recent release of this driver and the latest firmware for the
+BT-948/958/958D, will always be available from my Linux Home Page at URL
+"http://www.dandelion.com/Linux/".
+
+Bug reports should be sent via electronic mail to "lnz@dandelion.com".  Please
+include with the bug report the complete configuration messages reported by the
+driver and SCSI subsystem at startup, along with any subsequent system messages
+relevant to SCSI operations, and a detailed description of your system's
+hardware configuration.
+
+Mylex has been an excellent company to work with and I highly recommend their
+products to the Linux community.  In November 1995, I was offered the
+opportunity to become a beta test site for their latest MultiMaster product,
+the BT-948 PCI Ultra SCSI Host Adapter, and then again for the BT-958 PCI Wide
+Ultra SCSI Host Adapter in January 1996.  This was mutually beneficial since
+Mylex received a degree and kind of testing that their own testing group cannot
+readily achieve, and the Linux community has available high performance host
+adapters that have been well tested with Linux even before being brought to
+market.  This relationship has also given me the opportunity to interact
+directly with their technical staff, to understand more about the internal
+workings of their products, and in turn to educate them about the needs and
+potential of the Linux community.
+
+More recently, Mylex has reaffirmed the company's interest in supporting the
+Linux community, and I am now working on a Linux driver for the DAC960 PCI RAID
+Controllers.  Mylex's interest and support is greatly appreciated.
+
+Unlike some other vendors, if you contact Mylex Technical Support with a
+problem and are running Linux, they will not tell you that your use of their
+products is unsupported.  Their latest product marketing literature even states
+"Mylex SCSI host adapters are compatible with all major operating systems
+including: ... Linux ...".
+
+Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont, California
+94555, USA and can be reached at 510/796-6100 or on the World Wide Web at
+http://www.mylex.com.  Mylex HBA Technical Support can be reached by electronic
+mail at techsup@mylex.com, by Voice at 510/608-2400, or by FAX at 510/745-7715.
+Contact information for offices in Europe and Japan is available on the Web
+site.
+
+
+				DRIVER FEATURES
+
+o Configuration Reporting and Testing
+
+  During system initialization, the driver reports extensively on the host
+  adapter hardware configuration, including the synchronous transfer parameters
+  requested and negotiated with each target device.  AutoSCSI settings for
+  Synchronous Negotiation, Wide Negotiation, and Disconnect/Reconnect are
+  reported for each target device, as well as the status of Tagged Queuing and
+  Error Recovery.  If the same setting is in effect for all target devices,
+  then a single word or phrase is used; otherwise, a letter is provided for
+  each target device to indicate the individual status.  The following examples
+  should clarify this reporting format:
+
+    Synchronous Negotiation: Ultra
+
+      Synchronous negotiation is enabled for all target devices and the host
+      adapter will attempt to negotiate for 20.0 mega-transfers/second.
+
+    Synchronous Negotiation: Fast
+
+      Synchronous negotiation is enabled for all target devices and the host
+      adapter will attempt to negotiate for 10.0 mega-transfers/second.
+
+    Synchronous Negotiation: Slow
+
+      Synchronous negotiation is enabled for all target devices and the host
+      adapter will attempt to negotiate for 5.0 mega-transfers/second.
+
+    Synchronous Negotiation: Disabled
+
+      Synchronous negotiation is disabled and all target devices are limited to
+      asynchronous operation.
+
+    Synchronous Negotiation: UFSNUUU#UUUUUUUU
+
+      Synchronous negotiation to Ultra speed is enabled for target devices 0
+      and 4 through 15, to Fast speed for target device 1, to Slow speed for
+      target device 2, and is not permitted to target device 3.  The host
+      adapter's SCSI ID is represented by the "#".
+
+    The status of Wide Negotiation, Disconnect/Reconnect, and Tagged Queuing
+    are reported as "Enabled", Disabled", or a sequence of "Y" and "N" letters.
+
+    The Error Recovery option is reported as "Default", "Hard Reset",
+    "Bus Device Reset", "None" or a sequence of "D", "H", "B", and "N" letters.
+
+o Performance Features
+
+  BusLogic SCSI Host Adapters directly implement SCSI-2 Tagged Queuing, and so
+  support has been included in the driver to utilize tagged queuing with any
+  target devices that report having the tagged queuing capability.  Tagged
+  queuing allows for multiple outstanding commands to be issued to each target
+  device or logical unit, and can improve I/O performance substantially.  In
+  addition, BusLogic's Strict Round Robin Mode is used to optimize host adapter
+  performance, and scatter/gather I/O can support as many segments as can be
+  effectively utilized by the Linux I/O subsystem.  Control over the use of
+  tagged queuing for each target device as well as individual selection of the
+  tagged queue depth is available through driver options provided on the kernel
+  command line or at module initialization time.  By default, the queue depth
+  is determined automatically based on the host adapter's total queue depth and
+  the number, type, speed, and capabilities of the target devices found.  In
+  addition, tagged queuing is automatically disabled whenever the host adapter
+  firmware version is known not to implement it correctly, or whenever a tagged
+  queue depth of 1 is selected.  Tagged queuing is also disabled for individual
+  target devices if disconnect/reconnect is disabled for that device.
+
+o Robustness Features
+
+  The driver implements extensive error recovery procedures.  When the higher
+  level parts of the SCSI subsystem request that a timed out command be reset,
+  a selection is made between a full host adapter hard reset and SCSI bus reset
+  versus sending a bus device reset message to the individual target device
+  based on the recommendation of the SCSI subsystem.  Error recovery strategies
+  are selectable through driver options individually for each target device,
+  and also include sending a bus device reset to the specific target device
+  associated with the command being reset, as well as suppressing error
+  recovery entirely to avoid perturbing an improperly functioning device.  If
+  the bus device reset error recovery strategy is selected and sending a bus
+  device reset does not restore correct operation, the next command that is
+  reset will force a full host adapter hard reset and SCSI bus reset.  SCSI bus
+  resets caused by other devices and detected by the host adapter are also
+  handled by issuing a soft reset to the host adapter and re-initialization.
+  Finally, if tagged queuing is active and more than one command reset occurs
+  in a 10 minute interval, or if a command reset occurs within the first 10
+  minutes of operation, then tagged queuing will be disabled for that target
+  device.  These error recovery options improve overall system robustness by
+  preventing individual errant devices from causing the system as a whole to
+  lock up or crash, and thereby allowing a clean shutdown and restart after the
+  offending component is removed.
+
+o PCI Configuration Support
+
+  On PCI systems running kernels compiled with PCI BIOS support enabled, this
+  driver will interrogate the PCI configuration space and use the I/O port
+  addresses assigned by the system BIOS, rather than the ISA compatible I/O
+  port addresses.  The ISA compatible I/O port address is then disabled by the
+  driver.  On PCI systems it is also recommended that the AutoSCSI utility be
+  used to disable the ISA compatible I/O port entirely as it is not necessary.
+  The ISA compatible I/O port is disabled by default on the BT-948/958/958D.
+
+o /proc File System Support
+
+  Copies of the host adapter configuration information together with updated
+  data transfer and error recovery statistics are available through the
+  /proc/scsi/BusLogic/<N> interface.
+
+o Shared Interrupts Support
+
+  On systems that support shared interrupts, any number of BusLogic Host
+  Adapters may share the same interrupt request channel.
+
+
+			    SUPPORTED HOST ADAPTERS
+
+The following list comprises the supported BusLogic SCSI Host Adapters as of
+the date of this document.  It is recommended that anyone purchasing a BusLogic
+Host Adapter not in the following table contact the author beforehand to verify
+that it is or will be supported.
+
+FlashPoint Series PCI Host Adapters:
+
+FlashPoint LT (BT-930)	Ultra SCSI-3
+FlashPoint LT (BT-930R)	Ultra SCSI-3 with RAIDPlus
+FlashPoint LT (BT-920)	Ultra SCSI-3 (BT-930 without BIOS)
+FlashPoint DL (BT-932)	Dual Channel Ultra SCSI-3
+FlashPoint DL (BT-932R)	Dual Channel Ultra SCSI-3 with RAIDPlus
+FlashPoint LW (BT-950)	Wide Ultra SCSI-3
+FlashPoint LW (BT-950R)	Wide Ultra SCSI-3 with RAIDPlus
+FlashPoint DW (BT-952)	Dual Channel Wide Ultra SCSI-3
+FlashPoint DW (BT-952R)	Dual Channel Wide Ultra SCSI-3 with RAIDPlus
+
+MultiMaster "W" Series Host Adapters:
+
+BT-948	    PCI		Ultra SCSI-3
+BT-958	    PCI		Wide Ultra SCSI-3
+BT-958D	    PCI		Wide Differential Ultra SCSI-3
+
+MultiMaster "C" Series Host Adapters:
+
+BT-946C	    PCI		Fast SCSI-2
+BT-956C	    PCI		Wide Fast SCSI-2
+BT-956CD    PCI		Wide Differential Fast SCSI-2
+BT-445C	    VLB		Fast SCSI-2
+BT-747C	    EISA	Fast SCSI-2
+BT-757C	    EISA	Wide Fast SCSI-2
+BT-757CD    EISA	Wide Differential Fast SCSI-2
+BT-545C	    ISA		Fast SCSI-2
+BT-540CF    ISA		Fast SCSI-2
+
+MultiMaster "S" Series Host Adapters:
+
+BT-445S	    VLB		Fast SCSI-2
+BT-747S	    EISA	Fast SCSI-2
+BT-747D	    EISA	Differential Fast SCSI-2
+BT-757S	    EISA	Wide Fast SCSI-2
+BT-757D	    EISA	Wide Differential Fast SCSI-2
+BT-545S	    ISA		Fast SCSI-2
+BT-542D	    ISA		Differential Fast SCSI-2
+BT-742A	    EISA	SCSI-2 (742A revision H)
+BT-542B	    ISA		SCSI-2 (542B revision H)
+
+MultiMaster "A" Series Host Adapters:
+
+BT-742A	    EISA	SCSI-2 (742A revisions A - G)
+BT-542B	    ISA		SCSI-2 (542B revisions A - G)
+
+AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also
+supported by this driver.
+
+BusLogic SCSI Host Adapters are available packaged both as bare boards and as
+retail kits.  The BT- model numbers above refer to the bare board packaging.
+The retail kit model numbers are found by replacing BT- with KT- in the above
+list.  The retail kit includes the bare board and manual as well as cabling and
+driver media and documentation that are not provided with bare boards.
+
+
+			 FLASHPOINT INSTALLATION NOTES
+
+o RAIDPlus Support
+
+  FlashPoint Host Adapters now include RAIDPlus, Mylex's bootable software
+  RAID.  RAIDPlus is not supported on Linux, and there are no plans to support
+  it.  The MD driver in Linux 2.0 provides for concatenation (LINEAR) and
+  striping (RAID-0), and support for mirroring (RAID-1), fixed parity (RAID-4),
+  and distributed parity (RAID-5) is available separately.  The built-in Linux
+  RAID support is generally more flexible and is expected to perform better
+  than RAIDPlus, so there is little impetus to include RAIDPlus support in the
+  BusLogic driver.
+
+o Enabling UltraSCSI Transfers
+
+  FlashPoint Host Adapters ship with their configuration set to "Factory
+  Default" settings that are conservative and do not allow for UltraSCSI speed
+  to be negotiated.  This results in fewer problems when these host adapters
+  are installed in systems with cabling or termination that is not sufficient
+  for UltraSCSI operation, or where existing SCSI devices do not properly
+  respond to synchronous transfer negotiation for UltraSCSI speed.  AutoSCSI
+  may be used to load "Optimum Performance" settings which allow UltraSCSI
+  speed to be negotiated with all devices, or UltraSCSI speed can be enabled on
+  an individual basis.  It is recommended that SCAM be manually disabled after
+  the "Optimum Performance" settings are loaded.
+
+
+		      BT-948/958/958D INSTALLATION NOTES
+
+The BT-948/958/958D PCI Ultra SCSI Host Adapters have some features which may
+require attention in some circumstances when installing Linux.
+
+o PCI I/O Port Assignments
+
+  When configured to factory default settings, the BT-948/958/958D will only
+  recognize the PCI I/O port assignments made by the motherboard's PCI BIOS.
+  The BT-948/958/958D will not respond to any of the ISA compatible I/O ports
+  that previous BusLogic SCSI Host Adapters respond to.  This driver supports
+  the PCI I/O port assignments, so this is the preferred configuration.
+  However, if the obsolete BusLogic driver must be used for any reason, such as
+  a Linux distribution that does not yet use this driver in its boot kernel,
+  BusLogic has provided an AutoSCSI configuration option to enable a legacy ISA
+  compatible I/O port.
+
+  To enable this backward compatibility option, invoke the AutoSCSI utility via
+  Ctrl-B at system startup and select "Adapter Configuration", "View/Modify
+  Configuration", and then change the "ISA Compatible Port" setting from
+  "Disable" to "Primary" or "Alternate".  Once this driver has been installed,
+  the "ISA Compatible Port" option should be set back to "Disable" to avoid
+  possible future I/O port conflicts.  The older BT-946C/956C/956CD also have
+  this configuration option, but the factory default setting is "Primary".
+
+o PCI Slot Scanning Order
+
+  In systems with multiple BusLogic PCI Host Adapters, the order in which the
+  PCI slots are scanned may appear reversed with the BT-948/958/958D as
+  compared to the BT-946C/956C/956CD.  For booting from a SCSI disk to work
+  correctly, it is necessary that the host adapter's BIOS and the kernel agree
+  on which disk is the boot device, which requires that they recognize the PCI
+  host adapters in the same order.  The motherboard's PCI BIOS provides a
+  standard way of enumerating the PCI host adapters, which is used by the Linux
+  kernel.  Some PCI BIOS implementations enumerate the PCI slots in order of
+  increasing bus number and device number, while others do so in the opposite
+  direction.
+
+  Unfortunately, Microsoft decided that Windows 95 would always enumerate the
+  PCI slots in order of increasing bus number and device number regardless of
+  the PCI BIOS enumeration, and requires that their scheme be supported by the
+  host adapter's BIOS to receive Windows 95 certification.  Therefore, the
+  factory default settings of the BT-948/958/958D enumerate the host adapters
+  by increasing bus number and device number.  To disable this feature, invoke
+  the AutoSCSI utility via Ctrl-B at system startup and select "Adapter
+  Configuration", "View/Modify Configuration", press Ctrl-F10, and then change
+  the "Use Bus And Device # For PCI Scanning Seq." option to OFF.
+
+  This driver will interrogate the setting of the PCI Scanning Sequence option
+  so as to recognize the host adapters in the same order as they are enumerated
+  by the host adapter's BIOS.
+
+o Enabling UltraSCSI Transfers
+
+  The BT-948/958/958D ship with their configuration set to "Factory Default"
+  settings that are conservative and do not allow for UltraSCSI speed to be
+  negotiated.  This results in fewer problems when these host adapters are
+  installed in systems with cabling or termination that is not sufficient for
+  UltraSCSI operation, or where existing SCSI devices do not properly respond
+  to synchronous transfer negotiation for UltraSCSI speed.  AutoSCSI may be
+  used to load "Optimum Performance" settings which allow UltraSCSI speed to be
+  negotiated with all devices, or UltraSCSI speed can be enabled on an
+  individual basis.  It is recommended that SCAM be manually disabled after the
+  "Optimum Performance" settings are loaded.
+
+
+				DRIVER OPTIONS
+
+BusLogic Driver Options may be specified either via the Linux Kernel Command
+Line or via the Loadable Kernel Module Installation Facility.  Driver Options
+for multiple host adapters may be specified either by separating the option
+strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
+command line.  Individual option specifications for a single host adapter are
+separated by commas.  The Probing and Debugging Options apply to all host
+adapters whereas the remaining options apply individually only to the
+selected host adapter.
+
+The BusLogic Driver Probing Options comprise the following:
+
+IO:<integer>
+
+  The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
+  MultiMaster Host Adapter.  If neither "IO:" nor "NoProbeISA" options are
+  specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
+  will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134).  Multiple
+  "IO:" options may be specified to precisely determine the I/O Addresses to
+  be probed, but the probe order will always follow the standard list.
+
+NoProbe
+
+  The "NoProbe" option disables all probing and therefore no BusLogic Host
+  Adapters will be detected.
+
+NoProbeISA
+
+  The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
+  Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
+  will be detected.
+
+NoProbePCI
+
+  The "NoProbePCI" options disables the interrogation of PCI Configuration
+  Space and therefore only ISA Multimaster Host Adapters will be detected, as
+  well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
+  Port set to "Primary" or "Alternate".
+
+NoSortPCI
+
+  The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
+  enumerated in the order provided by the PCI BIOS, ignoring any setting of
+  the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
+
+MultiMasterFirst
+
+  The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
+  before FlashPoint Host Adapters.  By default, if both FlashPoint and PCI
+  MultiMaster Host Adapters are present, this driver will probe for
+  FlashPoint Host Adapters first unless the BIOS primary disk is controlled
+  by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
+  Adapters will be probed first.
+
+FlashPointFirst
+
+  The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
+  before MultiMaster Host Adapters.
+
+The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
+the Queue Depth and whether Tagged Queuing is permitted for each Target
+Device (assuming that the Target Device supports Tagged Queuing).  The Queue
+Depth is the number of SCSI Commands that are allowed to be concurrently
+presented for execution (either to the Host Adapter or Target Device).  Note
+that explicitly enabling Tagged Queuing may lead to problems; the option to
+enable or disable Tagged Queuing is provided primarily to allow disabling
+Tagged Queuing on Target Devices that do not implement it correctly.  The
+following options are available:
+
+QueueDepth:<integer>
+
+  The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
+  Target Devices that support Tagged Queuing, as well as the maximum Queue
+  Depth for devices that do not support Tagged Queuing.  If no Queue Depth
+  option is provided, the Queue Depth will be determined automatically based
+  on the Host Adapter's Total Queue Depth and the number, type, speed, and
+  capabilities of the detected Target Devices.  For Host Adapters that
+  require ISA Bounce Buffers, the Queue Depth is automatically set by default
+  to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
+  excessive preallocation of DMA Bounce Buffer memory.  Target Devices that
+  do not support Tagged Queuing always have their Queue Depth set to
+  BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
+  lower Queue Depth option is provided.  A Queue Depth of 1 automatically
+  disables Tagged Queuing.
+
+QueueDepth:[<integer>,<integer>...]
+
+  The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
+  individually for each Target Device.  If an <integer> is omitted, the
+  associated Target Device will have its Queue Depth selected automatically.
+
+TaggedQueuing:Default
+
+  The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
+  based on the firmware version of the BusLogic Host Adapter and based on
+  whether the Queue Depth allows queuing multiple commands.
+
+TaggedQueuing:Enable
+
+  The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
+  all Target Devices on this Host Adapter, overriding any limitation that
+  would otherwise be imposed based on the Host Adapter firmware version.
+
+TaggedQueuing:Disable
+
+  The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
+  for all Target Devices on this Host Adapter.
+
+TaggedQueuing:<Target-Spec>
+
+  The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
+  Tagged Queuing individually for each Target Device.  <Target-Spec> is a
+  sequence of "Y", "N", and "X" characters.  "Y" enables Tagged Queuing, "N"
+  disables Tagged Queuing, and "X" accepts the default based on the firmware
+  version.  The first character refers to Target Device 0, the second to
+  Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
+  does not cover all the Target Devices, unspecified characters are assumed
+  to be "X".
+
+The BusLogic Driver Error Recovery Option allows for explicitly specifying
+the Error Recovery action to be performed when BusLogic_ResetCommand is
+called due to a SCSI Command failing to complete successfully.  The following
+options are available:
+
+ErrorRecovery:Default
+
+  The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
+  Reset and Bus Device Reset options based on the recommendation of the SCSI
+  Subsystem.
+
+ErrorRecovery:HardReset
+
+  The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
+  Adapter Hard Reset which also causes a SCSI Bus Reset.
+
+ErrorRecovery:BusDeviceReset
+
+  The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
+  a Bus Device Reset message to the individual Target Device causing the
+  error.  If Error Recovery is again initiated for this Target Device and no
+  SCSI Command to this Target Device has completed successfully since the Bus
+  Device Reset message was sent, then a Hard Reset will be attempted.
+
+ErrorRecovery:None
+
+  The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
+  This option should only be selected if a SCSI Bus Reset or Bus Device Reset
+  will cause the Target Device or a critical operation to suffer a complete
+  and unrecoverable failure.
+
+ErrorRecovery:<Target-Spec>
+
+  The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
+  Error Recovery individually for each Target Device.  <Target-Spec> is a
+  sequence of "D", "H", "B", and "N" characters.  "D" selects Default, "H"
+  selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
+  The first character refers to Target Device 0, the second to Target Device
+  1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
+  cover all the possible Target Devices, unspecified characters are assumed
+  to be "D".
+
+The BusLogic Driver Miscellaneous Options comprise the following:
+
+BusSettleTime:<seconds>
+
+  The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
+  seconds.  The Bus Settle Time is the amount of time to wait between a Host
+  Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
+  Commands.  If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
+
+InhibitTargetInquiry
+
+  The "InhibitTargetInquiry" option inhibits the execution of an Inquire
+  Target Devices or Inquire Installed Devices command on MultiMaster Host
+  Adapters.  This may be necessary with some older Target Devices that do not
+  respond correctly when Logical Units above 0 are addressed.
+
+The BusLogic Driver Debugging Options comprise the following:
+
+TraceProbe
+
+  The "TraceProbe" option enables tracing of Host Adapter Probing.
+
+TraceHardwareReset
+
+  The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
+  Reset.
+
+TraceConfiguration
+
+  The "TraceConfiguration" option enables tracing of Host Adapter
+  Configuration.
+
+TraceErrors
+
+  The "TraceErrors" option enables tracing of SCSI Commands that return an
+  error from the Target Device.  The CDB and Sense Data will be printed for
+  each SCSI Command that fails.
+
+Debug
+
+  The "Debug" option enables all debugging options.
+
+The following examples demonstrate setting the Queue Depth for Target Devices
+1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
+Devices on the second host adapter to 31, and the Bus Settle Time on the
+second host adapter to 30 seconds.
+
+Linux Kernel Command Line:
+
+  linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
+
+LILO Linux Boot Loader (in /etc/lilo.conf):
+
+  append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
+
+INSMOD Loadable Kernel Module Installation Facility:
+
+  insmod BusLogic.o \
+      'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
+
+NOTE: Module Utilities 2.1.71 or later is required for correct parsing
+      of driver options containing commas.
+
+
+			      DRIVER INSTALLATION
+
+This distribution was prepared for Linux kernel version 2.0.35, but should be
+compatible with 2.0.4 or any later 2.0 series kernel.
+
+To install the new BusLogic SCSI driver, you may use the following commands,
+replacing "/usr/src" with wherever you keep your Linux kernel source tree:
+
+  cd /usr/src
+  tar -xvzf BusLogic-2.0.15.tar.gz
+  mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi
+  patch -p0 < BusLogic.patch (only for 2.0.33 and below)
+  cd linux
+  make config
+  make depend
+  make zImage
+
+Then install "arch/i386/boot/zImage" as your standard kernel, run lilo if
+appropriate, and reboot.
+
+
+		      BUSLOGIC ANNOUNCEMENTS MAILING LIST
+
+The BusLogic Announcements Mailing List provides a forum for informing Linux
+users of new driver releases and other announcements regarding Linux support
+for BusLogic SCSI Host Adapters.  To join the mailing list, send a message to
+"buslogic-announce-request@dandelion.com" with the line "subscribe" in the
+message body.
diff -Nru a/Documentation/scsi/ChangeLog b/Documentation/scsi/ChangeLog
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ChangeLog	Sun Nov 17 20:30:12 2002
@@ -0,0 +1,2023 @@
+Sat Jan 18 15:51:45 1997  Richard Henderson  <rth@tamu.edu>
+
+	* Don't play with usage_count directly, instead hand around
+	the module header and use the module macros.
+
+Fri May 17 00:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
+
+	* BusLogic Driver Version 2.0.3 Released.
+
+Tue Apr 16 21:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
+
+	* BusLogic Driver Version 1.3.2 Released.
+
+Sun Dec 31 23:26:00 1995  Leonard N. Zubkoff <lnz@dandelion.com>
+
+	* BusLogic Driver Version 1.3.1 Released.
+
+Fri Nov 10 15:29:49 1995  Leonard N. Zubkoff <lnz@dandelion.com>
+
+	* Released new BusLogic driver.
+
+Wed Aug  9 22:37:04 1995  Andries Brouwer  <aeb@cwi.nl>
+
+	As a preparation for new device code, separated the various
+	functions the request->dev field had into the device proper,
+	request->rq_dev and a status field request->rq_status.
+
+	The 2nd argument of bios_param is now a kdev_t.
+
+Wed Jul 19 10:43:15 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+        * scsi.c (scsi_proc_info): /proc/scsi/scsi now also lists all
+	attached devices.
+
+	* scsi_proc.c (proc_print_scsidevice): Added. Used by scsi.c and
+	eata_dma_proc.c to produce some device info for /proc/scsi.
+
+	* eata_dma.c (eata_queue)(eata_int_handler)(eata_scsi_done):
+	Changed handling of internal SCSI commands send to the HBA.
+
+
+Wed Jul 19 10:09:17 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.11 released.
+
+	* eata_dma.c (eata_queue)(eata_int_handler): Added code to do
+	command latency measurements if requested by root through
+	/proc/scsi interface.
+	Throughout Use HZ constant for time references.
+
+	* eata_pio.c: Use HZ constant for time references.
+
+	* aic7xxx.c, aic7xxx.h, aic7xxx_asm.c: Changed copyright from BSD
+	to GNU style.
+
+	* scsi.h: Added READ_12 command opcode constant
+
+Wed Jul 19 09:25:30 1995  Michael Neuffer <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.10 released.
+
+	* scsi_proc.c (dispatch_scsi_info): Removed unused variable.
+
+Wed Jul 19 09:25:30 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.9 released.
+
+	* scsi.c Blacklist concept expanded to 'support' more device
+	deficiencies. blacklist[] renamed to device_list[]
+	(scan_scsis): Code cleanup.
+
+	* scsi_debug.c (scsi_debug_proc_info): Added support to control
+	device lockup simulation via /proc/scsi interface.
+
+
+Wed Jul 19 09:22:34 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.7 released.
+
+	* scsi_proc.c: Fixed a number of bugs in directory handling
+
+Wed Jul 19 09:18:28 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.5 released.
+
+	* Native wide, multichannel and /proc/scsi support now in official
+	kernel distribution.
+
+        * scsi.c/h, hosts.c/h et al reindented to increase readability
+	(especially on 80 column wide terminals).
+
+	* scsi.c, scsi_proc.c, ../../fs/proc/inode.c: Added
+	/proc/scsi/scsi which allows root to scan for hotplugged devices.
+
+	* scsi.c (scsi_proc_info): Added, to support /proc/scsi/scsi.
+	(scan_scsis): Added some 'spaghetti' code to allow scanning for
+	single devices.
+	
+
+Thu Jun 20 15:20:27 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+        * proc.c: Renamed to scsi_proc.c
+
+Mon Jun 12 20:32:45 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* Linux 1.3.0 released.
+
+Mon May 15 19:33:14 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* scsi.c: Added native multichannel and wide scsi support.
+
+	* proc.c (dispatch_scsi_info) (build_proc_dir_hba_entries):
+	Updated /proc/scsi interface.
+
+Thu May  4 17:58:48 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
+
+	* sd.c (requeue_sd_request): Zero out the scatterlist only if
+	scsi_malloc returned memory for it.
+
+	* eata_dma.c (register_HBA) (eata_queue): Add support for
+	large scatter/gather tables and set use_clustering accordingly
+
+	* hosts.c: Make use_clustering changeable in the Scsi_Host structure.
+
+Wed Apr 12 15:25:52 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.2.5 released.
+
+	* buslogic.c: Update to version 1.15 (From Leonard N. Zubkoff).
+	Fixed interrupt routine to avoid races when handling multiple
+	complete commands per interrupt.  Seems to come up with faster
+	cards.
+
+	* eata_dma.c: Update to 2.3.5r. Modularize. Improved error handling
+        throughout and fixed bug interrupt routine which resulted in shifted
+        status bytes. Added blink LED state checks for ISA and EISA HBAs.
+        Memory management bug seems to have disappeared ==> increasing
+        C_P_L_CURRENT_MAX to 16 for now. Decreasing C_P_L_DIV to 3 for
+        performance reasons.
+
+	* scsi.c: If we get a FMK, EOM, or ILI when attempting to scan
+	the bus, assume that it was just noise on the bus, and ignore
+	the device.
+
+	* scsi.h: Update and add a bunch of missing commands which we
+	were never using.
+
+	* sd.c: Use restore_flags in do_sd_request - this may result in
+	latency conditions, but it gets rid of races and crashes.
+	Do not save flags again when searching for a second command to
+	queue.
+
+	* st.c: Use bytes, not STP->buffer->buffer_size when reading
+	from tape.
+
+
+Tue Apr  4 09:42:08 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.2.4 released.
+
+	* st.c: Fix typo - restoring wrong flags.
+
+Wed Mar 29 06:55:12 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.2.3 released.
+
+	* st.c: Perform some waiting operations with interrupts off.
+	Is this correct???
+
+Wed Mar 22 10:34:26 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.2.2 released.
+
+	* aha152x.c: Modularize.  Add support for PCMCIA.
+
+	* eata.c: Update to version 2.0.  Fixed bug preventing media
+	detection.  If scsi_register_host returns NULL, fail gracefully.
+
+	* scsi.c: Detect as NEC (for photo-cd purposes) for the 84
+	and 25 models as "NEC_OLDCDR".
+
+	* scsi.h: Add define for NEC_OLDCDR
+
+	* sr.c: Add handling for NEC_OLDCDR.  Treat as unknown.
+
+	* u14-34f.c: Update to version 2.0.  Fixed same bug as in
+	eata.c.
+
+
+Mon Mar  6 11:11:20 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.2.0 released.  Yeah!!!
+
+	* Minor spelling/punctuation changes throughout.  Nothing
+	substantive.
+
+Mon Feb 20 21:33:03 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.95 released.
+
+	* qlogic.c: Update to version 0.41.
+
+	* seagate.c: Change some message to be more descriptive about what
+	we detected.
+
+	* sr.c: spelling/whitespace changes.
+
+Mon Feb 20 21:33:03 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.94 released.
+
+Mon Feb 20 08:57:17 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.93 released.
+
+	* hosts.h: Change io_port to long int from short.
+
+ 	* 53c7,8xx.c: crash on AEN fixed, SCSI reset is no longer a NOP,
+ 	  NULL pointer panic on odd UDCs fixed, two bugs in diagnostic output
+ 	  fixed, should initialize correctly if left running, now loadable,
+  	  new memory allocation, extraneous diagnostic output suppressed,
+ 	  splx() replaced with save/restore flags. [ Drew ]
+
+	* hosts.c, hosts.h, scsi_ioctl.c, sd.c, sd_ioctl.c, sg.c, sr.c,
+	sr_ioctl.c: Add special junk at end that Emacs will use for
+	formatting the file.
+
+	* qlogic.c: Update to v0.40a.  Improve parity handling.
+
+	* scsi.c: Add Hitachi DK312C to blacklist.  Change "};" to "}" in
+	many places.  Use scsi_init_malloc to get command block - may
+	need this to be dma compatible for some host adapters.
+	Restore interrupts after unregistering a host.
+
+	* sd.c: Use sti instead of restore flags - causes latency problems.
+
+	* seagate.c: Use controller_type to determine string used when
+	registering irq.
+
+	* sr.c: More photo-cd hacks to make sure we get the xa stuff right.
+	* sr.h, sr.c: Change is_xa to xa_flags field.
+
+	* st.c: Disable retries for write operations.
+
+Wed Feb 15 10:52:56 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.92 released.
+
+	* eata.c: Update to 1.17.
+
+	* eata_dma.c: Update to 2.31a. Add more support for /proc/scsi.
+        Continuing modularization. Less crashes because of the bug in the
+        memory management ==> increase C_P_L_CURRENT_MAX to 10
+        and decrease C_P_L_DIV to 4.
+
+	* hosts.c: If we remove last host registered, reuse host number.
+	When freeing memory from host being deregistered, free extra_bytes
+	too.
+
+	* scsi.c (scan_scsis): memset(SDpnt, 0) and set SCmd.device to SDpnt.
+	Change memory allocation to work around bugs in __get_dma_pages.
+	Do not free host if usage count is not zero (for modules).
+
+	* sr_ioctl.c: Increase IOCTL_TIMEOUT to 3000.
+
+	* st.c: Allow for ST_EXTRA_DEVS in st data structures.
+
+	* u14-34f.c: Update to 1.17.
+
+Thu Feb  9 10:11:16 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.91 released.
+
+	* eata.c: Update to 1.16.  Use wish_block instead of host->block.
+
+	* hosts.c: Initialize wish_block to 0.
+
+	* hosts.h: Add wish_block.
+
+	* scsi.c: Use wish_block as indicator that the host should be added
+	to block list.
+
+	* sg.c: Add SG_EXTRA_DEVS to number of slots.
+
+	* u14-34f.c: Use wish_block.
+
+Tue Feb  7 11:46:04 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.90 released.
+
+	* eata.c: Change naming from eata_* to eata2x_*.  Now at vers 1.15.
+	Update interrupt handler to take pt_regs as arg.  Allow blocking
+	even if loaded as module.  Initialize target_time_out array.
+	Do not put sti(); in timing loop.
+
+	* hosts.c: Do not reuse host numbers.
+	Use scsi_make_blocked_list to generate blocking list.
+
+	* script_asm.pl:  Beats me.  Don't know perl.  Something to do with
+	phase index.
+
+	* scsi.c (scsi_make_blocked_list): New function - code copied from
+	hosts.c.
+
+	* scsi.c: Update code to disable photo CD for Toshiba cdroms.
+	Use just manufacturer name, not model number.
+
+	* sr.c: Fix setting density for Toshiba drives.
+
+	* u14-34f.c: Clear target_time_out array during reset.
+
+Wed Feb  1 09:20:45 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.89 released.
+
+	* Makefile, u14-34f.c: Modularize.
+
+	* Makefile, eata.c: Modularize.  Now version 1.14
+
+	* NCR5380.c: Update interrupt handler with new arglist.  Minor
+	cleanups.
+
+	* eata_dma.c: Begin to modularize.  Add hooks for /proc/scsi.
+	New version 2.3.0a. Add code in interrupt handler to allow
+        certain CDROM drivers to be detected which return a
+        CHECK_CONDITION during SCSI bus scan. Add opcode check to get
+        all DATA IN and DATA OUT phases right. Utilize HBA_interpret flag.
+	Improvements in HBA identification. Various other minor stuff.
+
+	* hosts.c: Initialize ->dma_channel and ->io_port when registering
+	a new host.
+
+	* qlogic.c: Modularize and add PCMCIA support.
+
+	* scsi.c: Add Hitachi to blacklist.
+
+	* scsi.c: Change default to no lun scan (too many problem devices).
+
+	* scsi.h: Define QUEUE_FULL condition.
+
+	* sd.c: Do not check for non-existent partition until after
+	new media check.
+
+	* sg.c: Undo previous change which was wrong.
+
+	* sr_ioctl.c: Increase IOCTL_TIMEOUT to 2000.
+
+	* st.c: Patches from Kai - improve filemark handling.
+
+Tue Jan 31 17:32:12 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.88 released.
+
+	* Throughout - spelling/grammar fixups.
+
+	* scsi.c: Make sure that all buffers are 16 byte aligned - some
+	drivers (buslogic) need this.
+
+	* scsi.c (scan_scsis): Remove message printed.
+
+	* scsi.c (scsi_init): Move message here.
+
+Mon Jan 30 06:40:25 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.87 released.
+
+	* sr.c: Photo-cd related changes. (Gerd Knorr??).
+
+	* st.c: Changes from Kai related to EOM detection.
+
+Mon Jan 23 23:53:10 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.86 released.
+
+	* 53c7,8xx.h: Change SG size to 127.
+
+	* eata_dma: Update to version 2.10i. Remove bug in the registration
+        of multiple HBAs and channels. Minor other improvements and stylistic
+        changes.
+
+	* scsi.c: Test for Toshiba XM-3401TA and exclude from detection
+	as toshiba drive - photo cd does not work with this drive.
+
+	* sr.c:  Update photocd code.
+
+Mon Jan 23 23:53:10 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.85 released.
+
+	* st.c, st_ioctl.c, sg.c, sd_ioctl.c, scsi_ioctl.c, hosts.c:
+	include linux/mm.h
+
+	* qlogic.c, buslogic.c, aha1542.c: Include linux/module.h.
+
+Sun Jan 22 22:08:46 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.84 released.
+
+	* Makefile: Support for loadable QLOGIC boards.
+
+	* aha152x.c: Update to version 1.8 from Juergen.
+
+	* eata_dma.c: Update from Michael Neuffer.
+        Remove hard limit of 2 commands per lun and make it better
+        configurable. Improvements in HBA identification.
+
+	* in2000.c: Fix biosparam to support large disks.
+
+	* qlogic.c: Minor changes (change sti -> restore_flags).
+
+Wed Jan 18 23:33:09 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.83 released.
+
+	* aha1542.c(aha1542_intr_handle): Use arguments handed down to find
+	which irq.
+
+	* buslogic.c: Likewise.
+
+	* eata_dma.c: Use min of 2 cmd_per_lun for OCS_enabled boards.
+
+	* scsi.c: Make RECOVERED_ERROR a SUGGEST_IS_OK.
+
+	* sd.c: Fail if we are opening a non-existent partition.
+
+	* sr.c: Bump SR_TIMEOUT to 15000.
+	Do not probe for media size at boot time(hard on changers).
+	Flag device as needing sector size instead.
+
+	* sr_ioctl.c: Remove CDROMMULTISESSION_SYS ioctl.
+
+	* ultrastor.c: Fix bug in call to ultrastor_interrupt (wrong #args).
+
+Mon Jan 16 07:18:23 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.82 released.
+
+	Throughout.
+	- Change all interrupt handlers to accept new calling convention.
+	In particular, we now receive the irq number as one of the arguments.
+
+	* More minor spelling corrections in some of the new files.
+
+	* aha1542.c, buslogic.c: Clean up interrupt handler a little now
+	that we receive the irq as an arg.
+
+	* aha274x.c: s/snarf_region/request_region/
+
+	* eata.c: Update to version 1.12.   Fix some comments and display a
+	message if we cannot reserve the port addresses.
+
+	* u14-34f.c: Update to version 1.13.   Fix some comments and display a
+	message if we cannot reserve the port addresses.
+
+	* eata_dma.c: Define get_board_data function (send INQUIRY command).
+	Use to improve detection of variants of different DPT boards.  Change
+	version subnumber to "0g".
+
+	* fdomain.c:  Update to version 5.26.  Improve detection of some boards
+	repackaged by IBM.
+
+	* scsi.c (scsi_register_host): Change "name" to const char *.
+
+	* sr.c: Fix problem in set mode command for Toshiba drives.
+
+	* sr.c: Fix typo from patch 81.
+
+Fri Jan 13 12:54:46 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.81 released.  Codefreeze for 1.2 release announced.
+
+	Big changes here.
+
+	* eata_dma.*: New files from Michael Neuffer.
+	(neuffer@goofy.zdv.uni-mainz.de).  Should support
+	all eata/dpt cards.
+
+	* hosts.c, Makefile: Add eata_dma.
+
+	* README.st: Document MTEOM.
+
+	Patches from me (ERY) to finish support for low-level loadable scsi.
+	It now works, and is actually useful.
+
+	* Throughout - add new argument to scsi_init_malloc that takes an
+	additional parameter.  This is used as a priority to kmalloc,
+	and you can specify the GFP_DMA flag if you need DMA-able memory.
+
+	* Makefile: For source files that are loadable, always add name
+	to SCSI_SRCS.  Fill in modules: target.
+
+	* hosts.c:  Change next_host to next_scsi_host, and make global.
+	Print hosts after we have identified all of them.  Use info()
+	function if present, otherwise use name field.
+
+	* hosts.h: Change attach function to return int, not void.
+	Define number of device slots to allow for loadable devices.
+	Define tags to tell scsi module code what type of module we
+	are loading.
+
+	* scsi.c: Fix scan_scsis so that it can be run by a user process.
+	Do not use waiting loops - use up and down mechanism as long
+	as current != task[0].
+
+	* scsi.c(scan_scsis): Do not use stack variables for I/O - this
+	could be > 16Mb if we are loading a module at runtime (i.e. use
+	scsi_init_malloc to get some memory we know will be safe).
+
+	* scsi.c: Change dma freelist to be a set of pages.  This allows
+	us to dynamically adjust the size of the list by adding more pages
+	to the pagelist.  Fix scsi_malloc and scsi_free accordingly.
+
+	* scsi_module.c: Fix include.
+
+	* sd.c: Declare detach function.  Increment/decrement module usage
+	count as required.  Fix init functions to allow loaded devices.
+	Revalidate all new disks so we get the partition tables.  Define
+	detach function.
+
+	* sr.c: Likewise.
+
+	* sg.c: Declare detach function.  Allow attachment of devices on
+	loaded drivers.
+
+	* st.c: Declare detach function.  Increment/decrement module usage
+	count as required.
+
+Tue Jan 10 10:09:58 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.79 released.
+
+	Patch from some undetermined individual who needs to get a life :-).
+
+	* sr.c: Attacked by spelling bee...
+
+	Patches from Gerd Knorr:
+
+	* sr.c: make printk messages for photoCD a little more informative.
+
+	* sr_ioctl.c: Fix CDROMMULTISESSION_SYS ioctl.
+
+Mon Jan  9 10:01:37 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.78 released.
+
+	* Makefile: Add empty modules: target.
+
+	* Wheee.  Now change register_iomem to request_region.
+
+	* in2000.c: Bugfix - apparently this is the fix that we have
+	all been waiting for.  It fixes a problem whereby the driver
+	is not stable under heavy load.  Race condition and all that.
+	Patch from Peter Lu.
+
+Wed Jan  4 21:17:40 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.77 released.
+
+	* 53c7,8xx.c: Fix from Linus - emulate splx.
+
+	Throughout:
+
+		Change "snarf_region" with "register_iomem".
+
+	* scsi_module.c: New file.  Contains support for low-level loadable
+	  scsi drivers. [ERY].
+
+	* sd.c: More s/int/long/ changes.
+
+	* seagate.c: Explicitly include linux/config.h
+
+	* sg.c: Increment/decrement module usage count on open/close.
+
+	* sg.c: Be a bit more careful about the user not supplying enough
+	  information for a valid command.  Pass correct size down to
+	  scsi_do_cmd.
+
+	* sr.c:  More changes for Photo-CD.  This apparently breaks NEC drives.
+
+	* sr_ioctl.c:  Support CDROMMULTISESSION ioctl.
+
+
+Sun Jan  1 19:55:21 1995  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.76 released.
+
+	* constants.c: Add type cast in switch statement.
+
+	* scsi.c (scsi_free): Change datatype of "offset" to long.
+	  (scsi_malloc): Change a few more variables to long.  Who
+	  did this and why was it important?  64 bit machines?
+
+
+	Lots of changes to use save_state/restore_state instead of cli/sti.
+	Files changed include:
+
+	* aha1542.c:
+	* aha1740.c:
+	* buslogic.c:
+	* in2000.c:
+	* scsi.c:
+	* scsi_debug.c:
+	* sd.c:
+	* sr.c:
+	* st.c:
+
+Wed Dec 28 16:38:29 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.75 released.
+
+	* buslogic.c: Spelling fix.
+
+	* scsi.c: Add HP C1790A and C2500A scanjet to blacklist.
+
+	* scsi.c: Spelling fixup.
+
+	* sd.c: Add support for sd_hardsizes (hard sector sizes).
+
+	* ultrastor.c: Use save_flags/restore_flags instead of cli/sti.
+
+Fri Dec 23 13:36:25 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.74 released.
+
+	* README.st: Update from Kai Makisara.
+
+	* eata.c: New version from Dario - version 1.11.
+	  use scsicam bios_param routine.  Add support for 2011
+	  and 2021 boards.
+
+	* hosts.c: Add support for blocking.  Linked list automatically
+	  generated when shpnt->block is set.
+
+	* scsi.c: Add sankyo & HP scanjet to blacklist.  Add support for
+	  kicking things loose when we deadlock.
+
+	* scsi.c: Recognize scanners and processors in scan_scsis.
+
+	* scsi_ioctl.h: Increase timeout to 9 seconds.
+
+	* st.c: New version from Kai - add better support for backspace.
+
+	* u14-34f.c: New version from Dario.  Supports blocking.
+
+Wed Dec 14 14:46:30 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.73 released.
+
+	* buslogic.c: Update from Dave Gentzel.  Version 1.14.
+	  Add module related stuff.   More fault tolerant if out of
+	  DMA memory.
+
+	* fdomain.c: New version from Rik Faith - version 5.22.  Add support
+	  for ISA-200S SCSI adapter.
+
+	* hosts.c: Spelling.
+
+	* qlogic.c: Update to version 0.38a.  Add more support for PCMCIA.
+
+	* scsi.c: Mask device type with 0x1f during scan_scsis.
+	  Add support for deadlocking, err, make that getting out of
+	  deadlock situations that are created when we allow the user
+	  to limit requests to one host adapter at a time.
+
+	* scsi.c: Bugfix - pass pid, not SCpnt as second arg to
+	  scsi_times_out.
+
+	* scsi.c: Restore interrupt state to previous value instead of using
+	  cli/sti pairs.
+
+	* scsi.c: Add a bunch of module stuff (all commented out for now).
+
+	* scsi.c: Clean up scsi_dump_status.
+
+Tue Dec  6 12:34:20 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.72 released.
+
+	* sg.c: Bugfix - always use sg_free, since we might have big buff.
+
+Fri Dec  2 11:24:53 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.71 released.
+
+	* sg.c: Clear buff field when not in use.  Only call scsi_free if
+	non-null.
+
+	* scsi.h: Call wake_up(&wait_for_request) when done with a
+	command.
+
+	* scsi.c (scsi_times_out): Pass pid down so that we can protect
+	against race conditions.
+
+	* scsi.c (scsi_abort): Zero timeout field if we get the
+	NOT_RUNNING message back from low-level driver.
+
+
+	* scsi.c (scsi_done): Restore cmd_len, use_sg here.
+
+	* scsi.c (request_sense): Not here.
+
+	* hosts.h: Add new forbidden_addr, forbidden_size fields.  Who
+	added these and why????
+
+	* hosts.c (scsi_mem_init): Mark pages as reserved if they fall in
+	the forbidden regions.  I am not sure - I think this is so that
+	we can deal with boards that do incomplete decoding of their
+	address lines for the bios chips, but I am not entirely sure.
+
+	* buslogic.c: Set forbidden_addr stuff if using a buggy board.
+
+	* aha1740.c: Test for NULL pointer in SCtmp.  This should not
+	occur, but a nice message is better than a kernel segfault.
+
+	* 53c7,8xx.c: Add new PCI chip ID for 815.
+
+Fri Dec  2 11:24:53 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.70 released.
+
+	* ChangeLog, st.c: Spelling.
+
+Tue Nov 29 18:48:42 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.69 released.
+
+	* u14-34f.h: Non-functional change.  [Dario].
+
+	* u14-34f.c: Use block field in Scsi_Host to prevent commands from
+	being queued to more than one host at the same time (used when
+	motherboard does not deal with multiple bus-masters very well).
+	Only when SINGLE_HOST_OPERATIONS is defined.
+	Use new cmd_per_lun field.  [Dario]
+
+	* eata.c: Likewise.
+
+	* st.c: More changes from Kai.  Add ready flag to indicate drive
+	status.
+
+	* README.st: Document this.
+
+	* sr.c: Bugfix (do not subtract CD_BLOCK_OFFSET) for photo-cd
+	code.
+
+	* sg.c: Bugfix - fix problem where opcode is not correctly set up.
+
+	* seagate.[c,h]: Use #defines to set driver name.
+
+	* scsi_ioctl.c: Zero buffer before executing command.
+
+	* scsi.c: Use new cmd_per_lun field in Scsi_Hosts as appropriate.
+	Add Sony CDU55S to blacklist.
+
+	* hosts.h: Add new cmd_per_lun field to Scsi_Hosts.
+
+	* hosts.c: Initialize cmd_per_lun in Scsi_Hosts from template.
+
+	* buslogic.c: Use cmd_per_lun field - initialize to different
+	values depending upon bus type (i.e. use 1 if ISA, so we do not
+	hog memory).  Use other patches which got lost from 1.1.68.
+
+	* aha1542.c: Spelling.
+
+Tue Nov 29 15:43:50 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.68 released.
+
+	Add support for 12 byte vendor specific commands in scsi-generics,
+	more (i.e. the last mandatory) low-level changes to support
+	loadable modules, plus a few other changes people have requested
+	lately.  Changes by me (ERY) unless otherwise noted.  Spelling
+	changes appear from some unknown corner of the universe.
+
+	* Throughout: Change COMMAND_SIZE() to use SCpnt->cmd_len.
+
+	* Throughout: Change info() low level function to take a Scsi_Host
+	pointer.  This way the info function can return specific
+	information about the host in question, if desired.
+
+	* All low-level drivers: Add NULL in initializer for the
+	usage_count field added to Scsi_Host_Template.
+
+	* aha152x.[c,h]: Remove redundant info() function.
+
+	* aha1542.[c,h]: Likewise.
+
+	* aha1740.[c,h]: Likewise.
+
+	* aha274x.[c,h]: Likewise.
+
+	* eata.[c,h]: Likewise.
+
+	* pas16.[c,h]: Likewise.
+
+	* scsi_debug.[c,h]: Likewise.
+
+	* t128.[c,h]: Likewise.
+
+	* u14-34f.[c,h]: Likewise.
+
+	* ultrastor.[c,h]: Likewise.
+
+	* wd7000.[c,h]: Likewise.
+
+	* aha1542.c: Add support for command line options with lilo to set
+	DMA parameters, I/O port.  From Matt Aarnio.
+
+	* buslogic.[c,h]: New version (1.13) from Dave Gentzel.
+
+	* hosts.h: Add new field to Scsi_Hosts "block" to allow blocking
+	all I/O to certain other cards.  Helps prevent problems with some
+	ISA motherboards.
+
+	* hosts.h: Add usage_count to Scsi_Host_Template.
+
+	* hosts.h: Add n_io_port to Scsi_Host (used when releasing module).
+
+	* hosts.c: Initialize block field.
+
+	* in2000.c: Remove "static" declarations from exported functions.
+
+	* in2000.h: Likewise.
+
+	* scsi.c: Correctly set cmd_len field as required.  Save and
+	change setting when doing a request_sense, restore when done.
+	Move abort timeout message.  Fix panic in request_queueable to
+	print correct function name.
+
+	* scsi.c: When incrementing usage count, walk block linked list
+	for host, and or in SCSI_HOST_BLOCK bit.  When decrementing usage
+	count to 0, clear this bit to allow usage to continue, wake up
+	processes waiting.
+
+
+	* scsi_ioctl.c: If we have an info() function, call it, otherwise
+	if we have a "name" field, use it, else do nothing.
+
+	* sd.c, sr.c: Clear cmd_len field prior to each command we
+	generate.
+
+	* sd.h: Add "has_part_table" bit to rscsi_disks.
+
+	* sg.[c,h]: Add support for vendor specific 12 byte commands (i.e.
+	override command length in COMMAND_SIZE).
+
+	* sr.c: Bugfix from Gerd in photocd code.
+
+	* sr.c: Bugfix in get_sectorsize - always use scsi_malloc buffer -
+	we cannot guarantee that the stack is < 16Mb.
+
+Tue Nov 22 15:40:46 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.67 released.
+
+	* sr.c: Change spelling of manufactor to manufacturer.
+
+	* scsi.h: Likewise.
+
+	* scsi.c: Likewise.
+
+	* qlogic.c: Spelling corrections.
+
+	* in2000.h: Spelling corrections.
+
+	* in2000.c: Update from Bill Earnest, change from
+	jshiffle@netcom.com.  Support new bios versions.
+
+	* README.qlogic: Spelling correction.
+
+Tue Nov 22 15:40:46 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.66 released.
+
+	* u14-34f.c: Spelling corrections.
+
+	* sr.[h,c]: Add support for multi-session CDs from Gerd Knorr.
+
+	* scsi.h: Add manufactor field for keeping track of device
+	manufacturer.
+
+	* scsi.c: More spelling corrections.
+
+	* qlogic.h, qlogic.c, README.qlogic: New driver from Tom Zerucha.
+
+	* in2000.c, in2000.h: New driver from Brad McLean/Bill Earnest.
+
+	* fdomain.c: Spelling correction.
+
+	* eata.c: Spelling correction.
+
+Fri Nov 18 15:22:44 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.65 released.
+
+	* eata.h: Update version string to 1.08.00.
+
+	* eata.c: Set sg_tablesize correctly for DPT PM2012 boards.
+
+	* aha274x.seq: Spell checking.
+
+	* README.st: Likewise.
+
+	* README.aha274x: Likewise.
+
+	* ChangeLog: Likewise.
+
+Tue Nov 15 15:35:08 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.64 released.
+
+	* u14-34f.h: Update version number to 1.10.01.
+
+	* u14-34f.c: Use Scsi_Host can_queue variable instead of one from template.
+
+	* eata.[c,h]: New driver for DPT boards from Dario Ballabio.
+
+	* buslogic.c: Use can_queue field.
+
+Wed Nov 30 12:09:09 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.63 released.
+
+	* sd.c: Give I/O error if we attempt 512 byte I/O to a disk with
+	1024 byte sectors.
+
+	* scsicam.c: Make sure we do read from whole disk (mask off
+	partition).
+
+	* scsi.c: Use can_queue in Scsi_Host structure.
+	Fix panic message about invalid host.
+
+	* hosts.c: Initialize can_queue from template.
+
+	* hosts.h: Add can_queue to Scsi_Host structure.
+
+	* aha1740.c: Print out warning about NULL ecbptr.
+
+Fri Nov  4 12:40:30 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.62 released.
+
+	* fdomain.c: Update to version 5.20. (From Rik Faith).  Support
+	BIOS version 3.5.
+
+	* st.h: Add ST_EOD symbol.
+
+	* st.c: Patches from Kai Makisara - support additional densities,
+	add support for MTFSS, MTBSS, MTWSM commands.
+
+	* README.st: Update to document new commands.
+
+	* scsi.c: Add Mediavision CDR-H93MV to blacklist.
+
+Sat Oct 29 20:57:36 1994  Eric Youngdale  (eric@andante.aib.com)
+
+	* Linux 1.1.60 released.
+
+	* u14-34f.[c,h]: New driver from Dario Ballabio.
+
+	* aic7770.c, aha274x_seq.h, aha274x.seq, aha274x.h, aha274x.c,
+	README.aha274x: New files, new driver from John Aycock.
+
+
+Tue Oct 11 08:47:39 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.54 released.
+
+	* Add third PCI chip id.  [Drew]
+
+	* buslogic.c: Set BUSLOGIC_CMDLUN back to 1 [Eric].
+
+	* ultrastor.c: Fix asm directives for new GCC.
+
+	* sr.c, sd.c: Use new end_scsi_request function.
+
+	* scsi.h(end_scsi_request): Return pointer to block if still
+	active, else return NULL if inactive.  Fixes race condition.
+
+Sun Oct  9 20:23:14 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.53 released.
+
+	* scsi.c: Do not allocate dma bounce buffers if we have exactly
+	16Mb.
+
+Fri Sep  9 05:35:30 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.51 released.
+
+	* aha152x.c: Add support for disabling the parity check.  Update
+	to version 1.4. [Juergen].
+
+	* seagate.c: Tweak debugging message.
+
+Wed Aug 31 10:15:55 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.50 released.
+
+	* aha152x.c: Add eb800 for Vtech Platinum SMP boards. [Juergen].
+
+	* scsi.c: Add Quantum PD1225S to blacklist.
+
+Fri Aug 26 09:38:45 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.49 released.
+
+	* sd.c: Fix bug when we were deleting the wrong entry if we
+	get an unsupported sector size device.
+
+	* sr.c: Another spelling patch.
+
+Thu Aug 25 09:15:27 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.48 released.
+
+	* Throughout: Use new semantics for request_dma, as appropriate.
+
+	* sr.c: Print correct device number.
+
+Sun Aug 21 17:49:23 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.47 released.
+
+	* NCR5380.c: Add support for LIMIT_TRANSFERSIZE.
+
+	* constants.h: Add prototype for print_Scsi_Cmnd.
+
+	* pas16.c: Some more minor tweaks.  Test for Mediavision board.
+	Allow for disks > 1Gb.  [Drew??]
+
+	* sr.c: Set SCpnt->transfersize.
+
+Tue Aug 16 17:29:35 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.46 released.
+
+	* Throughout: More spelling fixups.
+
+	* buslogic.c: Add a few more fixups from Dave.  Disk translation
+	mainly.
+
+	* pas16.c: Add a few patches (Drew?).
+
+
+Thu Aug 11 20:45:15 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.44 released.
+
+	* hosts.c: Add type casts for scsi_init_malloc.
+
+	* scsicam.c: Add type cast.
+
+Wed Aug 10 19:23:01 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.43 released.
+
+	* Throughout: Spelling cleanups. [??]
+
+	* aha152x.c, NCR53*.c, fdomain.c, g_NCR5380.c, pas16.c, seagate.c,
+	 t128.c: Use request_irq, not irqaction. [??]
+
+	* aha1542.c: Move test for shost before we start to use shost.
+
+	* aha1542.c, aha1740.c, ultrastor.c, wd7000.c: Use new
+	calling sequence for request_irq.
+
+	* buslogic.c: Update from Dave Gentzel.
+
+Tue Aug  9 09:32:59 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.42 released.
+
+	* NCR5380.c: Change NCR5380_print_status to static.
+
+	* seagate.c: A few more bugfixes.  Only Drew knows what they are
+	for.
+
+	* ultrastor.c: Tweak some __asm__ directives so that it works
+	with newer compilers. [??]
+
+Sat Aug  6 21:29:36 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.40 released.
+
+	* NCR5380.c: Return SCSI_RESET_WAKEUP from reset function.
+
+	* aha1542.c: Reset mailbox status after a bus device reset.
+
+	* constants.c: Fix typo (;;).
+
+	* g_NCR5380.c:
+	* pas16.c:  Correct usage of NCR5380_init.
+
+	* scsi.c: Remove redundant (and unused variables).
+
+	* sd.c: Use memset to clear all of rscsi_disks before we use it.
+
+	* sg.c: Ditto, except for scsi_generics.
+
+	* sr.c: Ditto, except for scsi_CDs.
+
+	* st.c: Initialize STp->device.
+
+	* seagate.c: Fix bug. [Drew]
+
+Thu Aug  4 08:47:27 1994  Eric Youngdale  (eric@andante)
+
+	* Linux 1.1.39 released.
+
+	* Makefile: Fix typo in NCR53C7xx.
+
+	* st.c: Print correct number for device.
+
+Tue Aug  2 11:29:14 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.38 released.
+
+	Lots of changes in 1.1.38.  All from Drew unless otherwise noted.
+
+	* 53c7,8xx.c: New file from Drew.  PCI driver.
+
+	* 53c7,8xx.h: Likewise.
+
+	* 53c7,8xx.scr: Likewise.
+
+	* 53c8xx_d.h, 53c8xx_u.h, script_asm.pl: Likewise.
+
+	* scsicam.c: New file from Drew.  Read block 0 on the disk and
+	read the partition table.  Attempt to deduce the geometry from
+	the partition table if possible.  Only used by 53c[7,8]xx right
+	now, but could be used by any device for which we have no way
+	of identifying the geometry.
+
+	* sd.c: Use device letters instead of sd%d in a lot of messages.
+
+	* seagate.c: Fix bug that resulted in lockups with some devices.
+
+	* sr.c (sr_open): Return -EROFS, not -EACCES if we attempt to open
+	device for write.
+
+	* hosts.c, Makefile: Update for new driver.
+
+	* NCR5380.c, NCR5380.h, g_NCR5380.h: Update from Drew to support
+	53C400 chip.
+
+	* constants.c: Define CONST_CMND and CONST_MSG.  Other minor
+	cleanups along the way.  Improve handling of CONST_MSG.
+
+	* fdomain.c, fdomain.h: New version from Rik Faith.  Update to
+	5.18.  Should now support TMC-3260 PCI card with 18C30 chip.
+
+	* pas16.c: Update with new irq initialization.
+
+	* t128.c: Update with minor cleanups.
+
+	* scsi.c (scsi_pid): New variable - gives each command a unique
+	id. Add Quantum LPS5235S to blacklist.  Change in_scan to
+	in_scan_scsis and make global.
+
+	* scsi.h: Add some defines for extended message handling,
+	INITIATE/RELEASE_RECOVERY.  Add a few new fields to support sync
+	transfers.
+
+	* scsi_ioctl.h: Add ioctl to request synchronous transfers.
+
+
+Tue Jul 26 21:36:58 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.37 released.
+
+	* aha1542.c: Always call aha1542_mbenable, use new udelay
+	mechanism so we do not wait a long time if the board does not
+	implement this command.
+
+	* g_NCR5380.c: Remove #include <linux/config.h> and #if
+	defined(CONFIG_SCSI_*).
+
+	* seagate.c: Likewise.
+
+	Next round of changes to support loadable modules.  Getting closer
+	now, still not possible to do anything remotely usable.
+
+	hosts.c: Create a linked list of detected high level devices.
+	(scsi_register_device): New function to insert into this list.
+	(scsi_init): Call scsi_register_device for each of the known high
+	level drivers.
+
+	hosts.h: Add prototype for linked list header.  Add structure
+	definition for device template structure which defines the linked
+	list.
+
+	scsi.c: (scan_scsis): Use linked list instead of knowledge about
+	existing high level device drivers.
+	(scsi_dev_init): Use init functions for drivers on linked list
+	instead of explicit list to initialize and attach devices to high
+	level drivers.
+
+	scsi.h: Add new field "attached" to scsi_device - count of number
+	of high level devices attached.
+
+	sd.c, sr.c, sg.c, st.c: Adjust init/attach functions to use new
+	scheme.
+
+Sat Jul 23 13:03:17 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.35 released.
+
+	* ultrastor.c: Change constraint on asm() operand so that it works
+	with gcc 2.6.0.
+
+Thu Jul 21 10:37:39 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.33 released.
+
+	* sr.c(sr_open): Do not allow opens with write access.
+
+Mon Jul 18 09:51:22 1994 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.31 released.
+
+	* sd.c: Increase SD_TIMEOUT from 300 to 600.
+
+	* sr.c: Remove stray task_struct* variable that was no longer
+	used.
+
+	* sr_ioctl.c: Fix typo in up() call.
+
+Sun Jul 17 16:25:29 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.30 released.
+
+	* scsi.c (scan_scsis): Fix detection of some Toshiba CDROM drives
+	that report themselves as disk drives.
+
+	* (Throughout): Use request.sem instead of request.waiting.
+	Should fix swap problem with fdomain.
+
+Thu Jul 14 10:51:42 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.29 released.
+
+	* scsi.c (scan_scsis): Add new devices to end of linked list, not
+	to the beginning.
+
+	* scsi.h (SCSI_SLEEP): Remove brain dead hack to try to save
+	the task state before sleeping.
+
+Sat Jul  9 15:01:03 1994  Eric Youngdale  (eric@esp22)
+
+	More changes to eventually support loadable modules.  Mainly
+	we want to use linked lists instead of arrays because it is easier
+	to dynamically add and remove things this way.
+
+	Quite a bit more work is needed before loadable modules are
+	possible (and usable) with scsi, but this is most of the grunge
+	work.
+
+	* Linux 1.1.28 released.
+
+	* scsi.c, scsi.h (allocate_device, request_queueable): Change
+	argument from index into scsi_devices to a pointer to the
+	Scsi_Device struct.
+
+	* Throughout: Change all calls to allocate_device,
+	request_queueable to use new calling sequence.
+
+	* Throughout: Use SCpnt->device instead of
+	scsi_devices[SCpnt->index].  Ugh - the pointer was there all along
+	- much cleaner this way.
+
+	* scsi.c (scsi_init_malloc, scsi_free_malloc): New functions -
+	allow us to pretend that we have a working malloc when we
+	initialize.  Use this instead of passing memory_start, memory_end
+	around all over the place.
+
+	* scsi.h, st.c, sr.c, sd.c, sg.c: Change *_init1 functions to use
+	scsi_init_malloc, remove all arguments, no return value.
+
+	* scsi.h: Remove index field from Scsi_Device and Scsi_Cmnd
+	structs.
+
+	* scsi.c (scsi_dev_init): Set up for scsi_init_malloc.
+	(scan_scsis): Get SDpnt from scsi_init_malloc, and refresh
+	when we discover a device.  Free pointer before returning.
+	Change scsi_devices into a linked list.
+
+	* scsi.c (scan_scsis): Change to only scan one host.
+	(scsi_dev_init): Loop over all detected hosts, and scan them.
+
+	* hosts.c  (scsi_init_free): Change so that  number of extra bytes
+	is stored in struct, and we do not have to pass it each time.
+
+	* hosts.h: Change Scsi_Host_Template struct to include "next" and
+	"release" functions.  Initialize to NULL in all low level
+	adapters.
+
+	* hosts.c: Rename scsi_hosts to builtin_scsi_hosts, create linked
+	list scsi_hosts, linked together with the new "next" field.
+
+Wed Jul  6 05:45:02 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.25 released.
+
+	* aha152x.c: Changes from Juergen - cleanups and updates.
+
+	* sd.c, sr.c: Use new check_media_change and revalidate
+	file_operations fields.
+
+	* st.c, st.h: Add changes from Kai Makisara, dated Jun 22.
+
+	* hosts.h: Change SG_ALL back to 0xff.  Apparently soft error
+	in /dev/brain resulted in having this bumped up.
+	Change first parameter in bios_param function to be Disk * instead
+	of index into rscsi_disks.
+
+	* sd_ioctl.c: Pass pointer to rscsi_disks element instead of index
+	to array.
+
+	* sd.h: Add struct name "scsi_disk" to typedef for Scsi_Disk.
+
+	* scsi.c: Remove redundant Maxtor XT8760S from blacklist.
+	In scsi_reset, add printk when DEBUG defined.
+
+	* All low level drivers: Modify definitions of bios_param in
+	appropriate way.
+
+Thu Jun 16 10:31:59 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.20 released.
+
+	* scsi_ioctl.c: Only pass down the actual number of characters
+	required to scsi_do_cmd, not the one rounded up to a even number
+	of sectors.
+
+	* ultrastor.c: Changes from Caleb Epstein for 24f cards.  Support
+	larger SG lists.
+
+	* ultrastor.c: Changes from me - use scsi_register to register
+	host.  Add some consistency checking,
+
+Wed Jun  1 21:12:13 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.19 released.
+
+	* scsi.h: Add new return code for reset() function:
+	SCSI_RESET_PUNT.
+
+	* scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for
+	now.
+
+	* aha1542.c: If the command responsible for the reset is not
+	pending, return SCSI_RESET_PUNT.
+
+	* aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return
+	SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE.
+
+Tue May 31 19:36:01 1994  Eric Youngdale  (eric@esp22)
+
+	* buslogic.c: Do not print out message about "must be Adaptec"
+	if we have detected a buslogic card.  Print out a warning message
+	if we are configuring for >16Mb, since the 445S at board level
+	D or earlier does not work right.  The "D" level board can be made
+	to work by flipping an undocumented switch, but this is too subtle.
+
+    Changes based upon patches in Yggdrasil distribution.
+
+	* sg.c, sg.h: Return sense data to user.
+
+	* aha1542.c, aha1740.c, buslogic.c: Do not panic if
+	sense buffer is wrong size.
+
+	* hosts.c: Test for ultrastor card before any of the others.
+
+	* scsi.c: Allow boot-time option for max_scsi_luns=? so that
+	buggy firmware has an easy work-around.
+
+Sun May 15 20:24:34 1994  Eric Youngdale  (eric@esp22)
+
+	* Linux 1.1.15 released.
+
+	Post-codefreeze thaw...
+
+	* buslogic.[c,h]: New driver from David Gentzel.
+
+	* hosts.h: Add use_clustering field to explicitly say whether
+	clustering should be used for devices attached to this host
+	adapter.  The buslogic board apparently supports large SG lists,
+	but it is apparently faster if sd.c condenses this into a smaller
+	list.
+
+	* sd.c: Use this field instead of heuristic.
+
+	* All host adapter include files: Add appropriate initializer for
+	use_clustering field.
+
+	* scsi.h: Add #defines for return codes for the abort and reset
+	functions.  There are now a specific set of return codes to fully
+	specify all of the possible things that the low-level adapter
+	could do.
+
+	* scsi.c: Act based upon return codes from abort/reset functions.
+
+	* All host adapter abort/reset functions: Return new return code.
+
+	* Add code in scsi.c to help debug timeouts.  Use #define
+	DEBUG_TIMEOUT to enable this.
+
+	* scsi.c: If the host->irq field is set, use
+	disable_irq/enable_irq before calling queuecommand if we
+	are not already in an interrupt.  Reduce races, and we
+	can be sloppier about cli/sti in the interrupt routines now
+	(reduce interrupt latency).
+
+	* constants.c: Fix some things to eliminate warnings.  Add some
+	sense descriptions that were omitted before.
+
+	* aha1542.c: Watch for SCRD from host adapter - if we see it, set
+	a flag.  Currently we only print out the number of pending
+	commands that might need to be restarted.
+
+	* aha1542.c (aha1542_abort): Look for lost interrupts, OGMB still
+	full, and attempt to recover.  Otherwise give up.
+
+	* aha1542.c (aha1542_reset): Try BUS DEVICE RESET, and then pass
+	DID_RESET back up to the upper level code for all commands running
+	on this target (even on different LUNs).
+
+Sat May  7 14:54:01 1994
+
+	* Linux 1.1.12 released.
+
+	* st.c, st.h: New version from Kai.  Supports boot time
+	specification of number of buffers.
+
+	* wd7000.[c,h]: Updated driver from John Boyd.  Now supports
+	more than one wd7000 board in machine at one time, among other things.
+
+Wed Apr 20 22:20:35 1994
+
+	* Linux 1.1.8 released.
+
+	* sd.c: Add a few type casts where scsi_malloc is called.
+
+Wed Apr 13 12:53:29 1994
+
+	* Linux 1.1.4 released.
+
+	* scsi.c: Clean up a few printks (use %p to print pointers).
+
+Wed Apr 13 11:33:02 1994
+
+	* Linux 1.1.3 released.
+
+	* fdomain.c: Update to version 5.16 (Handle different FIFO sizes
+	better).
+
+Fri Apr  8 08:57:19 1994
+
+	* Linux 1.1.2 released.
+
+	* Throughout: SCSI portion of cluster diffs added.
+
+Tue Apr  5 07:41:50 1994
+
+	* Linux 1.1 development tree initiated.
+
+	* The linux 1.0 development tree is now effectively frozen except
+	for obvious bugfixes.
+
+******************************************************************
+******************************************************************
+******************************************************************
+******************************************************************
+
+Sun Apr 17 00:17:39 1994
+
+	* Linux 1.0, patchlevel 9 released.
+
+	* fdomain.c: Update to version 5.16 (Handle different FIFO sizes
+	better).
+
+Thu Apr  7 08:36:20 1994
+
+	* Linux 1.0, patchlevel8 released.
+
+	* fdomain.c: Update to version 5.15 from 5.9.  Handles 3.4 bios.
+
+Sun Apr  3 14:43:03 1994
+
+	* Linux 1.0, patchlevel6 released.
+
+	* wd7000.c: Make stab at fixing race condition.
+
+Sat Mar 26 14:14:50 1994
+
+	* Linux 1.0, patchlevel5 released.
+
+	* aha152x.c, Makefile: Fix a few bugs (too much data message).
+	Add a few more bios signatures. (Patches from Juergen).
+
+	* aha1542.c: Fix race condition in aha1542_out.
+
+Mon Mar 21 16:36:20 1994
+
+	* Linux 1.0, patchlevel3 released.
+
+	* sd.c, st.c, sr.c, sg.c: Return -ENXIO, not -ENODEV if we attempt
+	to open a non-existent device.
+
+	* scsi.c: Add Chinon cdrom to blacklist.
+
+	* sr_ioctl.c: Check return status of verify_area.
+
+Sat Mar  6 16:06:19 1994
+
+	* Linux 1.0 released (technically a pre-release).
+
+	* scsi.c: Add IMS CDD521, Maxtor XT-8760S to blacklist.
+
+Tue Feb 15 10:58:20 1994
+
+        * pl15e released.
+
+        * aha1542.c: For 1542C, allow dynamic device scan with >1Gb turned
+	off.
+
+	* constants.c: Fix typo in definition of CONSTANTS.
+
+        * pl15d released.
+
+Fri Feb 11 10:10:16 1994
+
+        * pl15c released.
+
+	* scsi.c: Add Maxtor XT-3280 and Rodime RO3000S to blacklist.
+
+	* scsi.c: Allow tagged queueing for scsi 3 devices as well.
+	Some really old devices report a version number of 0.  Disallow
+	LUN != 0 for these.
+
+Thu Feb 10 09:48:57 1994
+
+        * pl15b released.
+
+Sun Feb  6 12:19:46 1994
+
+        * pl15a released.
+
+Fri Feb  4 09:02:17 1994
+
+        * scsi.c: Add Teac cdrom to blacklist.
+
+Thu Feb  3 14:16:43 1994
+
+	* pl15 released.
+
+Tue Feb  1 15:47:43 1994
+
+	* pl14w released.
+
+	* wd7000.c (wd_bases): Fix typo in last change.
+
+Mon Jan 24 17:37:23 1994
+
+	* pl14u released.
+
+	* aha1542.c: Support 1542CF/extended bios.  Different from 1542C
+
+	* wd7000.c: Allow bios at 0xd8000 as well.
+
+	* ultrastor.c: Do not truncate cylinders to 1024.
+
+	* fdomain.c: Update to version 5.9 (add new bios signature).
+
+	* NCR5380.c: Update from Drew - should work a lot better now.
+
+Sat Jan  8 15:13:10 1994
+
+	* pl14o released.
+
+	* sr_ioctl.c: Zero reserved field before trying to set audio volume.
+
+Wed Jan  5 13:21:10 1994
+
+	* pl14m released.
+
+	* fdomain.c: Update to version 5.8.  No functional difference???
+
+Tue Jan  4 14:26:13 1994
+
+	* pl14l released.
+
+	* ultrastor.c: Remove outl, inl functions (now provided elsewhere).
+
+Mon Jan  3 12:27:25 1994
+
+	* pl14k released.
+
+	* aha152x.c: Remove insw and outsw functions.
+
+	* fdomain.c: Ditto.
+
+Wed Dec 29 09:47:20 1993
+
+	* pl14i released.
+
+	* scsi.c: Support RECOVERED_ERROR for tape drives.
+
+	* st.c: Update of tape driver from Kai.
+
+Tue Dec 21 09:18:30 1993
+
+	* pl14g released.
+
+	* aha1542.[c,h]: Support extended BIOS stuff.
+
+	* scsi.c: Clean up messages about disks, so they are displayed as
+	sda, sdb, etc instead of sd0, sd1, etc.
+
+	* sr.c:  Force reread of capacity if disk was changed.
+	Clear buffer before asking for capacity/sectorsize (some drives
+	do not report this properly).  Set needs_sector_size flag if
+	drive did not return sensible sector size.
+
+Mon Dec 13 12:13:47 1993
+
+	* aha152x.c: Update to version .101 from Juergen.
+
+Mon Nov 29 03:03:00 1993
+
+        * linux 0.99.14 released.
+
+	* All scsi stuff moved from kernel/blk_drv/scsi to drivers/scsi.
+
+	* Throughout: Grammatical corrections to various comments.
+
+	* Makefile: fix so that we do not need to compile things we are
+	not going to use.
+
+	* NCR5380.c, NCR5380.h, g_NCR5380.c, g_NCR5380.h, pas16.c,
+	pas16.h, t128.c, t128.h:  New files from Drew.
+
+	* aha152x.c, aha152x.h: New files from Juergen Fischer.
+
+	* aha1542.c: Support for more than one 1542 in the machine
+	at the same time.  Make functions static that do not need
+	visibility.
+
+	* aha1740.c: Set NEEDS_JUMPSTART flag in reset function, so we
+	know to restart the command.  Change prototype of aha1740_reset
+	to take a command pointer.
+
+	* constants.c: Clean up a few things.
+
+	* fdomain.c: Update to version 5.6.  Move snarf_region.  Allow
+	board to be set at different SCSI ids.  Remove support for
+	reselection (did not work well).  Set JUMPSTART flag in reset
+	code.
+
+	* hosts.c: Support new low-level adapters.  Allow for more than
+	one adapter of a given type.
+
+	* hosts.h: Allow for more than one adapter of a given type.
+
+	* scsi.c:  Add scsi_device_types array, if NEEDS_JUMPSTART is set
+	after a low-level reset, start the command again.  Sort blacklist,
+	and add Maxtor MXT-1240S, XT-4170S, NEC CDROM 84, Seagate ST157N.
+
+	* scsi.h: Add constants for tagged queueing.
+
+	* Throughout: Use constants from major.h instead of hardcoded
+	numbers for major numbers.
+
+	* scsi_ioctl.c: Fix bug in buffer length in ioctl_command.  Use
+	verify_area in GET_IDLUN ioctl.  Add new ioctls for
+	TAGGED_QUEUE_ENABLE, DISABLE.  Only allow IOCTL_SEND_COMMAND by
+	superuser.
+
+	* sd.c: Only pay attention to UNIT_ATTENTION for removable disks.
+	Fix bug where sometimes portions of blocks would get lost
+	resulting in processes hanging.  Add messages when we spin up a
+	disk, and fix a bug in the timing.  Increase read-ahead for disks
+	that are on a scatter-gather capable host adapter.
+
+	* seagate.c: Fix so that some parameters can be set from the lilo
+	prompt.  Supply jumpstart flag if we are resetting and need the
+	command restarted.   Fix so that we return 1 if we detect a card
+	so that multiple card detection works correctly.  Add yet another
+	signature for FD cards (950).  Add another signature for ST0x.
+
+	* sg.c, sg.h: New files from Lawrence Foard for generic scsi
+	access.
+
+	* sr.c:  Add type casts for (void*) so that we can do pointer
+	arithmetic.  Works with GCC without this, but it is not strictly
+	correct.  Same bugfix as was in sd.c.  Increase read-ahead a la
+	disk driver.
+
+	* sr_ioctl.c: Use scsi_malloc buffer instead of buffer from stack
+	since we cannot guarantee that the stack is < 16Mb.
+
+	ultrastor.c: Update to support 24f properly (JFC's driver).
+
+	wd7000.c: Supply jumpstart flag for reset.  Do not round up
+	number of cylinders in biosparam function.
+
+Sat Sep  4 20:49:56 1993
+
+    * 0.99pl13 released.
+
+    * Throughout:  Use check_region/snarf_region for all low-level
+    drivers.
+
+    * aha1542.c: Do hard reset instead of soft (some ethercard probes
+    screw us up).
+
+    * scsi.c: Add new flag ASKED_FOR_SENSE so that we can tell if we are
+    in a loop whereby the device returns null sense data.
+
+    * sd.c: Add code to spin up a drive if it is not already spinning.
+    Do this one at a time to make it easier on power supplies.
+
+    * sd_ioctl.c: Use sync_dev instead of fsync_dev in BLKFLSBUF ioctl.
+
+    * seagate.c: Switch around DATA/CONTROL lines.
+
+    * st.c: Change sense to unsigned.
+
+Thu Aug  5 11:59:18 1993
+
+    * 0.99pl12 released.
+
+    * constants.c, constants.h: New files with ascii descriptions of
+    various conditions.
+
+    * Makefile: Do not try to count the number of low-level drivers,
+    just generate the list of .o files.
+
+    * aha1542.c: Replace 16 with sizeof(SCpnt->sense_buffer).  Add tests
+    for addresses > 16Mb, panic if we find one.
+
+    * aha1740.c: Ditto with sizeof().
+
+    * fdomain.c: Update to version 3.18.  Add new signature, register IRQ
+    with irqaction.  Use ID 7 for new board.  Be more intelligent about
+    obtaining the h/s/c numbers for biosparam.
+
+    * hosts.c: Do not depend upon Makefile generated count of the number
+    of low-level host adapters.
+
+    * scsi.c: Use array for scsi_command_size instead of a function.  Add
+    Texel cdrom and Maxtor XT-4380S to blacklist.  Allow compile time
+    option for no-multi lun scan.  Add semaphore for possible problems
+    with handshaking, assume device is faulty until we know it not to be
+    the case.  Add DEBUG_INIT symbol to dump info as we scan for devices.
+    Zero sense buffer so we can tell if we need to request it.  When
+    examining sense information, request sense if buffer is all zero.
+    If RESET, request sense information to see what to do next.
+
+    * scsi_debug.c: Change some constants to use symbols like INT_MAX.
+
+    * scsi_ioctl.c (kernel_scsi_ioctl): New function -for making ioctl
+    calls from kernel space.
+
+    * sd.c: Increase timeout to 300.  Use functions in constants.h to
+    display info.  Use scsi_malloc buffer for READ_CAPACITY, since
+    we cannot guarantee that a stack based buffer is < 16Mb.
+
+    * sd_ioctl.c: Add BLKFLSBUF ioctl.
+
+    * seagate.c: Add new compile time options for ARBITRATE,
+    SLOW_HANDSHAKE, and SLOW_RATE.  Update assembly loops for transferring
+    data.  Use kernel_scsi_ioctl to request mode page with geometry.
+
+    * sr.c: Use functions in constants.c to display messages.
+
+    * st.c: Support for variable block size.
+
+    * ultrastor.c: Do not use cache for tape drives.  Set
+    unchecked_isa_dma flag, even though this may not be needed (gets set
+    later).
+
+Sat Jul 17 18:32:44 1993
+
+    * 0.99pl11 released.  C++ compilable.
+
+    * Throughout: Add type casts all over the place, and use "ip" instead
+    of "info" in the various biosparam functions.
+
+    * Makefile: Compile seagate.c with C++ compiler.
+
+    * aha1542.c: Always set ccb pointer as this gets trashed somehow on
+    some systems.  Add a few type casts.  Update biosparam function a little.
+
+    * aha1740.c: Add a few type casts.
+
+    * fdomain.c: Update to version 3.17 from 3.6.  Now works with
+    TMC-18C50.
+
+    * scsi.c: Minor changes here and there with datatypes.  Save use_sg
+    when requesting sense information so that this can properly be
+    restored if we retry the command.  Set aside dma buffers assuming each
+    block is 1 page, not 1Kb minix block.
+
+    * scsi_ioctl.c: Add a few type casts.  Other minor changes.
+
+    * sd.c:  Correctly  free all scsi_malloc'd memory if we run out of
+    dma_pool. Store blocksize information for each partition.
+
+    * seagate.c: Minor cleanups here and there.
+
+    * sr.c: Set up blocksize array for all discs.  Fix bug in freeing
+    buffers if we run out of dma pool.
+
+Thu Jun  2 17:58:11 1993
+
+    * 0.99pl10 released.
+
+    * aha1542.c: Support for BT 445S (VL-bus board with no dma channel).
+
+    * fdomain.c: Upgrade to version 3.6. Preliminary support for TNC-18C50.
+
+    * scsi.c: First attempt to fix problem with old_use_sg.  Change
+    NOT_READY to a SUGGEST_ABORT.  Fix timeout race where time might
+    get decremented past zero.
+
+    * sd.c: Add block_fsync function to dispatch table.
+
+    * sr.c: Increase timeout to 500 from 250.  Add entry for sync in
+    dispatch table (supply NULL).  If we do not have a sectorsize,
+    try to get it in the sd_open function.  Add new function just to
+    obtain sectorsize.
+
+    * sr.h: Add needs_sector_size semaphore.
+
+    * st.c: Add NULL for fsync in dispatch table.
+
+    * wd7000.c: Allow another condition for power on that are normal
+    and do not require a panic.
+
+Thu Apr 22 23:10:11 1993
+
+    * 0.99pl9 released.
+
+    * aha1542.c: Use (void) instead of () in setup_mailboxes.
+
+    * scsi.c: Initialize transfersize and underflow fields in SCmd to 0.
+    Do not panic for unsupported message bytes.
+
+    * scsi.h: Allocate 12 bytes instead of 10 for commands.  Add
+    transfersize and underflow fields.
+
+    * scsi_ioctl.c: Further bugfix to ioctl_probe.
+
+    * sd.c: Use long instead of int for last parameter in sd_ioctl.
+    Initialize transfersize and underflow fields.
+
+    * sd_ioctl.c: Ditto for sd_ioctl(,,,,);
+
+    * seagate.c: New version from Drew.  Includes new signatures for FD
+    cards.  Support for 0ws jumper. Correctly initialize
+    scsi_hosts[hostnum].this_id.  Improved handing of
+    disconnect/reconnect, and support command linking.  Use
+    transfersize and underflow fields.  Support scatter-gather.
+
+    * sr.c, sr_ioctl.c: Use long instead of int for last parameter in sr_ioctl.
+    Use buffer and buflength in do_ioctl.  Patches from Chris Newbold for
+    scsi-2 audio commands.
+
+    * ultrastor.c: Comment out in_byte (compiler warning).
+
+    * wd7000.c: Change () to (void) in wd7000_enable_dma.
+
+Wed Mar 31 16:36:25 1993
+
+    * 0.99pl8 released.
+
+    * aha1542.c: Handle mailboxes better for 1542C.
+        Do not truncate number of cylinders at 1024 for biosparam call.
+
+    * aha1740.c: Fix a few minor bugs for multiple devices.
+        Same as above for biosparam.
+
+    * scsi.c: Add lockable semaphore for removable devices that can have
+    media removal prevented.  Add another signature for flopticals.
+    (allocate_device): Fix race condition.  Allow more space in dma pool
+    for blocksizes of up to 4Kb.
+
+    * scsi.h: Define COMMAND_SIZE.  Define a SCSI specific version of
+    INIT_REQUEST that can run with interrupts off.
+
+    * scsi_ioctl.c: Make ioctl_probe function more idiot-proof.  If
+    a removable device says ILLEGAL REQUEST to a door-locking command,
+    clear lockable flag.  Add SCSI_IOCTL_GET_IDLUN ioctl.  Do not attempt
+    to lock door for devices that do not have lockable semaphore set.
+
+    * sd.c: Fix race condition for multiple disks.  Use INIT_SCSI_REQUEST
+    instead of INIT_REQUEST.  Allow sector sizes of 1024 and 256.  For
+    removable disks that are not ready, mark them as having a media change
+    (some drives do not report this later).
+
+    * seagate.c: Use volatile keyword for memory-mapped register pointers.
+
+    * sr.c: Fix race condition, a la sd.c.  Increase the number of retries
+    to 1.  Use INIT_SCSI_REQUEST.  Allow 512 byte sector sizes.  Do a
+    read_capacity when we init the device so we know the size and
+    sectorsize.
+
+    * st.c: If ioctl not found in st.c, try scsi_ioctl for others.
+
+    * ultrastor.c: Do not truncate number of cylinders at 1024 for
+    biosparam call.
+
+    * wd7000.c: Ditto.
+    Throughout: Use COMMAND_SIZE macro to determine length of scsi
+    command.
+
+
+
+Sat Mar 13 17:31:29 1993
+
+    * 0.99pl7 released.
+
+    Throughout: Improve punctuation in some messages, and use new
+    verify_area syntax.
+
+    * aha1542.c: Handle unexpected interrupts better.
+
+    * scsi.c: Ditto.  Handle reset conditions a bit better, asking for
+    sense information and retrying if required.
+
+    * scsi_ioctl.c: Allow for 12 byte scsi commands.
+
+    * ultrastor.c: Update to use scatter-gather.
+
+Sat Feb 20 17:57:15 1993
+
+    * 0.99pl6 released.
+
+    * fdomain.c: Update to version 3.5.  Handle spurious interrupts
+    better.
+
+    * sd.c: Use register_blkdev function.
+
+    * sr.c: Ditto.
+
+    * st.c: Use register_chrdev function.
+
+    * wd7000.c: Undo previous change.
+
+Sat Feb  6 11:20:43 1993
+
+    * 0.99pl5 released.
+
+    * scsi.c: Fix bug in testing for UNIT_ATTENTION.
+
+    * wd7000.c: Check at more addresses for bios.  Fix bug in biosparam
+    (heads & sectors turned around).
+
+Wed Jan 20 18:13:59 1993
+
+    * 0.99pl4 released.
+
+    * scsi.c: Ignore leading spaces when looking for blacklisted devices.
+
+    * seagate.c: Add a few new signatures for FD cards.  Another patch
+    with SCint to fix race condition.  Use recursion_depth to keep track
+    of how many times we have been recursively called, and do not start
+    another command unless we are on the outer level.  Fixes bug
+    with Syquest cartridge drives (used to crash kernel), because
+    they do not disconnect with large data transfers.
+
+Tue Jan 12 14:33:36 1993
+
+    * 0.99pl3 released.
+
+    * fdomain.c: Update to version 3.3 (a few new signatures).
+
+    * scsi.c: Add CDU-541, Denon DRD-25X to blacklist.
+    (allocate_request, request_queueable): Init request.waiting to NULL if
+    non-buffer type of request.
+
+    * seagate.c:  Allow controller to be overridden with CONTROLLER symbol.
+    Set SCint=NULL when we are done, to remove race condition.
+
+    * st.c: Changes from Kai.
+
+Wed Dec 30 20:03:47 1992
+
+    * 0.99pl2 released.
+
+    * scsi.c: Blacklist back in.  Remove Newbury drive as other bugfix
+    eliminates need for it here.
+
+    * sd.c: Return ENODEV instead of EACCES if no such device available.
+    (sd_init) Init blkdev_fops earlier so that sd_open is available sooner.
+
+    * sr.c: Same as above for sd.c.
+
+    * st.c: Return ENODEV instead of ENXIO if no device.  Init chrdev_fops
+    sooner, so that it is always there even if no tapes.
+
+    * seagate.c (controller_type): New variable to keep track of ST0x or
+    FD.  Modify signatures list to indicate controller type, and init
+    controller_type once we find a match.
+
+    * wd7000.c (wd7000_set_sync): Remove redundant function.
+
+Sun Dec 20 16:26:24 1992
+
+    * 0.99pl1 released.
+
+    * scsi_ioctl.c: Bugfix - check dev->index, not dev->id against
+    NR_SCSI_DEVICES.
+
+    * sr_ioctl.c: Verify that device exists before allowing an ioctl.
+
+    * st.c: Patches from Kai - change timeout values, improve end of tape
+    handling.
+
+Sun Dec 13 18:15:23 1992
+
+    * 0.99 kernel released.  Baseline for this ChangeLog.
diff -Nru a/Documentation/scsi/ChangeLog.ips b/Documentation/scsi/ChangeLog.ips
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ChangeLog.ips	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,122 @@
+IBM ServeRAID driver Change Log
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        5.00.01  - Sarasota ( 5i ) adapters must always be scanned first  
+                 - Get rid on IOCTL_NEW_COMMAND code  
+                 - Add Extended DCDB Commands for Tape Support in 5I                  
+        
+        4.90.11  - Don't actually RESET unless it's physically required
+                 - Remove unused compile options
+        
+        4.90.08  - Data Corruption if First Scatter Gather Element is > 64K
+        
+        4.90.08  - Increase Delays in Flashing ( Trombone Only - 4H )        
+        
+        4.90.05  - Use New PCI Architecture to facilitate Hot Plug Development
+        
+        4.90.01  - Add ServeRAID Version Checking
+
+        4.80.26  - Clean up potential code problems ( Arjan's recommendations )
+        
+        4.80.21  - Change memcpy() to copy_to_user() in NVRAM Page 5 IOCTL path   
+        
+        4.80.20  - Set max_sectors in Scsi_Host structure ( if >= 2.4.7 kernel )
+                 - 5 second delay needed after resetting an i960 adapter
+        
+        4.80.14  - Take all semaphores off stack                    
+                 - Clean Up New_IOCTL path
+                   
+        4.80.04  - Eliminate calls to strtok() if 2.4.x or greater 
+                 - Adjustments to Device Queue Depth               
+
+        4.80.00  - Make ia64 Safe    
+        
+        4.72.01  - I/O Mapped Memory release ( so "insmod ips" does not Fail )    
+                 - Don't Issue Internal FFDC Command if there are Active Commands 
+                 - Close Window for getting too many IOCTL's active 
+                   
+        4.72.00  - Allow for a Scatter-Gather Element to exceed MAX_XFER Size     
+        
+        4.71.00  - Change all memory allocations to not use GFP_DMA flag 
+                 - Code Clean-Up for 2.4.x kernel      
+        
+        4.70.15  - Fix Breakup for very large ( non-SG ) requests
+        
+        4.70.13  - Don't release HA Lock in ips_next() until SC taken off queue  
+                 - Unregister SCSI device in ips_release()                        
+                 - Don't Send CDB's if we already know the device is not present  
+                 
+        4.70.12  - Corrective actions for bad controller ( during initialization )
+        
+        4.70.09  - Use a Common ( Large Buffer ) for Flashing from the JCRM CD    
+                 - Add IPSSEND Flash Support                                      
+                 - Set Sense Data for Unknown SCSI Command                        
+                 - Use Slot Number from NVRAM Page 5 
+                 - Restore caller's DCDB Structure
+                                       
+        4.20.14  - Update patch files for kernel 2.4.0-test5
+
+        4.20.13  - Fix some failure cases / reset code
+                 - Hook into the reboot_notifier to flush the controller
+                   cache
+
+        4.20.03 - Rename version to coincide with new release schedules
+                - Performance fixes
+                - Fix truncation of /proc files with cat
+                - Merge in changes through kernel 2.4.0test1ac21
+
+        4.10.13 - Fix for dynamic unload and proc file system
+
+        4.10.00 - Add support for ServeRAID 4M/4L
+
+        4.00.06 - Fix timeout with initial FFDC command
+
+        4.00.05 - Remove wish_block from init routine
+                - Use linux/spinlock.h instead of asm/spinlock.h for kernels
+                  2.3.18 and later
+                - Sync with other changes from the 2.3 kernels
+
+        4.00.04 - Rename structures/constants to be prefixed with IPS_
+
+        4.00.03 - Add alternative passthru interface
+                - Add ability to flash ServeRAID BIOS
+
+        4.00.02 - Fix problem with PT DCDB with no buffer
+
+        4.00.01 - Add support for First Failure Data Capture
+
+        4.00.00 - Add support for ServeRAID 4
+
+        3.60.02 - Make DCDB direction based on lookup table.
+                - Only allow one DCDB command to a SCSI ID at a time.
+
+        3.60.01 - Remove bogus error check in passthru routine.
+
+        3.60.00 - Bump max commands to 128 for use with ServeRAID
+                  firmware 3.60.
+                - Change version to 3.60 to coincide with ServeRAID release
+                  numbering.
+
+        1.00.00 - Initial Public Release
+                - Functionally equivalent to 0.99.05
+
+        0.99.05 - Fix an oops on certain passthru commands
+
+        0.99.04 - Fix race condition in the passthru mechanism
+                  -- this required the interface to the utilities to change
+                - Fix error recovery code
+
+        0.99.03 - Make interrupt routine handle all completed request on the
+                  adapter not just the first one
+                - Make sure passthru commands get woken up if we run out of
+                  SCBs
+                - Send all of the commands on the queue at once rather than
+                  one at a time since the card will support it.
+
+        0.99.02 - Added some additional debug statements to print out
+                  errors if an error occurs while trying to read/write
+                  to a logical drive (IPS_DEBUG).
+
+                - Fixed read/write errors when the adapter is using an
+                  8K stripe size.
+
diff -Nru a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ChangeLog.ncr53c8xx	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,495 @@
+Sat May 12 12:00 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version ncr53c8xx-3.4.3b
+	- Ensure LEDC bit in GPCNTL is cleared when reading the NVRAM.
+	  Fix sent by Stig Telfer <stig@api-networks.com>.
+	- Define scsi_set_pci_device() as nil for kernel < 2.4.4.
+
+Mon Feb 12 22:30 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version ncr53c8xx-3.4.3
+	- Call pci_enable_device() as AC wants this to be done.
+	- Get both the BAR cookies actual and PCI BAR values.
+	  (see Changelog.sym53c8xx rev. 1.7.3 for details)
+	- Merge changes for linux-2.4 that declare the host template 
+	  in the driver object also when the driver is statically 
+	  linked with the kernel.
+
+Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version ncr53c8xx-3.4.2
+	- See Changelog.sym53c8xx, driver version 1.7.2.
+
+Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version ncr53c8xx-3.4.1
+	- Provide OpenFirmare path through the proc FS on PPC.
+	- Remove trailing argument #2 from a couple of #undefs.
+
+Sun Jul 09 16:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version ncr53c8xx-3.4.0
+	- Remove the PROFILE C and SCRIPTS code.
+	  This facility was not this useful and thus was not longer 
+	  desirable given the increasing complexity of the driver code.
+	- Merges from FreeBSD sym-1.6.2 driver:
+	  * Clarify memory barriers needed by the driver for architectures 
+	    that implement a weak memory ordering.
+	- General cleanup:
+	  Move definitions for barriers and IO/MMIO operations to the 
+	  sym53c8xx_defs.h header files. They are now shared by the 
+	  both drivers.
+	  Use SCSI_NCR_IOMAPPED instead of NCR_IOMAPPED.
+
+Thu May 11   12:30 2000 Pam Delaney (pam.delaney@lsil.com)
+	* revision 3.3b
+ 
+Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2i
+	- Return value 1 (instead of 0) from the driver setup routine.
+	- Let the driver also attach controllers that have been set to 
+	  OFF in the NVRAM as it did prior to revision 3.2g.
+
+Sat Apr 1  12:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2h
+	- Fix a compilation problem on Alpha introduced in version 3.2g.
+          (`port' changed to `base_io').
+	- Move from `sym' to this driver a tiny change for __sparc__ that 
+	  applies to cache line size (? Probably from David S Miller).
+	- Make sure no data transfer will happen for Scsi_Cmnd requests 
+	  that supply SCSI_DATA_NONE direction (this avoids some BUG() 
+	  statement in the PCI code when a data buffer is also supplied).
+
+Thu Mar 16   9:30 2000 Pam Delaney (pam.delaney@lsil.com)
+	* revision 3.3b-3
+ 	- Added exclusion for the 53C1010 and 53C1010_66 chips
+	  to the driver (change to sym53c8xx_comm.h).
+
+Mon March 6  23:15 2000 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2g
+	- Add the file sym53c8xx_comm.h that collects code that should 
+	  be shared by sym53c8xx and ncr53c8xx drivers. For now, it is  
+	  a header file that is only included by the ncr53c8xx driver, 
+	  but things will be cleaned up later. This code addresses 
+	  notably:
+	  * Chip detection and PCI related initialisations
+	  * NVRAM detection and reading
+	  * DMA mapping
+	  * Boot setup command
+	  * And some other ...
+	- Add support for the new dynamic dma mapping kernel interface.
+	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
+	- Get data transfer direction from the scsi command structure 
+	  (Scsi_Cmnd) when this information is available.
+
+Mon March 6  23:15 2000 Gerard Roudier (groudier@club-internet.fr)
+        * revision 3.2g
+        - Add the file sym53c8xx_comm.h that collects code that should
+          be shared by sym53c8xx and ncr53c8xx drivers. For now, it is
+          a header file that is only included by the ncr53c8xx driver,
+          but things will be cleaned up later. This code addresses
+          notably:
+          * Chip detection and PCI related initialisations
+          * NVRAM detection and reading
+          * DMA mapping
+          * Boot setup command
+          * And some other ...
+        - Add support for the new dynamic dma mapping kernel interface.
+          Requires Linux-2.3.47 (tested with pre-2.3.47-6).
+        - Get data transfer direction from the scsi command structure
+          (Scsi_Cmnd) when this information is available.
+
+Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
+	* revision pre-3.3b-1
+	- Merge parallel driver series 3.31 and 3.2e 
+
+Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
+	* revision 3.31
+	- Added support for mounting disks on wide-narrow-wide
+	  scsi configurations.  
+	- Built off of version 3.30
+
+Mon Jan 10 13:30 2000 Pam Delaney (pam.delaney@lsil.com)
+	* revision 3.30
+	- Added capability to use the integrity checking code
+	  in the kernel (optional).
+	- Disabled support for the 53C1010.
+	- Built off of version 3.2c
+
+Sat Jan 8  22:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2e
+	- Add year 2000 copyright.
+	- Display correctly bus signals when bus is detected wrong.
+	- Remove the dead code that broke driver 3.2d.
+
+Mon Dec 6  22:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2d
+	- Change messages written by the driver at initialisation and 
+	  through the /proc FS (rather cosmetic changes that consist in
+	  printing out the PCI bus number and device/function).
+	- Get rid of the old PCI bios interface, but preserve kernel 2.0 
+	  compatibility from a simple wrapper.
+	- Remove the compilation condition about having to acquire the 
+	  io_request_lock since it seems to be a definite feature now.:)
+	- proc_dir structure no longer needed for kernel >= 2.3.27.
+	- Change the driver detection code by the sym53c8xx one, modulo 
+	  some minor changes. The driver can now attach any number of 
+	  controllers (>40) and does no longer hoger stack space at 
+	  initialisation.
+	- Definitely disable overlapped PCI arbitration for all dual 
+	  function chips, since I cannot make sure for what chip revisions 
+	  it is actually safe.
+	- Add support for the SYM53C1510D.
+	- Update the poor Tekram sync factor table.
+	- Remove the compilation condition about having to acquire the 
+	  io_request_lock since it seems to be a definite feature now.:)
+	- proc_dir structure no longer needed for kernel >= 2.3.27.
+
+Sat Sep 11  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2c
+	- Handle correctly (hopefully) jiffies wrap-around.
+	- Restore the entry used to detect 875 until revision 0xff.
+	  (I removed it inadvertently, it seems :) )
+	- Replace __initfunc() which is deprecated stuff by __init which 
+	  is not yet so. ;-)
+	- Add support of some 'resource handling' for linux-2.3.13.
+	  Basically the BARs have been changed to something more complex 
+	  in the pci_dev structure.
+	- Remove some deprecated code.
+
+Sat May 10  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision pre-3.2b-1
+	- Support for the 53C895A by Pamela Delaney <pam.delaney@lsil.com>
+	  The 53C895A contains all of the features of the 896 but has only 
+	  one channel and has a 32 bit PCI bus. It does 64 bit PCI addressing 
+	  using dual cycle PCI data transfers.
+	- Miscellaneous minor fixes.
+	- Some additions to the README.ncr53c8xx file.
+
+Sun Apr 11  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2a
+	- Add 'hostid:#id' boot option. This option allows to change the 
+	  default SCSI id the driver uses for controllers.
+	- Remove nvram layouts and driver set-up structures from the C source,
+	  and use the one defined in sym53c8xx_defs.h file.
+	  (shared by both drivers).
+	- Set for now MAX LUNS to 16 (instead of 8).
+
+Thu Mar 11  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.2	  (8xx-896 driver bundle)
+	- Only define the host template in ncr53c8xx.h and include the 
+	  sym53c8xx_defs.h file.
+	- Declare static all symbols that do not need to be visible from 
+	  outside the driver code.
+	- Add 'excl' boot command option that allows to pass to the driver 
+	  io address of devices not to attach.
+	- Add info() function called from the host template to print 
+	  driver/host information.
+	- Minor documentation additions.
+
+Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1h
+	- Fix some oooold bug that hangs the bus if a device rejects a 
+	  negotiation. Btw, the corresponding stuff also needed some cleanup 
+	  and thus the change is a bit larger than it could have been.
+	- Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb  14:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1g
+	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
+	  Pointed out by Leonard Zubkoff.
+	- Allow to tune request_irq() flags from the boot command line using 
+	  ncr53c8xx=irqm:??, as follows:
+	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
+	  a 53C8XX adapter and a network board.
+	- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
+	  harmless.
+	- Negotiate SYNC data transfers with CCS devices.
+
+Sat Jan 16  17:30 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1f
+	- Some PCI fix-ups not needed any more for PPC (from Cort).
+	- Cache line size set to 16 DWORDS for Sparc   (from DSM).
+	- Waiting list look-up didn't work for the first command of the list.
+	- Remove 2 useless lines of code.
+
+Sun Dec 13  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1e
+	- Same work-around as for the 53c876 rev <= 0x15 for 53c896 rev 1:
+	  Disable overlapped arbitration. This will not make difference 
+	  since the chip has on-chip RAM.
+
+Thu Nov 26  22:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1d
+	- The SISL RAID change requires now remap_pci_mem() stuff to be 
+	  compiled for __i386__ when normal IOs are used.
+	- Minor spelling fixes in doc files.
+
+Sat Nov 21  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1c
+	- Ignore chips that are driven by SISL RAID (DAC 960).
+	  Change sent by Leonard Zubkoff and slightly reworked.
+	- Still a buglet in the tags initial settings that needed to be fixed.
+	  It was not possible to disable TGQ at system startup for devices 
+	  that claim TGQ support. The driver used at least 2 for the queue 
+	  depth but did'nt keep track of user settings for tags depth lower 
+	  than 2.
+
+Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1b
+	- The driver was unhappy when configured with default_tags > MAX_TAGS
+	  Hopefully doubly-fixed.
+	- Update the Configure.help driver section that speaks of TAGS.
+
+Wed Oct 21 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1a
+	- Changes from Eddie Dost for Sparc and Alpha:
+	  ioremap/iounmap support for Sparc.
+	  pcivtophys changed to bus_dvma_to_phys.
+	- Add the 53c876 description to the chip table. This is only useful 
+	  for printing the right name of the controller.
+	- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
+	- Add additionnal checking of INQUIRY data:
+	  Check INQUIRY data received length is at least 7. Byte 7 of 
+	  inquiry data contains device features bits and the driver might 
+	  be confused by garbage. Also check peripheral qualifier.
+	- Cleanup of the SCSI tasks management:
+	  Remove the special case for 32 tags. Now the driver only uses the 
+	  scheme that allows up to 64 tags per LUN.
+	  Merge some code from the 896 driver.
+	  Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could  
+	  use any tag number from 1 to 253 and some non conformant devices  
+	  might have problems with large tag numbers.
+	- 'no_sync' changed to 'no_disc' in the README file. This is an old 
+	  and trivial mistake that seems to demonstrate the README file is 
+	  not often read. :)
+
+Sun Oct  4 14:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0i
+	- Cosmetic changes for sparc (but not for the driver) that needs  
+	  __irq_itoa() to be used for printed IRQ value to be understandable.
+	- Some problems with the driver that didn't occur using driver 2.5f 
+	  were due to a SCSI selection problem triggered by a clearly 
+	  documented feature that in fact seems not to work: (53C8XX chips  
+	  are claimed by the manuals to be able to execute SCSI scripts just 
+	  after abitration while the SCSI core is performing SCSI selection).
+	  This optimization is broken and has been removed.
+	- Some broken scsi devices are confused when a negotiation is started 
+	  on a LUN that does not correspond to a real device. According to 
+	  SCSI specs, this is a device firmware bug. This has been worked 
+	  around by only starting negotiation if the LUN has previously be 
+	  used for at least 1 successful SCSI command.
+	- The 'last message sent' printed out on M_REJECT message reception 
+	  was read from the SFBR i/o register after the previous message had 
+	  been sent. 
+	  This was not correct and affects all previous driver versions and 
+	  the original FreeBSD one as well. The SCSI scripts has been fixed 
+	  so that it now provides the right information to the C code.
+
+Sat Jul 18 13:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0g
+	- Preliminary fixes for Big Endian (sent by Eddie C. Dost).
+	  Big Endian architectures should work again with the driver.
+	  Eddie's patch has been partially applied since current 2.1.109 
+	  does not have all the Sparc changes of the vger tree.
+	- Use of BITS_PER_LONG instead of (~0UL == 0xffffffffUL) has fixed
+	  the problem observed when the driver was compiled using EGCS or 
+	  PGCC.
+
+Mon Jul 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0f
+	- Some spelling fixes.
+	- linux/config.h misplaced in ncr53c8xx.h
+	- MODULE_PARM stuff added for linux 2.1.
+	- check INQUIRY response data format is exactly 2. 
+	- use BITS_PER_LONG if defined. 
+
+Sun Jun 28 12:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0e
+	- Some cleanup, spelling fixes, version checks, documentations 
+	  changes, etc ...
+
+Sat Jun 20 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0c
+	- Add a boot setup option that allows to set up device queue depths 
+	  at boot-up. This option is very useful since Linux does not 
+	  allow to change scsi device queue depth once the system has been 
+	  booted up.
+
+Sun Jun 15 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0a
+	- Support for up to 64 TAGS per LUN.
+	- Rewrite the TARGET vs LUN capabilities management.
+	  CmdQueue is now handled as a LUN capability as it shall be.
+	  This also fixes a bug triggered when disabling tagged command 
+	  queuing for a device that had this feature enabled.
+	- Remove the ncr_opennings() stuff that was useless under Linux 
+	  and hard to understand to me.
+	- Add "setverbose" procfs driver command. It allows to tune 
+	  verbose level after boot-up. Setting this level to zero, for 
+	  example avoid flooding the syslog file.
+	- Add KERN_XXX to some printk's.
+
+Tue Jun 10 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0
+	- Linux config changes for 2.0.34:
+	  Remove NVRAM detection config option. This option is now enabled 
+	  by default but can be disabled by editing the driver header file.
+	  Add a PROFILE config option.
+	- Update Configure.help
+	- Add calls to new function mdelay() for milli-seconds delay if 
+	  kernel version >= 2.1.105.
+	- Replace all printf(s) by printk(s). After all, the ncr53c8xx is 
+	  a driver for Linux.
+	- Perform auto-sense on COMMAND TERMINATED. Not sure it is useful.
+	- Some other minor changes.
+
+Tue Jun 4 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6n
+	- Code cleanup and simplification:
+	  Remove kernel 1.2.X and 1.3.X support.
+	  Remove the _old_ target capabilities table.
+	  Remove the error recovery code that have'nt been really useful.
+	  Use a single alignment boundary (CACHE_LINE_SIZE) for data 
+	  structures.
+	- Several aggressive SCRIPTS optimizations and changes:
+	  Reselect SCRIPTS code rewritten.
+	  Support for selection/reselection without ATN.
+	  And some others.
+	- Miscallaneous changes in the C code:
+	  Count actual number of CCB queued to the controller (future use).
+	  Lots of other minor changes.
+
+Wed May 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6m
+	- Problem of missed SCSI bus reset with the 53C895 fixed by 
+	  Richard Waltham. The 53C895 needs about 650 us for the bus 
+	  mode to settle. Delays used while resetting the controller 
+	  and the bus have been adjusted. Thanks Richard!
+	- Some simplification for 64 bit arch done ccb address testing.
+	- Add a check of the MSG_OUT phase after Selection with ATN.
+	- The new tagged queue stuff seems ok, so some informationnal 
+	  message have been conditionned by verbose >= 3.
+	- Donnot reset if a SBMC interrupt reports the same bus mode.
+	- Print out the whole driver set-up. Some options were missing and 
+	  the print statement was misplaced for modules.
+	- Ignore a SCSI parity interrupt if the chip is not connected to 
+	  the SCSI bus.
+
+Sat May 1 16:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6l
+	- Add CCB done queue support for Alpha and perhaps some other 
+	  architectures.
+	- Add some barriers to enforce memory ordering for x86 and 
+	  Alpha architectures.
+	- Fix something that looks like an old bug in the nego SIR 
+	  interrupt code in case of negotiation failure.
+
+Sat Apr 25 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6k
+	- Remove all accesses to the on-chip RAM from the C code:
+	  Use SCRIPTS to load the on-chip RAM.
+	  Use SCRIPTS to repair the start queue on selection timeout.
+	  Use the copy of script in main memory to calculate the chip 
+	  context on phase mismatch.
+	- The above allows now to use the on-chip RAM without requiring 
+	  to get access to the on-chip RAM from the C code. This makes 
+	  on-chip RAM useable for linux-1.2.13 and for Linux-Alpha for 
+	  instance.
+	- Some simplifications and cleanups in the SCRIPTS and C code.
+	- Buglet fixed in parity error recovery SCRIPTS (never tested).
+	- Minor updates in README.ncr53c8xx.
+
+Wed Apr 15 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6j
+	- Incorporate changes from linux-2.1.95 ncr53c8xx driver version.
+	- Add SMP support for linux-2.1.95 and above.
+	- Fix a bug when QUEUE FULL is returned and no commands are 
+	  disconnected. This happens with Atlas I / L912 and may happen 
+	  with Atlas II / LXY4.
+	- Nail another one on CHECK condition when requeuing the command 
+	  for auto-sense.
+	- Call scsi_done() for all completed commands after interrupt 
+	  handling.
+	- Increase the done queue to 24 entries.
+
+Sat Apr 4 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6i
+	- CTEST0 is used by the 53C885 for Power Management and 
+	  priority setting between the 2 functions.
+	  Use SDID instead as actual target number. Just have had to 
+	  overwrite it with SSID on reselection.
+	- Split DATA_IN and DATA_OUT scripts into 2 sub-scripts.
+	  64 segments are moved from on-chip RAM scripts.
+	  If more segments, a script in main memory is used for the 
+	  additionnal segments.
+	- Since the SCRIPTS processor continues SCRIPTS execution after 
+	  having won arbitration, do some stuff prior to testing any SCSI 
+	  phase on reselection. This should have the vertue to process 
+	  scripts in parallel with the SCSI core performing selection.
+	- Increase the done queue to 12 entries.
+
+Sun Mar 29 12:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6h
+	- Some fixes.
+
+Tue Mar 26 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6g
+	- New done queue. 8 entries by default (6 always useable).
+	  Can be increased if needed.
+	- Resources management using doubly linked queues.
+	- New auto-sense and QUEUE FULL handling that does not need to 
+	  stall the NCR queue any more.
+	- New CCB starvation avoiding algorithm.
+	- Prepare CCBs for SCSI commands that cannot be queued, instead of 
+	  inserting these commands into the waiting list. The waiting list 
+	  is now only used while resetting and when memory for CCBs is not 
+	  yet available?
+
+Sun Feb 8 22:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6f
+	- Some fixes in order to really support the 53C895, at least with 
+	  FAST-20 devices.
+	- Heavy changes in the target/lun resources management to allow 
+	  the scripts to jump directly to the CCB on reselection instead 
+	  of walking on the lun CCBs list. Up to 32 tags per lun are now 
+	  supported without script processor and PCI traffic overhead.
+
+Sun Jan 11 22:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 2.6d
+	- new (different ?) implementation of the start queue:
+          Use a simple CALL to a launch script in the CCB.
+	- implement a minimal done queue (1 entry :-) ).
+          this avoid scanning all CCBs on INT FLY (Only scan all CCBs, on 
+          overflow). Hit ratio is better than 99.9 % on my system, so no 
+          need to have a larger done queue.
+	- generalization of the restart of CCB on special condition as 
+          Abort, QUEUE FULL, CHECK CONDITION.
+          This has been called 'silly scheduler'.
+	- make all the profiling code conditionned by a config option.
+	  This spare some PCI traffic and C code when this feature is not 
+          needed.
+	- handle more cleanly the situation where direction is unknown.
+	  The pointers patching is now performed by the SCRIPTS processor.
+	- remove some useless scripts instructions.
+
+	Ported from driver 2.5 series:
+        ------------------------------
+	- Use FAST-5 instead of SLOW for slow scsi devices according to 
+	  new SPI-2 draft.
+	- Make some changes in order to accomodate with 875 rev <= 3 
+	  device errata listing 397. Minor consequences are:
+	  . Leave use of PCI Write and Invalidate under user control.
+	    Now, by default the driver does not enable PCI MWI and option
+	    'specf:y' is required in order to enable this feature.
+	  . Memory Read Line is not enabled for 875 and 875-like chips.
+	  . Programmed burst length set to 64 DWORDS (instead of 128).
+	    (Note: SYMBIOS uses 32 DWORDS for the SDMS BIOS)
+	- Add 'buschk' boot option.
+	  This option enables checking of SCSI BUS data lines after SCSI 
+	  RESET (set by default). (Submitted by Richard Waltham).
+	- Update the README file.
+	- Dispatch CONDITION MET and RESERVATION CONFLICT scsi status 
+	  as OK driver status.
+	- Update the README file and the Symbios NVRAM format definition 
+	  with removable media flags values (available with SDMS 4.09).
+	- Several PCI configuration registers fix-ups for powerpc.
+	  (Patch sent by Cort).
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ChangeLog.sym53c8xx	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,593 @@
+Sat May 12 12:00 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.3c
+	- Ensure LEDC bit in GPCNTL is cleared when reading the NVRAM.
+	  Fix sent by Stig Telfer <stig@api-networks.com>.
+	- Backport from SYM-2 the work-around that allows to support 
+	  hardwares that fail PCI parity checking.
+	- Check that we received at least 8 bytes of INQUIRY response 
+	  for byte 7, that contains device capabilities, to be valid.
+	- Define scsi_set_pci_device() as nil for kernel < 2.4.4.
+	- + A couple of minor changes.
+	  
+Sat Apr 7 19:30 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.3b
+	- Fix an unaligned LOAD from scripts (was used as dummy read).
+	- In ncr_soft_reset(), only try to ABORT the current operation 
+	  for chips that support SRUN bit in ISTAT1 and if SCRIPTS are 
+	  currently running, as 896 and 1010 manuals suggest.
+	- In the CCB abort path, donnot assume that the CCB is currently 
+	  queued to SCRIPTS. This is not always true, notably after a 
+	  QUEUE FULL status or when using untagged commands.
+
+Sun Mar 4 18:30 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.3a
+	- Fix an issue in the ncr_int_udc() (unexpected disconnect)
+	  handling. If the DSA didn't match a CCB, a bad write to 
+	  memory could happen.
+
+Mon Feb 12 22:30 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.3
+	- Support for hppa.
+	  Tiny patch sent to me by Robert Hirst.
+	- Tiny patch for ia64 sent to me by Pamela Delaney.
+
+Tue Feb 6 13:30 2001 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.3-pre1
+	- Call pci_enable_device() as AC wants this to be done.
+	- Get both the BAR cookies used by CPU and actual PCI BAR 
+	  values used from SCRIPTS. Recent PCI chips are able to 
+	  access themselves using internal cycles, but they compare 
+	  BAR values to destination address to make decision.
+	  Earlier chips simply use PCI transactions to access IO 
+	  registers from SCRIPTS.
+	  The bus_dvma_to_mem() interface that reverses the actual 
+	  PCI BAR value from the BAR cookie is now useless.
+	  This point had been discussed at the list and the solution 
+	  got approved by PCI code maintainer (Martin Mares).
+	- Merge changes for linux-2.4 that declare the host template 
+	  in the driver object also when the driver is statically 
+	  linked with the kernel.
+	- Increase SCSI message size up to 12 bytes, given that 8 
+	  bytes was not enough for the PPR message (fix).
+	- Add field 'maxoffs_st' (max offset for ST data transfers).
+	  The C1010 supports offset 62 in DT mode but only 31 in 
+	  ST mode, to 2 different values for the max SCSI offset 
+	  are needed. Replace the obviously wrong masking of the 
+	  offset against 0x1f for ST mode by a lowering to 
+	  maxoffs_st of the SCSI offset in ST mode.
+	- Refine a work-around for the C1010-66. Revision 1 does 
+	  not requires extra cycles in DT DATA OUT phase.
+	- Add a missing endian-ization (abrt_tbl.addr).
+	- Minor clean-up in the np structure for fields accessed 
+	  from SCRIPTS that requires special alignments.
+
+Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.2
+	- Remove the hack for PPC added in previous driver version.
+	- Add FE_DAC feature bit to distinguish between 64 bit PCI 
+	  addressing (FE_DAC) and 64 bit PCI interface (FE_64BIT).
+	- Get rid of the boot command line "ultra:" argument.
+	  This parameter wasn't that clever since we can use "sync:" 
+	  for Ultra/Ultra2 settings, and for Ultra3 we may want to 
+	  pass PPR options (for now only DT clocking).
+	- Add FE_VARCLK feature bit that indicates that SCSI clock 
+	  frequency may vary depending on board design and thus, 
+	  the driver should try to evaluate the SCSI clock.
+	- Simplify the way the driver determine the SCSI clock:
+	  ULTRA3 -> 160 MHz, ULTRA2 -> 80 MHz otherwise 40 MHz.
+	  Measure the SCSI clock frequency if FE_VARCLK is set.
+	- Remove FE_CLK80 feature bit that got useless.
+	- Add support for the SYM53C875A (Pamela Delaney).
+
+Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.1
+	- Provide OpenFirmare path through the proc FS on PPC.
+	- Download of on-chip SRAM using memcpy_toio() doesn't work 
+	  on PPC. Restore previous method (MEMORY MOVE from SCRIPTS).
+	- Remove trailing argument #2 from a couple of #undefs.
+
+Sun Jul 09 16:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.7.0
+	- Remove the PROFILE C and SCRIPTS code.
+	  This facility was not this useful and thus was not longer 
+	  desirable given the increasing complexity of the driver code.
+	- Merges from FreeBSD sym-1.6.2 driver:
+	  * Clarify memory barriers needed by the driver for architectures 
+	    that implement a weak memory ordering.
+	  * Simpler handling of illegal phases and data overrun from 
+	    SCRIPTS. These errors are now immediately reported to 
+	    the C code by an interrupt.
+	  * Sync the residual handling code with sym-1.6.2 and now 
+	    report `resid' to user for linux version >= 2.3.99 
+	- General cleanup:
+	  Move definitions for barriers and IO/MMIO operations to the 
+	  sym53c8xx_defs.h header files. They are now shared by the 
+	  both drivers.
+	  Remove unused options that claimed to optimize for the 896.
+	  If fact, they were not this clever. :)
+	  Use SCSI_NCR_IOMAPPED instead of NCR_IOMAPPED.
+	  Remove a couple of unused fields from data structures.
+
+Thu May 11 12:40 2000 Pam Delaney (pam.delaney@lsil.com)
+	* version sym53c8xx-1.6b
+	- Merged version.
+
+Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5m
+	- Return value 1 (instead of 0) from the driver setup routine.
+	- Do not enable PCI DAC cycles. This just broke support for 
+	  SYM534C896 on sparc64. Problem fixed by David S. Miller.
+
+Fri Apr 14 9:00 2000 Pam Delaney (pam.delaney@lsil.com)
+	* version sym53c8xx-1.6b-9
+	- Added 53C1010_66 support.
+	- Small fix to integrity checking code.
+	- Removed requirement for integrity checking if want to run
+	  at ultra 3.
+ 
+Sat Apr 1  12:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5l
+	- Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that 
+	  applies to cache line size (? Probably from David S Miller).
+	- Make sure no data transfer will happen for Scsi_Cmnd requests 
+	  that supply SCSI_DATA_NONE direction (this avoids some BUG() 
+	  statement in the PCI code when a data buffer is also supplied).
+
+Sat Mar 11 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.6b-5
+	- Test against expected data transfer direction from SCRIPTS.
+	- Add support for the new dynamic dma mapping kernel interface.
+	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
+	  Many thanks to David S. Miller for his preliminary changes 
+	  that have been useful guidelines.
+	- Get data transfer direction from the scsi command structure 
+	  (Scsi_Cmnd) with kernels that provide this information.
+
+Mon Mar  6 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5k
+	- Test against expected data transfer direction from SCRIPTS.
+	- Revert the change in 'ncr_flush_done_cmds()' but unmap the 
+	  scsi dma buffer prior to queueing the command to our done 
+	  list.
+	- Miscellaneous (minor) fixes in the code added in driver 
+	  version 1.5j.
+
+Mon Feb 14 4:00 2000 Pam Delaney (pam.delaney@lsil.com)
+ 	* version sym53c8xx-pre-1.6b-2.
+	- Updated the SCRIPTS error handling of the SWIDE
+	  condition - to remove any reads of the sbdl
+	  register. Changes needed because the 896 and 1010
+	  chips will check parity in some special circumstances.
+	  This will cause a parity error interrupt if not in
+	  data phase.  Changes based on those made in the
+	  FreeBSD driver version 1.3.2.
+
+Sun Feb 20 11:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5j
+	- Add support for the new dynamic dma mapping kernel interface.
+	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
+	  Many thanks to David S. Miller for his preliminary changes 
+	  that have been useful guidelines, for having reviewed the 
+	  code and having tested this driver version on Ultra-Sparc.
+	- 2 tiny bugs fixed in the PCI wrapper that provides support 
+	  for early kernels without pci device structure.
+	- Get data transfer direction from the scsi command structure 
+	  (Scsi_Cmnd) with kernels that provide this information.
+	- Fix an old bug that only affected 896 rev. 1 when driver 
+	  profile support option was set in kernel configuration.
+
+Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
+ 	* version sym53c8xx-pre-1.6b-1.
+	- Merge parallel driver series 1.61 and 1.5e 
+
+Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
+	* version sym53c8xx-1.61
+	- Added support for mounting disks on wide-narrow-wide
+	  scsi configurations. 
+	- Modified offset to be a maximum of 31 in ST mode, 
+	  62 in DT mode.
+	- Based off of 1.60
+
+Mon Jan 10 10:00 2000 Pam Delaney (pam.delaney@lsil.com)
+	* version sym53c8xx-1.60
+	- Added capability to use the integrity checking code
+	  in the kernel (optional).
+	-  Added PPR negotiation.
+	- Added support for 53C1010 Ultra 3 part.
+	- Based off of 1.5f
+
+Sat Jan 8  22:00 2000 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5h
+	- Add year 2000 copyright.
+	- Display correctly bus signals when bus is detected wrong.
+	- Some fix for Sparc from DSM that went directly to kernel tree.
+
+Mon Dec 6  22:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5g
+	- Change messages written by the driver at initialisation and 
+	  through the /proc FS (rather cosmetic changes that consist in
+	  printing out the PCI bus number and PCI device/function).
+	- Ensure the SCRIPTS processor is stopped while calibrating the 
+	  SCSI clock (the initialisation code has been a bit reworked).
+	  Change moved to the FreeBSD sym_hipd driver).
+	- Some fixes in the MODIFY_DP/IGN_RESIDUE code and residual 
+	  calculation (moved from FreeBSD sym_hipd driver).
+	- Add NVRAM support for Tekram boards that use 24C16 EEPROM.
+	  Code moved from the FreeBSD sym_hipd driver, since it has 
+	  been that one that got this feature first.
+	- Definitely disable overlapped PCI arbitration for all dual 
+	  function chips, since I cannot make sure for what chip revisions 
+	  it is actually safe.
+	- Add support for the SYM53C1510D (also for ncr53c8xx).
+	- Fix up properly the PCI latency timer when needed or asked for.
+	- Get rid of the old PCI bios interface, but preserve kernel 2.0 
+	  compatibility from a simple wrapper.
+	- Update the poor Tekram sync factor table.
+	- Fix in a tiny 'printk' bug that may oops in case of extended 
+	  errors (unrecovered parity error, data overrun, etc ...)
+	  (Sent by Pamela Delaney from LSILOGIC)
+	- Remove the compilation condition about having to acquire the 
+	  io_request_lock since it seems to be a definite feature now.:)
+	- Change get_pages by GetPages since Linux >= 2.3.27 now wants 
+	  get_pages to ever be used as a kernel symbol (from 2.3.27).
+	- proc_dir structure no longer needed for kernel >= 2.3.27.
+
+Sun Oct  3  19:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5f
+	- Change the way the driver checks the PCI clock frequency, so 
+	  that overclocked PCI BUS up to 48 MHz will not be refused.
+	  The more the BUS is overclocked, the less the driver will 
+	  guarantee that its measure of the SCSI clock is correct.
+	- Backport some minor improvements of SCRIPTS from the sym_hipd 
+	  driver.
+	- Backport the code rewrite of the START QUEUE dequeuing (on 
+	  bad scsi status received) from the sym_hipd driver.
+
+Sat Sep 11  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5e
+	- New linux-2.3.13 __setup scheme support added.
+	- Cleanup of the extended error status handling:
+	  Use 1 bit per error type.
+	- Also save the extended error status prior to auto-sense.
+	- Add the FE_DIFF chip feature bit to indicate support of 
+	  diff probing from GPIO3 (825/825A/876/875).
+	- Remove the quirk handling that has been useless since day one.
+	- Work-around PCI chips being reported twice on some platforms.
+	- Add some redundant PCI reads in order to deal with common 
+	  bridge misbehaviour regarding posted write flushing.
+	- Add some other conditionnal code for people who have to deal 
+	  with really broken bridges (they will have to edit a source 
+	  file to try these options).
+	- Handle correctly (hopefully) jiffies wrap-around.
+	- Restore the entry used to detect 875 until revision 0xff.
+	  (I removed it inadvertently, it seems :) )
+	- Replace __initfunc() which is deprecated stuff by __init which 
+	  is not yet so. ;-)
+	- Rewrite the MESSAGE IN scripts more generic by using a MOVE 
+	  table indirect. Extended messages of any size are accepted now.
+	  (Size is limited to 8 for now, but a constant is just to be 
+	  increased if necessary)
+	- Fix some bug in the fully untested MDP handling:) and share 
+	  some code between MDP handling and residual calculation.
+	- Calculate the data transfer residual as the 2's complement 
+	  integer (A positive value in returned on data overrun, and 
+	  a negative one on underrun).
+	- Add support of some 'resource handling' for linux-2.3.13.
+	  Basically the BARs have been changed to something more complex 
+	  in the pci_dev structure.
+	- Remove some deprecated code.
+
+Sat Jun  5  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5c
+	- Do not negotiate on auto-sense if we are currently using 8 bit 
+	  async transfer for the target.
+	- Only check for SISL/RAID on i386 platforms.
+	  (A problem has been reported on PPC with that code).
+	- On MSG REJECT for a negotiation, the driver attempted to restart 
+	  the SCRIPT processor when this one was already running.
+
+Sat May 29  12:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5b
+	- Force negotiation prior auto-sense.
+	  This ensures that the driver will be able to grab the sense data 
+	  from a device that has received a BUS DEVICE RESET message from 
+	  another initiator.
+	- Complete all disconnected CCBs for a logical UNIT if we are told 
+	  about a UNIT ATTENTION for a RESET condition by this target.
+	- Add the control command 'cleardev' that allows to send a ABORT  
+	  message to a logical UNIT (for test purpose).
+
+Tue May 25  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5a
+	- Add support for task abort and bus device reset SCSI message 
+	  and implement proper synchonisation with SCRIPTS to handle 
+          correctly task abortion without races.
+	- Send an ABORT message (if untagged) or ABORT TAG message (if tagged)
+	  when the driver is told to abort a command that is disconnected and 
+	  complete the command with appropriate error.
+	  If the aborted command is not yet started, remove it from the start 
+	  queue and complete it with error.
+	- Add the control command 'resetdev' that allows to send a BUS 
+	  DEVICE RESET message to a target (for test purpose).
+	- Clean-up some unused or useless code.
+
+Fri May 21  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.5
+	- Add support for CHMOV with Wide controllers.
+	- Handling of the SWIDE (low byte residue at the end of a CHMOV 
+	  in DATA IN phase with WIDE transfer when the byte count gets odd).
+	- Handling of the IGNORE WIDE RESIDUE message.
+	  Handled from SCRIPTS as possible with some optimizations when both 
+	  a wide device and the controller are odd at the same time (SWIDE 
+	  present and IGNORE WIDE RESIDUE message on the BUS at the same time).
+	- Check against data OVERRUN/UNDERRUN condition at the end of a data 
+	  transfer, whatever a SWIDE is present (OVERRUN in DATA IN phase) 
+	  or the SODL is full (UNDERRUN in DATA out phase).
+	- Handling of the MODIFY DATA POINTER message.
+	  This one cannot be handled from SCRIPTS, but hopefully it will not
+	  happen very often. :)
+	- Large rewrite of the SCSI MESSAGE handling.
+
+Sun May 9  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.4
+	- Support for IMMEDIATE ARBITRATION.
+	  See the README file for detailed information about this feature.
+	  Requires both a compile option and a boot option.
+	- Minor SCRIPTS optimization in reselection pattern for LUN 0.
+	- Simpler algorithm to deal with SCSI command starvation.
+	  Just use 2 tag counters in flip/flop and switch to the other 
+	  one every 3 seconds.
+	- Do some work in SCRIPTS after the SELECT instruction and prior 
+	  to testing for a PHASE. SYMBIOS say this feature is working fine. 
+	  (Btw, only problems with Toshiba 3401B had been reported).
+	- Measure the PCI clock speed and do not attach controllers if 
+	  result is greater than 37 MHz. Since the precision of the 
+	  algorithm (from Stefan Esser) is better than 2%, this should 
+	  be fine.
+	- Fix the misdetection of SYM53C875E (was detected as a 876).
+	- Fix the misdetection of SYM53C810 not A (was detected as a 810A).
+	- Support for up to 256 TAGS per LUN (CMD_PER_LUN).
+	  Currently limited to 255 due to Linux limitation. :)
+	- Support for up to 508 active commands (CAN_QUEUE).
+	- Support for the 53C895A by Pamela Delaney <pam.delaney@lsil.com>
+	  The 53C895A contains all of the features of the 896 but has only 
+	  one channel and has a 32 bit PCI bus. It does 64 bit PCI addressing 
+	  using dual cycle PCI data transfers.
+	- Miscellaneous minor fixes.
+	- Some additions to the README.ncr53c8xx file.
+
+Tue Apr 15  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.3e
+	- Support for any number of LUNs (64) (SPI2-compliant).
+	  (Btw, this may only be ever useful under linux-2.2 ;-))
+
+Sun Apr 11  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.3d
+	- Add 'hostid:#id' boot option. This option allows to change the 
+	  default SCSI id the driver uses for controllers.
+	- Make SCRIPTS not use self-mastering for PCI.
+	  There were still 2 places the driver used this feature of the 
+	  53C8XX family.
+	- Move some data structures (nvram layouts and driver set-up) to 
+	  the sym53c8xx_defs.h file. So, the both drivers will share them.
+	- Set MAX LUNS to 16 (instead of 8).
+
+Sat Mar 20  21:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.3b
+	- Add support for NCR PQS PDS.
+	  James Bottomley <James.Bottomley@columbiasc.ncr.com>
+	- Allow value 0 for host ID.
+	- Support more than 8 controllers (> 40 in fact :-) )
+	- Add 'excl=#ioaddr' boot option: exclude controller.
+	  (Version 1.3a driver)
+
+Thu Mar 11  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.3   (8xx-896 driver bundle)
+	- Equivalent changes as ncr53c8xx-3.2 due to the driver bundle.
+	  (See Changelog.ncr53c8xx)
+	- Do a normal soft reset as first chip reset, since aborting current 
+	  operation may raise an interrupt we are not able to handle since 
+	  the interrupt handler is not yet established.
+
+Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.2b
+	- Fix some oooold bug that hangs the bus if a device rejects a 
+	  negotiation. Btw, the corresponding stuff also needed some cleanup 
+	  and thus the change is a bit larger than it could have been.
+	- Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb 21  20:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.2a
+	- The rewrite of the interrupt handling broke the SBMC interrupt 
+	  handling due to a 1 bit mask tiny error. Hopefully fixed.
+	- If INQUIRY came from a scatter list, the driver looked into 
+	  the scatterlist instead of the data.:) Since this should never
+	  happen, we just discard the data if use_sg is not zero.
+
+Fri Feb 12  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.2
+	- Major rewrite of the interrupt handling and recovery stuff for 
+	  the support of non compliant SCSI removal, insertion and all 
+	  kinds of screw-up that may happen on the SCSI BUS.
+	  Hopefully, the driver is now unbreakable or may-be, it is just 
+	  quite brocken. :-)
+	  Many thanks to Johnson Russel (Symbios) for having responded to 
+	  my questions and for his interesting advices and comments about 
+	  support of SCSI hot-plug.
+	- Add 'recovery' option to driver set-up.
+	- Negotiate SYNC data transfers with CCS devices.
+	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
+	  Pointed out by Leonard Zubkoff.
+
+Sun Jan 31  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.1a
+	- Some 896 chip revisions (all for now :-)), may hang-up if the 
+	  soft reset bit is set at the wrong time while SCRIPTS are running.
+	  We need to first abort the current SCRIPTS operation prior to 
+	  resetting the chip. This fix has been sent to me by SYMBIOS/LSI 
+	  and I just translated it into ncr53c8xx syntax.
+	  Must be considered 100 % trustable, unless I did some mistake 
+	  when translating it. :-)
+
+Sun Jan 24  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.1
+	- Major rewrite of the SCSI parity error handling.
+	  The informations contained in the data manuals are incomplete about 
+	  this feature.
+	  I asked SYMBIOS about and got in reply the explanations that are 
+	  _indeed_ missing in the data manuals.
+	- Allow to tune request_irq() flags from the boot command line using 
+	  ncr53c8xx=irqm:??, as follows:
+	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
+	  a 53C8XX adapter and a network board.
+	- Fix for 64 bit PCI address register calculation. (Lance Robinson)
+	- Fix for big-endian in phase mismatch handling. (Michal Jaegermann)
+
+Fri Jan  1  20:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.0a
+	- Waiting list look-up didn't work for the first command of the list.
+	  Hopefully fixed, but tested on paper only. ;)
+	- Remove the most part of PPC specific code for Linux-2.2.
+	  Thanks to Cort.
+	- Some other minors changes.
+
+Sat Dec 19  21:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version sym53c8xx-1.0
+	- Define some new IO registers for the 896 (istat1, mbox0, mbox1)
+	- Revamp slighly the Symbios NVRAM lay-out based on the excerpt of 
+	  the header file I received from Symbios.
+	- Check the PCI bus number for the boot order (Using a fast 
+	  PCI controller behing a PCI-PCI bridge seems sub-optimal).
+	- Disable overlapped PCI arbitration for the 896 revision 1.
+	- Reduce a bit the number of IO register reads for phase mismatch 
+	  by reading DWORDS at a time instead of BYTES.
+
+Thu Dec  3  24:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.18
+	- I received this afternoon a 896 from SYMBIOS and started testing  
+	  the driver with this beast. After having fixed 3 buglets, it worked  
+	  with all features enabled including the phase mismatch handling 
+	  from SCRIPTS. Since this feature is not yet tested enough, the 
+	  boot option 'ncr53c8xx=specf:1' is still required to enable the 
+	  driver to handle PM from SCRIPTS. 
+
+Sun Nov 29  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.17
+	- The SISL RAID change requires now remap_pci_mem() stuff to be 
+	  compiled for __i386__ when normal IOs are used.
+	- The PCI memory read from SCRIPTS that should ensure ordering 
+	  was in fact misplaced. BTW, this may explain why broken PCI 
+	  device drivers regarding ordering are working so well. ;-)
+	- Rewrite ncr53c8xx_setup (boot command line options) since the  
+	  binary code was a bit too bloated in my opinion.
+	- Make the code simpler in the wakeup_done routine.
+
+Tue Nov 24  23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.16
+	- Add SCSI_NCR_OPTIMIZE_896_1 compile option and 'optim' boot option.
+	  When set, the driver unconditionnaly assumes that the interrupt 
+	  handler is called for command completion, then clears INTF, scans 
+	  the done queue and returns if some completed CCB is found. If no 
+	  completed CCB are found, interrupt handling will proceed normally.
+	  With a 896 that handles MA from SCRIPTS, this can be a great win, 
+	  since the driver will never performs PCI read transactions, but 
+	  only PCI write transactions that may be posted.
+	  If the driver haven't to also raise the SIGP this would be perfect.
+	  Even with this penalty, I think that this will work great.
+	  Obviously this optimization makes sense only if the IRQ is not 
+	  shared with another device.
+	- Still a buglet in the tags initial settings that needed to be fixed.
+	  It was not possible to disable TGQ at system startup for devices 
+	  that claim TGQ support. The driver used at least 2 for the queue 
+	  depth but did'nt keep track of user settings for tags depth lower 
+	  than 2.
+
+Thu Nov 19  23:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.15
+	- Add support for hardware LED control of the 896.
+	- Ignore chips that are driven by SISL RAID (DAC 960).
+	  Change sent by Leonard Zubkoff and slightly reworked.
+	- Prevent 810A rev 11 and 860 rev 1 from using cache line based 
+	  transactions since those early chip revisions may use such on 
+	  LOAD/STORE instructions (work-around).
+	- Remove some useless and bloat code from the pci init stuff.
+	- Do not use the readX()/writeX() kernel functions for __i386__, 
+	  since they perform useless masking operations in order to deal 
+	  with broken driver in 2.1.X kernel.
+
+Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.14
+	- The driver was unhappy when configured with default_tags > MAX_TAGS
+	  Hopefully doubly-fixed.
+	- Set PCI_PARITY in PCI_COMMAND register in not set (PCI fix-up).
+	- Print out some message if phase mismatch is handled from SCRIPTS.
+
+Sun Nov 1  14H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.13
+	- Some rewrite of the device detection code. This code had been 
+	  patched too much and needed to be face-lifted a bit.
+	  Remove all platform dependant fix-ups that was not needed or
+	  conflicted with some other driver code as work-arounds.
+	  Reread the NVRAM before the calling of ncr_attach(). This spares 
+	  stack space and so allows to handle more boards.
+	  Handle 64 bit base addresses under linux-2.0.X.
+	  Set MASTER bit in PCI COMMAND register if not set.
+
+Wed Oct 30 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.12
+	- Damned! I just broke the driver for Alpha by leaving a stale 
+	  instruction in the source code. Hopefully fixed.
+	- Do not set PFEN when it is useless. Doing so we are sure that BOF 
+	  will be active, since the manual appears to be very unclear on what 
+	  feature is actually used by the chip when both PFEN and BOF are 
+	  set.
+
+Sat Oct 24 16H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.11
+	- LOAD/STORE instructions were miscompiled for register offsets 
+	  beyond 0x7f. This broke accesses to 896' new registers.
+	- Disable by default Phase Mismatch handling from SCRIPTS, since 
+	  current 896 rev.1 seems not to operate safely with the driver
+	  when this feature is enabled (and above LOAD/STORE fix applied).
+	  I will change the default to 'enabled' when this problem will be 
+	  solved.
+	  Using boot option 'ncr53c8xx=specf:1' enables this feature.
+	- Implement a work-around (DEL 472 - ITEM 5) that should allow the 
+	  driver to safely enable hardware phase mismatch with 896 rev. 1.
+
+Tue Oct 20 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.10
+	- Add the 53c876 description to the chip table. This is only useful 
+	  for printing the right name of the controller.
+	- Add additionnal checking of INQUIRY data:
+	  Check INQUIRY data received length is at least 7. Byte 7 of 
+	  inquiry data contains device features bits and the driver might 
+	  be confused by garbage. Also check peripheral qualifier.
+	- Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could  
+	  use any tag number from 1 to 253 and some non conformant devices  
+	  might have problems with large tag numbers.
+	- Use NAME53C and NAME53C8XX for chip name prefix chip family name.
+	  Just give a try using "sym53c" and "sym53c8xx" instead of "ncr53c" 
+	  and "ncr53c8xx". :-)
+
+Sun Oct 11 17H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.9
+	- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
+	- Break ncr_scatter() into 2 functions in order to guarantee best 
+	  possible code optimization for the case we get a scatter list.
+	- Add the code intended to support up to 1 tera-byte for 64 bit systems.
+	  It is probably too early, but I wanted to complete the thing.
+
+Sat Oct 3 14H00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* version pre-sym53c8xx-0.8
+	- Do some testing with io_mapped and fix what needed to be so.
+	- Wait for SCSI selection to complete or time-out immediately after 
+	  the chip won arbitration, since executing SCRIPTS while the SCSI 
+	  core is performing SCSI selection breaks the selection procedure 
+	  at least for some chip revisions.
+	- Interrupt the SCRIPTS if a device does not go to MSG OUT phase after 
+	  having been selected with ATN. Such a situation is not recoverable, 
+	  better to fail when we are stuck.
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx_2 b/Documentation/scsi/ChangeLog.sym53c8xx_2
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ChangeLog.sym53c8xx_2	Sun Nov 17 20:30:13 2002
@@ -0,0 +1,144 @@
+Sat Dec 30 21:30 2000 Gerard Roudier 
+	* version sym-2.1.0-20001230
+	- Initial release of SYM-2.
+
+Mon Jan 08 21:30 2001 Gerard Roudier 
+	* version sym-2.1.1-20010108
+	- Change a couple of defines containing ncr or NCR by their 
+	  equivalent containing sym or SYM instead.
+
+Sun Jan 14 22:30 2001 Gerard Roudier 
+	* version sym-2.1.2-20010114
+	- Fix a couple of printfs:
+	  * Add the target number to the display of transfer parameters.
+	  * Make the display of TCQ and queue depth clearer.
+
+Wed Jan 17 23:30 2001 Gerard Roudier 
+	* version sym-2.1.3-20010117
+	- Wrong residual values were returned in some situations.
+	  This broke cdrecord with linux-2.4.0, for example.
+
+Sat Jan 20 18:00 2001 Gerard Roudier 
+	* version sym-2.1.4-20010120
+	- Add year 2001 to Copyright.
+	- A tiny bug in the dma memory freeing path has been fixed.
+	  (Driver unload failed with a bad address reference).
+
+Wed Jan 24 21:00 2001 Gerard Roudier 
+	* version sym-2.1.5-20010124
+	- Make the driver work under Linux-2.4.x when statically linked 
+	  with the kernel.
+	- Check against memory allocation failure for SCRIPTZ and add the 
+	  missing free of this memory on instance detach.
+	- Check against GPIO3 pulled low for HVD controllers (driver did 
+	  just the opposite).
+	  Misdetection of BUS mode was triggerred on module reload only, 
+	  since BIOS settings were trusted instead on first load.
+
+Wed Feb 7 21:00 2001 Gerard Roudier 
+	* version sym-2.1.6-20010207
+	- Call pci_enable_device() as wished by kernel maintainers.
+	- Change the sym_queue_scsiio() interface.
+	  This is intended to simplify portability.
+	- Move the code intended to deal with the dowloading of SCRIPTS 
+	  from SCRIPTS :) in the patch method (was wrongly placed in 
+	  the SCRIPTS setup method).
+	- Add a missing cpu_to_scr()  (np->abort_tbl.addr)
+	- Remove a wrong cpu_to_scr() (np->targtbl_ba)
+	- Cleanup a bit the PPR failure recovery code.
+
+Sat Mar 3 21:00 2001 Gerard Roudier 
+	- Add option SYM_OPT_ANNOUNCE_TRANSFER_RATE and move the 
+	  corresponding code to file sym_misc.c.
+	  Also move the code that sniffes INQUIRY to sym_misc.c.
+	  This allows to share the corresponding code with NetBSD 
+	  without polluating the core driver source (sym_hipd.c).
+	- Add optionnal code that handles IO timeouts from the driver.
+	  (not used under Linux, but required for NetBSD)
+	- Donnot assume any longer that PAGE_SHIFT and PAGE_SIZE are 
+	  defined at compile time, as at least NetBSD uses variables 
+	  in memory for that.
+	- Refine a work-around for the C1010-33 that consists in 
+	  disabling internal LOAD/STORE. Was applied up to revision 1.
+	  Is now only applied to revision 0.
+	- Some code reorganisations due to code moves between files.
+
+Tues Apr 10 21:00 2001 Gerard Roudier 
+	* version sym-2.1.9-20010412
+	- Reset 53C896 and 53C1010 chip according to the manual.
+	  (i.e.: set the ABRT bit in ISTAT if SCRIPTS are running)
+	- Set #LUN in request sense only if scsi version <= 2 and
+	  #LUN <= 7.
+	- Set busy_itl in LCB to 1 if the LCB is allocated and a 
+	  SCSI command is active. This is a simplification.
+	- In sym_hcb_free(), donnot scan the free_ccbq if no CCBs 
+	  has been allocated. This fixes a panic if attach failed.
+	- Add DT/ST (double/simple transition) in the transfer 
+	  negotiation announce.
+	- Forces the max number of tasks per LUN to at least 64.
+	- Use pci_set_dma_mask() for linux-2.4.3 and above.
+	- A couple of comments fixes.
+
+Wed May 22:00 2001 Gerard Roudier 
+	* version sym-2.1.10-20010509
+	- Mask GPCNTL against 0x1c (was 0xfc) for the reading of the NVRAM.
+	  This ensure LEDC bit will not be set on 896 and later chips.
+	  Fix sent by Chip Salzenberg <chip@perlsupport.com>.
+	- Define the number of PQS BUSes supported.
+	  Fix sent by Stig Telfer <stig@api-networks.com>
+	- Miscellaneous common code rearrangements due to NetBSD accel 
+	  ioctl support, without impact on Linux (hopefully).
+
+Mon July 2 12:00 2001 Gerard Roudier 
+	* version sym-2.1.11-20010702
+	- Add Tekram 390 U2B/U2W SCSI LED handling.
+	  Submitted by Chip Salzenberg <chip@valinux.com>
+	- Add call to scsi_set_pci_device() for kernels >= 2.4.4.
+	- Check pci dma mapping failures and complete the IO with some 
+	  error when such mapping fails.
+	- Fill in instance->max_cmd_len for kernels > 2.4.0.
+	- A couple of tiny fixes ...
+
+Sun Sep 9 18:00 2001 Gerard Roudier 
+	* version sym-2.1.12-20010909
+	- Change my email address.
+	- Add infrastructure for the forthcoming 64 bit DMA adressing support.
+	  (Based on PCI 64 bit patch from David S. Miller)
+	- Donnot use anymore vm_offset_t type.
+
+Sat Sep 15 20:00 2001 Gerard Roudier 
+	* version sym-2.1.13-20010916
+	- Add support for 64 bit DMA addressing using segment registers.
+	  16 registers for up to 4 GB x 16 -> 64 GB.
+
+Sat Sep 22 12:00 2001 Gerard Roudier 
+	* version sym-2.1.14-20010922
+	- Complete rewrite of the eh handling. The driver is now using a 
+	  semaphore in order to behave synchronously as required by the eh 
+	  threads. A timer is also used to prevent from waiting indefinitely.
+
+Sun Sep 30 17:00 2001 Gerard Roudier 
+	* version sym-2.1.15-20010930
+	- Include <linux/module.h> unconditionnaly as expected by latest
+	  kernels.
+	- Use del_timer_sync() for recent kernels to kill the driver timer 
+	  on module release.
+
+Sun Oct 28 15:00 2001 Gerard Roudier 
+	* version sym-2.1.16-20011028
+	- Slightly simplify driver configuration.
+	- Prepare a new patch against linux-2.4.13.
+
+Sat Nov 17 10:00 2001 Gerard Roudier 
+	* version sym-2.1.17
+	- Fix a couple of gcc/gcc3 warnings.
+	- Allocate separately from the HCB the array for CCBs hashed by DSA.
+	  All driver memory allocations are now not greater than 1 PAGE 
+	  even on PPC64 / 4KB PAGE surprising setup.
+
+Sat Dec 01 18:00 2001 Gerard Roudier 
+	* version sym-2.1.17a
+	- Use u_long instead of U32 for the IO base cookie. This is more 
+	  consistent with what archs are expecting.
+	- Use MMIO per default for Power PC instead of some fake normal IO,
+	  as Paul Mackerras stated that MMIO works fine now on this arch.
diff -Nru a/Documentation/scsi/FlashPoint.txt b/Documentation/scsi/FlashPoint.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/FlashPoint.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,163 @@
+The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux.
+The upgrade program described below has been officially terminated effective
+31 March 1997 since it is no longer needed.
+
+
+
+	  MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS
+	      BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS
+
+
+FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux
+operating system support to its BusLogic brand of FlashPoint Ultra SCSI
+host adapters.  All of BusLogic's other SCSI host adapters, including the
+MultiMaster line, currently support the Linux operating system.  Linux
+drivers and information will be available on October 15th at
+http://www.dandelion.com/Linux/.
+
+"Mylex is committed to supporting the Linux community," says Peter Shambora,
+vice president of marketing for Mylex.  "We have supported Linux driver
+development and provided technical support for our host adapters for several
+years, and are pleased to now make our FlashPoint products available to this
+user base."
+
+The Linux Operating System
+
+Linux is a freely-distributed implementation of UNIX for Intel x86, Sun
+SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC
+machines.  It supports a wide range of software, including the X Window
+System, Emacs, and TCP/IP networking.  Further information is available at
+http://www.linux.org and http://www.ssc.com/linux.
+
+FlashPoint Host Adapters
+
+The FlashPoint family of Ultra SCSI host adapters, designed for workstation
+and file server environments, are available in narrow, wide, dual channel,
+and dual channel wide versions.  These adapters feature SeqEngine
+automation technology, which minimizes SCSI command overhead and reduces
+the number of interrupts generated to the CPU.
+
+About Mylex
+
+Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading
+producer of RAID technology and network management products.  The company
+produces high performance disk array (RAID) controllers, and complementary
+computer products for network servers, mass storage systems, workstations
+and system boards.  Through its wide range of RAID controllers and its
+BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling
+intelligent I/O technologies that increase network management control,
+enhance CPU utilization, optimize I/O performance, and ensure data security
+and availability.  Products are sold globally through a network of OEMs,
+major distributors, VARs, and system integrators.  Mylex Corporation is
+headquartered at 34551 Ardenwood Blvd., Fremont, CA.
+
+				   ####
+
+Contact:
+
+Peter Shambora
+Vice President of Marketing
+Mylex Corp.
+510/796-6100
+peters@mylex.com
+
+			       ANNOUNCEMENT
+	       BusLogic FlashPoint LT/BT-948 Upgrade Program
+			      1 February 1996
+
+			  ADDITIONAL ANNOUNCEMENT
+	       BusLogic FlashPoint LW/BT-958 Upgrade Program
+			       14 June 1996
+
+Ever since its introduction last October, the BusLogic FlashPoint LT has
+been problematic for members of the Linux community, in that no Linux
+drivers have been available for this new Ultra SCSI product.  Despite it's
+officially being positioned as a desktop workstation product, and not being
+particularly well suited for a high performance multitasking operating
+system like Linux, the FlashPoint LT has been touted by computer system
+vendors as the latest thing, and has been sold even on many of their high
+end systems, to the exclusion of the older MultiMaster products.  This has
+caused grief for many people who inadvertently purchased a system expecting
+that all BusLogic SCSI Host Adapters were supported by Linux, only to
+discover that the FlashPoint was not supported and would not be for quite
+some time, if ever.
+
+After this problem was identified, BusLogic contacted its major OEM
+customers to make sure the BT-946C/956C MultiMaster cards would still be
+made available, and that Linux users who mistakenly ordered systems with
+the FlashPoint would be able to upgrade to the BT-946C.  While this helped
+many purchasers of new systems, it was only a partial solution to the
+overall problem of FlashPoint support for Linux users.  It did nothing to
+assist the people who initially purchased a FlashPoint for a supported
+operating system and then later decided to run Linux, or those who had
+ended up with a FlashPoint LT, believing it was supported, and were unable
+to return it.
+
+In the middle of December, I asked to meet with BusLogic's senior
+management to discuss the issues related to Linux and free software support
+for the FlashPoint.  Rumors of varying accuracy had been circulating
+publicly about BusLogic's attitude toward the Linux community, and I felt
+it was best that these issues be addressed directly.  I sent an email
+message after 11pm one evening, and the meeting took place the next
+afternoon.  Unfortunately, corporate wheels sometimes grind slowly,
+especially when a company is being acquired, and so it's taken until now
+before the details were completely determined and a public statement could
+be made.
+
+BusLogic is not prepared at this time to release the information necessary
+for third parties to write drivers for the FlashPoint.  The only existing
+FlashPoint drivers have been written directly by BusLogic Engineering, and
+there is no FlashPoint documentation sufficiently detailed to allow outside
+developers to write a driver without substantial assistance.  While there
+are people at BusLogic who would rather not release the details of the
+FlashPoint architecture at all, that debate has not yet been settled either
+way.  In any event, even if documentation were available today it would
+take quite a while for a usable driver to be written, especially since I'm
+not convinced that the effort required would be worthwhile.
+
+However, BusLogic does remain committed to providing a high performance
+SCSI solution for the Linux community, and does not want to see anyone left
+unable to run Linux because they have a Flashpoint LT.  Therefore, BusLogic
+has put in place a direct upgrade program to allow any Linux user worldwide
+to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra
+SCSI Host Adapter.  The BT-948 is the Ultra SCSI successor to the BT-946C
+and has all the best features of both the BT-946C and FlashPoint LT,
+including smart termination and a flash PROM for easy firmware updates, and
+is of course compatible with the present Linux driver.  The price for this
+upgrade has been set at US $45 plus shipping and handling, and the upgrade
+program will be administered through BusLogic Technical Support, which can
+be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408
+654-0760, or by FAX at +1 408 492-1542.
+
+As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade
+program has now been extended to encompass the FlashPoint LW Wide Ultra
+SCSI Host Adapter.  Any Linux user worldwide may trade in their FlashPoint
+LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter.  The
+price for this upgrade has been set at US $65 plus shipping and handling.
+
+I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of
+my BusLogic driver already included latent support for the BT-948/958.
+Additional cosmetic support for the Ultra SCSI MultiMaster cards was added
+subsequent releases.  As a result of this cooperative testing process,
+several firmware bugs were found and corrected.  My heavily loaded Linux
+test system provided an ideal environment for testing error recovery
+processes that are much more rarely exercised in production systems, but
+are crucial to overall system stability.  It was especially convenient
+being able to work directly with their firmware engineer in demonstrating
+the problems under control of the firmware debugging environment; things
+sure have come a long way since the last time I worked on firmware for an
+embedded system.  I am presently working on some performance testing and
+expect to have some data to report in the not too distant future.
+
+BusLogic asked me to send this announcement since a large percentage of the
+questions regarding support for the FlashPoint have either been sent to me
+directly via email, or have appeared in the Linux newsgroups in which I
+participate.  To summarize, BusLogic is offering Linux users an upgrade
+from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US
+$45 plus shipping and handling, or from the unsupported FlashPoint LW
+(BT-950) to the supported BT-958 for $65 plus shipping and handling.
+Contact BusLogic Technical Support at techsup@buslogic.com or +1 408
+654-0760 to take advantage of their offer.
+
+		Leonard N. Zubkoff
+		lnz@dandelion.com
diff -Nru a/Documentation/scsi/LICENSE.FlashPoint b/Documentation/scsi/LICENSE.FlashPoint
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/LICENSE.FlashPoint	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,60 @@
+                     FlashPoint Driver Developer's Kit
+                                Version 1.0
+
+                   Copyright 1995-1996 by Mylex Corporation
+                            All Rights Reserved
+
+This program is free software; you may redistribute and/or modify it under
+the terms of either:
+
+    a) the GNU General Public License as published by the Free Software
+    Foundation; either version 2, or (at your option) any later version,
+
+    or
+
+    b) the "BSD-style License" included below.
+
+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 either the GNU General Public
+License or the BSD-style License below for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+675 Mass Ave, Cambridge, MA 02139, USA.
+
+The BSD-style License is as follows:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain this LICENSE.FlashPoint
+   file, without modification, this list of conditions, and the following
+   disclaimer.  The following copyright notice must appear immediately at
+   the beginning of all source files:
+
+        Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
+
+        This file is available under both the GNU General Public License
+        and a BSD-style copyright; see LICENSE.FlashPoint for details.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. The name of Mylex Corporation may not be used to endorse or promote
+   products derived from this software without specific prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY MYLEX CORP. ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff -Nru a/Documentation/scsi/Mylex.txt b/Documentation/scsi/Mylex.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/Mylex.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,5 @@
+Please see the file README.BusLogic for information about Linux support for
+Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters.
+
+The Mylex DAC960 PCI RAID Controllers are now supported.  Please consult
+http://www.dandelion.com/Linux/ for further information on the DAC960 driver.
diff -Nru a/Documentation/scsi/NinjaSCSI.txt b/Documentation/scsi/NinjaSCSI.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/NinjaSCSI.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,130 @@
+
+         WorkBiT NinjaSCSI-3/32Bi driver for Linux
+
+1. Comment
+ This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3
+(http://www.workbit.co.jp/ts/z_nj3r.html) and NinjaSCSI-32Bi
+(http://www.workbit.co.jp/ts/z_njsc32bi.html) PCMCIA card driver module
+for Linux.
+
+2. My Linux environment
+Linux kernel: 2.4.7 / 2.2.19
+pcmcia-cs:    3.1.27
+gcc:          gcc-2.95.4
+PC card:      I-O data PCSC-F (NinjaSCSI-3)
+              I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi)
+SCSI device:  I-O data CDPS-PX24 (CD-ROM drive)
+              Media Intelligent MMO-640GT (Optical disk drive)
+
+3. Install
+[1] Check your PC card is true "NinjaSCSI-3" card.
+    If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN
+    card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to
+    your console or log file.
+    You can also use "cardctl" program (this program is in pcmcia-cs source
+    code) to get more info.
+
+# cat /var/log/messgaes
+...
+Jan  2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1
+Jan  2 03:45:06 lindberg cardmgr[78]:   product info: "WBT", "NinjaSCSI-3", "R1.0"
+...
+# cardctl ident
+Socket 0:
+  no product info available
+Socket 1:
+  product info: "IO DATA", "CBSC16       ", "1"
+
+
+[2] Get Linux kernel source, and extract it to /usr/src.
+    Because NinjaSCSI driver requiers some SCSI header files in Linux kernel
+    source.
+    I recomend rebuilding your kernel. This eliminate some versioning problem.
+$ cd /usr/src
+$ tar -zxvf linux-x.x.x.tar.gz
+$ cd linux
+$ make config
+...
+
+[3] If you use this driver with Kernel 2.2, Unpack pcmcia-cs in some directory
+    and make & install. This driver requies pcmcia-cs header file.
+$ cd /usr/src
+$ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz
+...
+
+[4] Extract this driver's archive somewhere, and edit Makefile, then do make.
+$ tar -zxvf nsp_cs-x.x.tar.gz
+$ cd nsp_cs-x.x
+$ emacs Makefile
+...
+$ make
+
+[5] Copy nsp_cs.o to suitable plase, like /lib/modules/<Kernel version>/pcmcia/ .
+
+[6] Add these lines to /etc/pcmcia/config .
+    If you yse pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file.
+    So, you don't need to edit file. Just copy to /etc/pcmcia/ .
+
+-------------------------------------
+device "nsp_cs"
+  class "scsi" module "nsp_cs"
+
+card "WorkBit NinjaSCSI-3"
+  version "WBT", "NinjaSCSI-3", "R1.0"
+  bind "nsp_cs"
+
+card "WorkBit NinjaSCSI-32Bi (16bit)"
+  version "WORKBIT", "UltraNinja-16", "1"
+  bind "nsp_cs"
+
+# OEM
+card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA"
+  version "IO DATA", "CBSC16       ", "1"
+  bind "nsp_cs"
+
+# OEM
+card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1"
+  version "KME    ", "SCSI-CARD-001", "1"
+  bind "nsp_cs"
+card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2"
+  version "KME    ", "SCSI-CARD-002", "1"
+  bind "nsp_cs"
+card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3"
+  version "KME    ", "SCSI-CARD-003", "1"
+  bind "nsp_cs"
+card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4"
+  version "KME    ", "SCSI-CARD-004", "1"
+  bind "nsp_cs"
+-------------------------------------
+
+[7] Start (or restart) pcmcia-cs.
+# /etc/rc.d/rc.pcmcia start        (BSD style)
+or
+# /etc/init.d/pcmcia start         (SYSV style)
+
+
+4. History
+See README.nin_cs .
+
+5. Caution
+ If you eject card when doing some operation for your SCSI device or suspend
+your computer, you encount some *BAD* error like disk crash.
+ It works good when I using this driver right way. But I'm not guarantee
+your data. Please backup your data when you use this driver.
+
+6. Known Bugs
+ In 2.4 kernel, you can't use 640MB Optical disk. This error comes from
+high level SCSI driver.
+
+7. Testing
+ Please send me some reports(bug reports etc..) of this software.
+When you send report, please tell me these or more.
+	card name
+	kernel version
+	your SCSI device name(hard drive, CD-ROM, etc...)
+
+8. Copyright
+ See GPL.
+
+
+2001/08/08 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi>
diff -Nru a/Documentation/scsi/aha152x.txt b/Documentation/scsi/aha152x.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/aha152x.txt	Sun Nov 17 20:30:12 2002
@@ -0,0 +1,183 @@
+$Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $
+Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x)
+
+Copyright 1993-1999 Jürgen Fischer <fischer@norbit.de>
+TC1550 patches by Luuk van Dijk (ldz@xs4all.nl)
+
+
+In Revision 2 the driver was modified a lot (especially the
+bottom-half handler complete()).
+
+The driver is much cleaner now, has support for the new
+error handling code in 2.3, produced less cpu load (much
+less polling loops), has slightly higher throughput (at
+least on my ancient test box; a i486/33Mhz/20MB).
+
+
+CONFIGURATION ARGUMENTS:
+
+IOPORT        base io address                           (0x340/0x140)
+IRQ           interrupt level                           (9-12; default 11)
+SCSI_ID       scsi id of controller                     (0-7; default 7)
+RECONNECT     allow targets to disconnect from the bus  (0/1; default 1 [on])
+PARITY        enable parity checking                    (0/1; default 1 [on])
+SYNCHRONOUS   enable synchronous transfers              (0/1; default 1 [on])
+DELAY:        bus reset delay                           (default 100)
+EXT_TRANS:    enable extended translation               (0/1: default 0 [off])
+              (see NOTES)
+
+COMPILE TIME CONFIGURATION (go into AHA152X in drivers/scsi/Makefile):
+
+-DAUTOCONF
+ use configuration the controller reports (AHA-152x only)
+
+-DSKIP_BIOSTEST
+ Don't test for BIOS signature (AHA-1510 or disabled BIOS)
+
+-DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
+ override for the first controller 
+
+-DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
+ override for the second controller
+
+-DAHA152X_DEBUG
+ enable debugging output
+
+-DAHA152X_STAT
+ enable some statistics
+
+
+LILO COMMAND LINE OPTIONS:
+
+aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY> [,<EXT_TRANS]]]]]]]
+
+ The normal configuration can be overridden by specifying a command line.
+ When you do this, the BIOS test is skipped. Entered values have to be
+ valid (known).  Don't use values that aren't supported under normal
+ operation.  If you think that you need other values: contact me.
+ For two controllers use the aha152x statement twice.
+
+
+SYMBOLS FOR MODULE CONFIGURATION:
+
+Choose from 2 alternatives:
+
+1. specify everything (old)
+
+aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
+  configuration override for first controller
+
+
+aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
+  configuration override for second controller
+
+2. specify only what you need to (irq or io is required; new)
+
+io=IOPORT0[,IOPORT1]
+  IOPORT for first and second controller
+
+irq=IRQ0[,IRQ1]
+  IRQ for first and second controller
+
+scsiid=SCSIID0[,SCSIID1]
+  SCSIID for first and second controller
+
+reconnect=RECONNECT0[,RECONNECT1]
+  allow targets to disconnect for first and second controller
+
+parity=PAR0[PAR1]
+  use parity for first and second controller
+
+sync=SYNCHRONOUS0[,SYNCHRONOUS1]
+  enable synchronous transfers for first and second controller
+
+delay=DELAY0[,DELAY1]
+  reset DELAY for first and second controller
+
+exttrans=EXTTRANS0[,EXTTRANS1]
+  enable extended translation for first and second controller
+
+
+If you use both alternatives the first will be taken.
+
+
+NOTES ON EXT_TRANS: 
+
+SCSI uses block numbers to address blocks/sectors on a device.
+The BIOS uses a cylinder/head/sector addressing scheme (C/H/S)
+scheme instead.  DOS expects a BIOS or driver that understands this
+C/H/S addressing.
+
+The number of cylinders/heads/sectors is called geometry and is required
+as base for requests in C/H/S addressing.  SCSI only knows about the
+total capacity of disks in blocks (sectors).
+
+Therefore the SCSI BIOS/DOS driver has to calculate a logical/virtual
+geometry just to be able to support that addressing scheme.  The geometry
+returned by the SCSI BIOS is a pure calculation and has nothing to
+do with the real/physical geometry of the disk (which is usually
+irrelevant anyway).
+
+Basically this has no impact at all on Linux, because it also uses block
+instead of C/H/S addressing.  Unfortunately C/H/S addressing is also used
+in the partition table and therefore every operating system has to know
+the right geometry to be able to interpret it.
+
+Moreover there are certain limitations to the C/H/S addressing scheme,
+namely the address space is limited to upto 255 heads, upto 63 sectors
+and a maximum of 1023 cylinders.
+
+The AHA-1522 BIOS calculates the geometry by fixing the number of heads
+to 64, the number of sectors to 32 and by calculating the number of
+cylinders by dividing the capacity reported by the disk by 64*32 (1 MB).
+This is considered to be the default translation.
+
+With respect to the limit of 1023 cylinders using C/H/S you can only
+address the first GB of your disk in the partition table.  Therefore
+BIOSes of some newer controllers based on the AIC-6260/6360 support
+extended translation.  This means that the BIOS uses 255 for heads,
+63 for sectors and then divides the capacity of the disk by 255*63
+(about 8 MB), as soon it sees a disk greater than 1 GB.  That results
+in a maximum of about 8 GB addressable diskspace in the partition table
+(but there are already bigger disks out there today).
+
+To make it even more complicated the translation mode might/might
+not be configurable in certain BIOS setups.
+
+This driver does some more or less failsafe guessing to get the
+geometry right in most cases:
+
+- for disks<1GB: use default translation (C/32/64)
+
+- for disks>1GB:
+  - take current geometry from the partition table
+    (using scsicam_bios_param and accept only `valid' geometries,
+    ie. either (C/32/64) or (C/63/255)).  This can be extended translation
+    even if it's not enabled in the driver.
+
+  - if that fails, take extended translation if enabled by override,
+    kernel or module parameter, otherwise take default translation and
+    ask the user for verification.  This might on not yet partitioned
+    disks.
+
+
+REFERENCES USED:
+
+ "AIC-6260 SCSI Chip Specification", Adaptec Corporation.
+
+ "SCSI COMPUTER SYSTEM INTERFACE - 2 (SCSI-2)", X3T9.2/86-109 rev. 10h
+
+ "Writing a SCSI device driver for Linux", Rik Faith (faith@cs.unc.edu)
+
+ "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu)
+
+ "Adaptec 1520/1522 User's Guide", Adaptec Corporation.
+
+ Michael K. Johnson (johnsonm@sunsite.unc.edu)
+
+ Drew Eckhardt (drew@cs.colorado.edu)
+
+ Eric Youngdale (eric@andante.org) 
+
+ special thanks to Eric Youngdale for the free(!) supplying the
+ documentation on the chip.
diff -Nru a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/aic7xxx.txt	Sun Nov 17 20:30:14 2002
@@ -0,0 +1,477 @@
+			    AIC7xxx Driver for Linux
+
+Introduction
+----------------------------
+The AIC7xxx SCSI driver adds support for Adaptec (http://www.adaptec.com)
+SCSI controllers and chipsets. Major portions of the driver and driver
+development are shared between both Linux and FreeBSD. Support for the
+AIC-7xxx chipsets have been in the default Linux kernel since approximately
+linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
+2.1.0 or later.
+
+  Supported cards/chipsets
+  ----------------------------
+    Adaptec Cards
+    ----------------------------
+    AHA-274x
+    AHA-274xT
+    AHA-274xW
+    AHA-284x
+    AHA-284xW
+    All PCI based cards using any of the chipsets listed under motherboard
+    chipsets.  In general, this means *all* of the Adaptec SCSI controllers
+    except the ones specifically excluded later on in this document.
+
+    Motherboard Chipsets
+    ----------------------------
+    AIC-777x
+    AIC-785x
+    AIC-786x
+    AIC-787x
+    AIC-788x
+    AIC-789x
+    AIC-3860
+
+    Bus Types
+    ----------------------------
+    W - Wide SCSI, SCSI-3, 16bit bus, 68pin connector, will also support
+        SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
+    U - Ultra SCSI, transfer rates up to 40MB/s.
+    U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
+    U3- Ultra 3 SCSI, transfer rates up to 160MB/s.
+    D - Differential SCSI.
+    T - Twin Channel SCSI. Up to 14 SCSI devices.
+
+    AHA-274x - EISA SCSI controller
+    AHA-284x - VLB SCSI controller
+    AHA-29xx - PCI SCSI controller
+    AHA-39xx - PCI controllers with multiple separate SCSI channels on-board.
+
+  Not Supported Devices
+  ------------------------------
+    Adaptec Cards
+    ----------------------------
+    AHA-2920 (Only the cards that use the Future Domain chipset are not
+              supported, any 2920 cards based on Adaptec AIC chipsets,
+	      such as the 2920C, are supported)
+    AAA-13x Raid Adapters
+    AAA-113x Raid Port Card
+
+    Motherboard Chipsets
+    ----------------------------
+    AIC-781x
+
+    Bus Types
+    ----------------------------
+    R - Raid Port busses are not supported.
+
+    The hardware RAID devices sold by Adaptec are *NOT* supported by this
+    driver (and will people please stop emailing me about them, they are
+    a totally separate beast from the bare SCSI controllers and this driver
+    can not be retrofitted in any sane manner to support the hardware RAID
+    features on those cards - Doug Ledford).
+    
+
+  People
+  ------------------------------
+    Justin T Gibbs  gibbs@plutotech.com
+      (BSD Driver Author)
+    Dan Eischen     deischen@iworks.InterWorks.org
+      (Original Linux Driver Co-maintainer)
+    Dean Gehnert    deang@teleport.com
+      (Original Linux FTP/patch maintainer)
+    Jess Johnson    jester@frenzy.com
+      (AIC7xxx FAQ author)
+    Doug Ledford    dledford@redhat.com
+      (Current Linux aic7xxx-5.x.x Driver/Patch/FTP maintainer)
+    
+    Special thanks go to John Aycock (aycock@cpsc.ucalgary.ca), the original
+    author of the driver. John has since retired from the project. Thanks
+    again for all his work!
+    
+  Mailing list
+  ------------------------------
+    There is a mailing list available for users who want to track development
+    and converse with other users and developers. This list is for both
+    FreeBSD and Linux support of the AIC7xxx chipsets.
+
+    To subscribe to the AIC7xxx mailing list send mail to the list server,
+    with "subscribe AIC7xxx" in the body (no Subject: required):
+        To: majordomo@FreeBSD.ORG
+        ---
+        subscribe AIC7xxx
+
+    To unsubscribe from the list, send mail to the list server with:
+        To: majordomo@FreeBSD.ORG
+        ---
+        unsubscribe AIC7xxx
+
+    Send regular messages and replies to: AIC7xxx@FreeBSD.ORG
+    
+  Boot Command line options
+  ------------------------------
+    "aic7xxx=no_reset" -  Eliminate the SCSI bus reset during startup.
+        Some SCSI devices need the initial reset that this option disables
+	in order to work.  If you have problems at bootup, please make sure
+	you aren't using this option.
+	
+    "aic7xxx=reverse_scan" - Certain PCI motherboards scan for devices at
+        bootup by scanning from the highest numbered PCI device to the
+	lowest numbered PCI device, others do just the opposite and scan
+	from lowest to highest numbered PCI device.  There is no reliable
+	way to autodetect this ordering.  So, we default to the most common
+	order, which is lowest to highest.  Then, in case your motherboard
+	scans from highest to lowest, we have this option.  If your BIOS
+	finds the drives on controller A before controller B but the linux
+	kernel finds your drives on controller B before A, then you should
+	use this option.
+	
+    "aic7xxx=extended" - Force the driver to detect extended drive translation
+        on your controller.  This helps those people who have cards without
+        a SEEPROM make sure that linux and all other operating systems think
+        the same way about your hard drives.
+
+    "aic7xxx=scbram" - Some cards have external SCB RAM that can be used to
+        give the card more hardware SCB slots.  This allows the driver to use
+	that SCB RAM.  Without this option, the driver won't touch the SCB
+	RAM because it is known to cause problems on a few cards out there
+	(such as 3985 class cards).
+	
+    "aic7xxx=irq_trigger:x" - Replace x with either 0 or 1 to force the kernel
+        to use the correct IRQ type for your card.  This only applies to EISA
+        based controllers.  On these controllers, 0 is for Edge triggered
+        interrupts, and 1 is for Level triggered interrupts.  If you aren't
+        sure or don't know which IRQ trigger type your EISA card uses, then
+        let the kernel autodetect the trigger type.
+	
+    "aic7xxx=verbose" - This option can be used in one of two ways.  If you
+        simply specify aic7xxx=verbose, then the kernel will automatically
+	pick the default set of verbose messages for you to see.
+	Alternatively, you can specify the command as 
+	"aic7xxx=verbose:0xXXXX" where the X entries are replaced with
+	hexadecimal digits.  This option is a bit field type option.  For
+	a full listing of the available options, search for the 
+	#define VERBOSE_xxxxxx lines in the aic7xxx.c file.  If you want
+	verbose messages, then it is recommended that you simply use the
+	aic7xxx=verbose variant of this command.
+	
+    "aic7xxx=pci_parity:x" - This option controls whether or not the driver
+        enables PCI parity error checking on the PCI bus.  By default, this
+        checking is disabled.  To enable the checks, simply specify pci_parity
+        with no value afterwords.  To reverse the parity from even to odd,
+        supply any number other than 0 or 255.  In short:
+          pci_parity     - Even parity checking (even is the normal PCI parity)
+          pci_parity:x   - Where x > 0, Odd parity checking
+          pci_parity:0   - No check (default)
+        NOTE: In order to get Even PCI parity checking, you must use the
+        version of the option that does not include the : and a number at
+        the end (unless you want to enter exactly 2^32 - 1 as the number).
+	
+    "aic7xxx=no_probe" - This option will disable the probing for any VLB
+        based 2842 controllers and any EISA based controllers.  This is
+	needed on certain newer motherboards where the normal EISA I/O ranges
+	have been claimed by other PCI devices.  Probing on those machines
+	will often result in the machine crashing or spontaneously rebooting
+	during startup.  Examples of machines that need this are the
+	Dell PowerEdge 6300 machines.
+
+    "aic7xxx=seltime:2" - This option controls how long the card waits
+        during a device selection sequence for the device to respond.
+	The original SCSI spec says that this "should be" 256ms.  This
+	is generally not required with modern devices.  However, some
+	very old SCSI I devices need the full 256ms.  Most modern devices
+	can run fine with only 64ms.  The default for this option is
+	64ms.  If you need to change this option, then use the following
+	table to set the proper value in the example above:
+	  0  -  256ms
+	  1  -  128ms
+	  2  -   64ms
+	  3  -   32ms
+	
+    "aic7xxx=panic_on_abort" - This option is for debugging and will cause
+        the driver to panic the linux kernel and freeze the system the first
+	time the drivers abort or reset routines are called.  This is most
+	helpful when some problem causes infinite reset loops that scroll too
+	fast to see.  By using this option, you can write down what the errors
+	actually are and send that information to me so it can be fixed.
+	
+    "aic7xxx=dump_card" - This option will print out the *entire* set of
+        configuration registers on the card during the init sequence.  This
+	is a debugging aid used to see exactly what state the card is in
+	when we finally finish our initialization routines.  If you don't
+	have documentation on the chipsets, this will do you absolutely
+	no good unless you are simply trying to write all the information
+	down in order to send it to me.
+	
+    "aic7xxx=dump_sequencer" - This is the same as the above options except
+        that instead of dumping the register contents on the card, this
+	option dumps the contents of the sequencer program RAM.  This gives
+	the ability to verify that the instructions downloaded to the
+	card's sequencer are indeed what they are suppossed to be.  Again,
+	unless you have documentation to tell you how to interpret these
+	numbers, then it is totally useless.
+	
+    "aic7xxx=override_term:0xffffffff" - This option is used to force the
+    	termination on your SCSI controllers to a particular setting.  This
+	is a bit mask variable that applies for up to 8 aic7xxx SCSI channels.
+	Each channel gets 4 bits, divided as follows:
+	bit   3   2   1   0
+	      |   |   |   Enable/Disable Single Ended Low Byte Termination
+	      |   |   En/Disable Single Ended High Byte Termination
+	      |   En/Disable Low Byte LVD Termination
+	      En/Disable High Byte LVD Termination
+
+	The upper 2 bits that deal with LVD termination only apply to Ultra2
+	controllers.  Futhermore, due to the current Ultra2 controller
+	designs, these bits are tied together such that setting either bit
+	enables both low and high byte LVD termination.  It is not possible
+	to only set high or low byte LVD termination in this manner.  This is
+	an artifact of the BIOS definition on Ultra2 controllers.  For other
+	controllers, the only important bits are the two lowest bits.  Setting
+	the higher bits on non-Ultra2 controllers has no effect.  A few
+	examples of how to use this option:
+
+	Enable low and high byte termination on a non-ultra2 controller that
+	is the first aic7xxx controller (the correct bits are 0011), 
+	aic7xxx=override_term:0x3
+
+	Enable all termination on the third aic7xxx controller, high byte
+	termination on the second aic7xxx controller, and low and high byte
+	SE termination on the first aic7xxx controller 
+	(bits are 1111 0010 0011), 
+	aic7xxx=override_term:0xf23
+	
+	No attempt has been made to make this option non-cryptic.  It really
+	shouldn't be used except in dire circumstances, and if that happens,
+	I'm probably going to be telling you what to set this to anyway :)
+
+    "aic7xxx=stpwlev:0xffffffff" - This option is used to control the STPWLEV
+        bit in the DEVCONFIG PCI register.  Currently, this is one of the
+	very few registers that we have absolutely *no* way of detecting
+	what the variable should be.  It depends entirely on how the chipset
+	and external terminators were coupled by the card/motherboard maker.
+	Further, a chip reset (at power up) always sets this bit to 0.  If
+	there is no BIOS to run on the chipset/card (such as with a 2910C
+	or a motherboard controller with the BIOS totally disabled) then
+	the variable may not get set properly.  Of course, if the proper
+	setting was 0, then that's what it would be after the reset, but if
+	the proper setting is actually 1.....you get the picture.  Now, since
+	we can't detect this at all, I've added this option to force the
+	setting.  If you have a BIOS on your controller then you should never
+	need to use this option.  However, if you are having lots of SCSI
+	reset problems and can't seem to get them knocked out, this may help.
+
+	Here's a test to know for certain if you need this option.  Make
+	a boot floppy that you can use to boot your computer up and that
+	will detect the aic7xxx controller.  Next, power down your computer.
+	While it's down, unplug all SCSI cables from your Adaptec SCSI
+	controller.  Boot the system back up to the Adaptec EZ-SCSI BIOS
+	and then make sure that termination is enabled on your adapter (if
+	you have an Adaptec BIOS of course).  Next, boot up the floppy you
+	made and wait for it to detect the aic7xxx controller.  If the kernel
+	finds the controller fine, says scsi : x hosts and then tries to
+	detect your devices like normal, up to the point where it fails to
+	mount your root file system and panics, then you're fine.  If, on
+	the other hand, the system goes into an infinite reset loop, then
+	you need to use this option and/or the previous option to force the
+	proper termination settings on your controller.   If this happens,
+	then you next need to figure out what your settings should be.
+
+	To find the correct settings, power your machine back down, connect
+	back up the SCSI cables, and boot back into your machine like normal.
+	However, boot with the aic7xxx=verbose:0x39 option.  Record the
+	initial DEVCONFIG values for each of your aic7xxx controllers as
+	they are listed, and also record what the machine is detecting as
+	the proper termination on your controllers.  NOTE: the order in
+	which the initial DEVCONFIG values are printed out is not gauranteed
+	to be the same order as the SCSI controllers are registered.  The
+	above option and this option both work on the order of the SCSI
+	controllers as they are registered, so make sure you match the right
+	DEVCONFIG values with the right controllers if you have more than
+	one aic7xxx controller.
+
+	Once you have the detected termination settings and the initial
+	DEVCONFIG values for each controller, then figure out what the
+	termination on each of the controllers *should* be.  Hopefully, that
+	part is correct, but it could possibly be wrong if there is
+	bogus cable detection logic on your controller or something similar.
+	If all the controllers have the correct termination settings, then
+	don't set the aic7xxx=override_term variable at all, leave it alone.
+	Next, on any controllers that go into an infinite reset loop when
+	you unplug all the SCSI cables, get the starting DEVCONFIG value.
+	If the initial DEVCONFIG value is divisible by 2, then the correct
+	setting for that controller is 0.  If it's an odd number, then
+	the correct setting for that controller is 1.  For any other
+	controllers that didn't have an infinite reset problem, then reverse
+	the above options.  If DEVCONFIG was even, then the correct setting
+	is 1, if not then the correct setting is 0.
+
+	Now that you know what the correct setting was for each controller,
+	we need to encode that into the aic7xxx=stpwlev:0x... variable.
+	This variable is a bit field encoded variable.  Bit 0 is for the first
+	aic7xxx controller, bit 1 for the next, etc.  Put all these bits
+	together and you get a number.  For example, if the third aic7xxx
+	needed a 1, but the second and first both needed a 0, then the bits
+	would be 100 in binary.  This then translates to 0x04.  You would
+	therefore set aic7xxx=stpwlev:0x04.  This is fairly standard binary
+	to hexadecimal conversions here.  If you aren't up to speed on the
+	binary->hex conversion then send an email to the aic7xxx mailing
+	list and someone can help you out.
+
+    "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
+        or enable Tagged Command Queueing (TCQ) on specific devices.  As of
+	driver version 5.1.11, TCQ is now either on or off by default
+	according to the setting you choose during the make config process.
+	In order to en/disable TCQ for certian devices at boot time, a user
+	may use this boot param.  The driver will then parse this message out
+        and en/disable the specific device entries that are present based upon
+        the value given.  The param line is parsed in the following manner:
+
+          { - first instance indicates the start of this parameter values
+              second instance is the start of entries for a particular
+              device entry
+          } - end the entries for a particular host adapter, or end the entire
+              set of parameter entries
+          , - move to next entry.  Inside of a set of device entries, this
+              moves us to the next device on the list.  Outside of device
+              entries, this moves us to the next host adapter
+          . - Same effect as , but is safe to use with insmod.
+          x - the number to enter into the array at this position.  
+              0 = Enable tagged queueing on this device and use the default
+                  queue depth
+              1-254 = Enable tagged queueing on this device and use this
+                      number as the queue depth
+              255 = Disable tagged queueing on this device.
+              Note: anything above 32 for an actual queue depth is wasteful
+                    and not recommended.
+
+        A few examples of how this can be used:
+
+        tag_info:{{8,12,,0,,255,4}}
+          This line will only effect the first aic7xxx card registered.  It
+          will set scsi id 0 to a queue depth of 8, id 1 to 12, leave id 2
+          at the default, set id 3 to tagged queueing enabled and use the
+          default queue depth, id 4 default, id 5 disabled, and id 6 to 4.
+          Any not specified entries stay at the default value, repeated
+          commas with no value specified will simply increment to the next id
+          without changing anything for the missing values.
+
+        tag_info:{,,,{,,,255}}
+          First, second, and third adapters at default values.  Fourth
+          adapter, id 3 is disabled.  Notice that leading commas simply
+	  increment what the first number effects, and there are no need
+	  for trailing commas.  When you close out an adapter, or the
+	  entire entry, anything not explicitly set stays at the default
+	  value.
+
+        A final note on this option.  The scanner I used for this isn't
+        perfect or highly robust.  If you mess the line up, the worst that
+        should happen is that the line will get ignored.  If you don't
+        close out the entire entry with the final bracket, then any other
+        aic7xxx options after this will get ignored.  So, in general, be
+        sure of what you are entering, and after you have it right, just
+        add it to the lilo.conf file so there won't be any mistakes.  As
+        a means of checking this parser, the entire tag_info array for
+        each card is now printed out in the /proc/scsi/aic7xxx/x file.  You
+        can use that to verify that your options were parsed correctly. 
+        
+    Boot command line options may be combined to form the proper set of options
+    a user might need.  For example, the following is valid:
+    
+    aic7xxx=verbose,extended,irq_trigger:1
+    
+    The only requirement is that individual options be separated by a comma or
+    a period on the command line.
+        
+  Module Loading command options
+  ------------------------------
+    When loading the aic7xxx driver as a module, the exact same options are
+    available to the user.  However, the syntax to specify the options changes
+    slightly.  For insmod, you need to wrap the aic7xxx= argument in quotes
+    and replace all ',' with '.'.  So, for example, a valid insmod line
+    would be:
+
+    insmod aic7xxx aic7xxx='verbose.irq_trigger:1.extended'
+
+    This line should result in the *exact* same behaviour as if you typed
+    it in at the lilo prompt and the driver was compiled into the kernel
+    instead of being a module.  The reason for the single quote is so that
+    the shell won't try to interpret anything in the line, such as {. 
+    Insmod assumes any options starting with a letter instead of a number
+    is a character string (which is what we want) and by switching all of
+    the commas to periods, insmod won't interpret this as more than one
+    string and write junk into our binary image.  I consider it a bug in
+    the insmod program that even if you wrap your string in quotes (quotes
+    that pass the shell mind you and that insmod sees) it still treates
+    a comma inside of those quotes as starting a new variable, resulting
+    in memory scribbles if you don't switch the commas to periods.
+
+
+  Kernel Compile options
+  ------------------------------
+    The various kernel compile time options for this driver are now fairly
+    well documented in the file Documentation/Configure.help.  In order to
+    see this documentation, you need to use one of the advanced configuration
+    programs (menuconfig and xconfig).  If you are using the "make menuconfig"
+    method of configuring your kernel, then you would simply highlight the
+    option in question and hit the ? key.  If you are using the "make xconfig"
+    method of configuring your kernel, then simply click on the help button
+    next to the option you have questions about.  The help information from
+    the Configure.help file will then get automatically displayed.
+
+  /proc support
+  ------------------------------
+    The /proc support for the AIC7xxx can be found in the /proc/scsi/aic7xxx/
+    directory. That directory contains a file for each SCSI controller in
+    the system. Each file presents the current configuration and transfer
+    statistics (enabled with #define in aic7xxx.c) for each controller.
+
+    Thanks to Michael Neuffer for his upper-level SCSI help, and
+    Matthew Jacob for statistics support.
+
+  Debugging the driver
+  ------------------------------
+    Should you have problems with this driver, and would like some help in
+    getting them solved, there are a couple debugging items built into
+    the driver to facilitate getting the needed information from the system.
+    In general, I need a complete description of the problem, with as many
+    logs as possible concerning what happens.  To help with this, there is
+    a command option aic7xxx=panic_on_abort.  This option, when set, forces
+    the driver to panic the kernel on the first SCSI abort issued by the
+    mid level SCSI code.  If your system is going to reset loops and you
+    can't read the screen, then this is what you need.  Not only will it
+    stop the system, but it also prints out a large amount of state
+    information in the process.  Second, if you specify the option
+    "aic7xxx=verbose:0x1ffff", the system will print out *SOOOO* much
+    information as it runs that you won't be able to see anything.
+    However, this can actually be very useful if your machine simply
+    locks up when trying to boot, since it will pin-point what was last
+    happening (in regards to the aic7xxx driver) immediately prior to
+    the lockup.  This is really only useful if your machine simply can
+    not boot up successfully.  If you can get your machine to run, then
+    this will produce far too much information.
+
+  FTP sites
+  ------------------------------
+    ftp://ftp.redhat.com/pub/aic/
+      - Out of date.  I used to keep stuff here, but too many people
+        complained about having a hard time getting into Red Hat's ftp
+	server.  So use the web site below instead.
+    ftp://ftp.pcnet.com/users/eischen/Linux/
+      - Dan Eischen's driver distribution area
+    ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
+      - European Linux mirror of Teleport site
+
+  Web sites
+  ------------------------------
+    http://people.redhat.com/dledford/
+      - My web site, also the primary aic7xxx site with several related
+        pages.
+
+Dean W. Gehnert
+deang@teleport.com
+
+$Revision: 3.0 $
+
+Modified by Doug Ledford 1998-2000
+
diff -Nru a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/aic7xxx_old.txt	Sun Nov 17 20:30:14 2002
@@ -0,0 +1,511 @@
+			    AIC7xxx Driver for Linux
+
+Introduction
+----------------------------
+The AIC7xxx SCSI driver adds support for Adaptec (http://www.adaptec.com)
+SCSI controllers and chipsets. Major portions of the driver and driver
+development are shared between both Linux and FreeBSD. Support for the
+AIC-7xxx chipsets have been in the default Linux kernel since approximately
+linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
+2.1.0 or later.
+
+  Supported cards/chipsets
+  ----------------------------
+    Adaptec Cards
+    ----------------------------
+    AHA-274x
+    AHA-274xT               
+    AHA-2842
+    AHA-2910B               
+    AHA-2920C
+    AHA-2930
+    AHA-2930U
+    AHA-2930CU
+    AHA-2930U2
+    AHA-2940               
+    AHA-2940W              
+    AHA-2940U              
+    AHA-2940UW
+    AHA-2940UW-PRO
+    AHA-2940AU 
+    AHA-2940U2W
+    AHA-2940U2
+    AHA-2940U2B
+    AHA-2940U2BOEM
+    AHA-2944D              
+    AHA-2944WD
+    AHA-2944UD
+    AHA-2944UWD
+    AHA-2950U2
+    AHA-2950U2W
+    AHA-2950U2B
+    AHA-29160M
+    AHA-3940
+    AHA-3940U
+    AHA-3940W
+    AHA-3940UW
+    AHA-3940AUW
+    AHA-3940U2W
+    AHA-3950U2B
+    AHA-3950U2D
+    AHA-3960D
+    AHA-39160M
+    AHA-3985
+    AHA-3985U
+    AHA-3985W
+    AHA-3985UW
+
+    Motherboard Chipsets
+    ----------------------------
+    AIC-777x   
+    AIC-785x
+    AIC-786x
+    AIC-787x
+    AIC-788x
+    AIC-789x
+    AIC-3860
+
+    Bus Types
+    ----------------------------
+    W - Wide SCSI, SCSI-3, 16bit bus, 68pin connector, will also support
+        SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
+    U - Ultra SCSI, transfer rates up to 40MB/s.
+    U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
+    D - Differential SCSI.
+    T - Twin Channel SCSI. Up to 14 SCSI devices.
+
+    AHA-274x - EISA SCSI controller
+    AHA-284x - VLB SCSI controller
+    AHA-29xx - PCI SCSI controller
+    AHA-394x - PCI controllers with two separate SCSI controllers on-board.
+    AHA-398x - PCI RAID controllers with three separate SCSI controllers
+               on-board.
+
+  Not Supported Devices
+  ------------------------------
+    Adaptec Cards
+    ----------------------------
+    AHA-2920 (Only the cards that use the Future Domain chipset are not
+              supported, any 2920 cards based on Adaptec AIC chipsets,
+	      such as the 2920C, are supported)
+    AAA-13x Raid Adapters
+    AAA-113x Raid Port Card
+
+    Motherboard Chipsets
+    ----------------------------
+    AIC-7810
+
+    Bus Types
+    ----------------------------
+    R - Raid Port busses are not supported.
+
+    The hardware RAID devices sold by Adaptec are *NOT* supported by this
+    driver (and will people please stop emailing me about them, they are
+    a totally separate beast from the bare SCSI controllers and this driver
+    can not be retrofitted in any sane manner to support the hardware RAID
+    features on those cards - Doug Ledford).
+    
+
+  People
+  ------------------------------
+    Justin T Gibbs  gibbs@plutotech.com
+      (BSD Driver Author)
+    Dan Eischen     deischen@iworks.InterWorks.org
+      (Original Linux Driver Co-maintainer)
+    Dean Gehnert    deang@teleport.com
+      (Original Linux FTP/patch maintainer)
+    Jess Johnson    jester@frenzy.com
+      (AIC7xxx FAQ author)
+    Doug Ledford    dledford@redhat.com
+      (Current Linux aic7xxx-5.x.x Driver/Patch/FTP maintainer)
+    
+    Special thanks go to John Aycock (aycock@cpsc.ucalgary.ca), the original
+    author of the driver. John has since retired from the project. Thanks
+    again for all his work!
+    
+  Mailing list
+  ------------------------------
+    There is a mailing list available for users who want to track development
+    and converse with other users and developers. This list is for both
+    FreeBSD and Linux support of the AIC7xxx chipsets.
+
+    To subscribe to the AIC7xxx mailing list send mail to the list server,
+    with "subscribe AIC7xxx" in the body (no Subject: required):
+        To: majordomo@FreeBSD.ORG
+        ---
+        subscribe AIC7xxx
+
+    To unsubscribe from the list, send mail to the list server with:
+        To: majordomo@FreeBSD.ORG
+        ---
+        unsubscribe AIC7xxx
+
+    Send regular messages and replies to: AIC7xxx@FreeBSD.ORG
+    
+  Boot Command line options
+  ------------------------------
+    "aic7xxx=no_reset" -  Eliminate the SCSI bus reset during startup.
+        Some SCSI devices need the initial reset that this option disables
+	in order to work.  If you have problems at bootup, please make sure
+	you aren't using this option.
+	
+    "aic7xxx=reverse_scan" - Certain PCI motherboards scan for devices at
+        bootup by scanning from the highest numbered PCI device to the
+	lowest numbered PCI device, others do just the opposite and scan
+	from lowest to highest numbered PCI device.  There is no reliable
+	way to autodetect this ordering.  So, we default to the most common
+	order, which is lowest to highest.  Then, in case your motherboard
+	scans from highest to lowest, we have this option.  If your BIOS
+	finds the drives on controller A before controller B but the linux
+	kernel finds your drives on controller B before A, then you should
+	use this option.
+	
+    "aic7xxx=extended" - Force the driver to detect extended drive translation
+        on your controller.  This helps those people who have cards without
+        a SEEPROM make sure that linux and all other operating systems think
+        the same way about your hard drives.
+
+    "aic7xxx=scbram" - Some cards have external SCB RAM that can be used to
+        give the card more hardware SCB slots.  This allows the driver to use
+	that SCB RAM.  Without this option, the driver won't touch the SCB
+	RAM because it is known to cause problems on a few cards out there
+	(such as 3985 class cards).
+	
+    "aic7xxx=irq_trigger:x" - Replace x with either 0 or 1 to force the kernel
+        to use the correct IRQ type for your card.  This only applies to EISA
+        based controllers.  On these controllers, 0 is for Edge triggered
+        interrupts, and 1 is for Level triggered interrupts.  If you aren't
+        sure or don't know which IRQ trigger type your EISA card uses, then
+        let the kernel autodetect the trigger type.
+	
+    "aic7xxx=verbose" - This option can be used in one of two ways.  If you
+        simply specify aic7xxx=verbose, then the kernel will automatically
+	pick the default set of verbose messages for you to see.
+	Alternatively, you can specify the command as 
+	"aic7xxx=verbose:0xXXXX" where the X entries are replaced with
+	hexadecimal digits.  This option is a bit field type option.  For
+	a full listing of the available options, search for the 
+	#define VERBOSE_xxxxxx lines in the aic7xxx.c file.  If you want
+	verbose messages, then it is recommended that you simply use the
+	aic7xxx=verbose variant of this command.
+	
+    "aic7xxx=pci_parity:x" - This option controls whether or not the driver
+        enables PCI parity error checking on the PCI bus.  By default, this
+        checking is disabled.  To enable the checks, simply specify pci_parity
+        with no value afterwords.  To reverse the parity from even to odd,
+        supply any number other than 0 or 255.  In short:
+          pci_parity     - Even parity checking (even is the normal PCI parity)
+          pci_parity:x   - Where x > 0, Odd parity checking
+          pci_parity:0   - No check (default)
+        NOTE: In order to get Even PCI parity checking, you must use the
+        version of the option that does not include the : and a number at
+        the end (unless you want to enter exactly 2^32 - 1 as the number).
+	
+    "aic7xxx=no_probe" - This option will disable the probing for any VLB
+        based 2842 controllers and any EISA based controllers.  This is
+	needed on certain newer motherboards where the normal EISA I/O ranges
+	have been claimed by other PCI devices.  Probing on those machines
+	will often result in the machine crashing or spontaneously rebooting
+	during startup.  Examples of machines that need this are the
+	Dell PowerEdge 6300 machines.
+
+    "aic7xxx=seltime:2" - This option controls how long the card waits
+        during a device selection sequence for the device to respond.
+	The original SCSI spec says that this "should be" 256ms.  This
+	is generally not required with modern devices.  However, some
+	very old SCSI I devices need the full 256ms.  Most modern devices
+	can run fine with only 64ms.  The default for this option is
+	64ms.  If you need to change this option, then use the following
+	table to set the proper value in the example above:
+	  0  -  256ms
+	  1  -  128ms
+	  2  -   64ms
+	  3  -   32ms
+	
+    "aic7xxx=panic_on_abort" - This option is for debugging and will cause
+        the driver to panic the linux kernel and freeze the system the first
+	time the drivers abort or reset routines are called.  This is most
+	helpful when some problem causes infinite reset loops that scroll too
+	fast to see.  By using this option, you can write down what the errors
+	actually are and send that information to me so it can be fixed.
+	
+    "aic7xxx=dump_card" - This option will print out the *entire* set of
+        configuration registers on the card during the init sequence.  This
+	is a debugging aid used to see exactly what state the card is in
+	when we finally finish our initialization routines.  If you don't
+	have documentation on the chipsets, this will do you absolutely
+	no good unless you are simply trying to write all the information
+	down in order to send it to me.
+	
+    "aic7xxx=dump_sequencer" - This is the same as the above options except
+        that instead of dumping the register contents on the card, this
+	option dumps the contents of the sequencer program RAM.  This gives
+	the ability to verify that the instructions downloaded to the
+	card's sequencer are indeed what they are suppossed to be.  Again,
+	unless you have documentation to tell you how to interpret these
+	numbers, then it is totally useless.
+	
+    "aic7xxx=override_term:0xffffffff" - This option is used to force the
+    	termination on your SCSI controllers to a particular setting.  This
+	is a bit mask variable that applies for up to 8 aic7xxx SCSI channels.
+	Each channel gets 4 bits, divided as follows:
+	bit   3   2   1   0
+	      |   |   |   Enable/Disable Single Ended Low Byte Termination
+	      |   |   En/Disable Single Ended High Byte Termination
+	      |   En/Disable Low Byte LVD Termination
+	      En/Disable High Byte LVD Termination
+
+	The upper 2 bits that deal with LVD termination only apply to Ultra2
+	controllers.  Futhermore, due to the current Ultra2 controller
+	designs, these bits are tied together such that setting either bit
+	enables both low and high byte LVD termination.  It is not possible
+	to only set high or low byte LVD termination in this manner.  This is
+	an artifact of the BIOS definition on Ultra2 controllers.  For other
+	controllers, the only important bits are the two lowest bits.  Setting
+	the higher bits on non-Ultra2 controllers has no effect.  A few
+	examples of how to use this option:
+
+	Enable low and high byte termination on a non-ultra2 controller that
+	is the first aic7xxx controller (the correct bits are 0011), 
+	aic7xxx=override_term:0x3
+
+	Enable all termination on the third aic7xxx controller, high byte
+	termination on the second aic7xxx controller, and low and high byte
+	SE termination on the first aic7xxx controller 
+	(bits are 1111 0010 0011), 
+	aic7xxx=override_term:0xf23
+	
+	No attempt has been made to make this option non-cryptic.  It really
+	shouldn't be used except in dire circumstances, and if that happens,
+	I'm probably going to be telling you what to set this to anyway :)
+
+    "aic7xxx=stpwlev:0xffffffff" - This option is used to control the STPWLEV
+        bit in the DEVCONFIG PCI register.  Currently, this is one of the
+	very few registers that we have absolutely *no* way of detecting
+	what the variable should be.  It depends entirely on how the chipset
+	and external terminators were coupled by the card/motherboard maker.
+	Further, a chip reset (at power up) always sets this bit to 0.  If
+	there is no BIOS to run on the chipset/card (such as with a 2910C
+	or a motherboard controller with the BIOS totally disabled) then
+	the variable may not get set properly.  Of course, if the proper
+	setting was 0, then that's what it would be after the reset, but if
+	the proper setting is actually 1.....you get the picture.  Now, since
+	we can't detect this at all, I've added this option to force the
+	setting.  If you have a BIOS on your controller then you should never
+	need to use this option.  However, if you are having lots of SCSI
+	reset problems and can't seem to get them knocked out, this may help.
+
+	Here's a test to know for certain if you need this option.  Make
+	a boot floppy that you can use to boot your computer up and that
+	will detect the aic7xxx controller.  Next, power down your computer.
+	While it's down, unplug all SCSI cables from your Adaptec SCSI
+	controller.  Boot the system back up to the Adaptec EZ-SCSI BIOS
+	and then make sure that termination is enabled on your adapter (if
+	you have an Adaptec BIOS of course).  Next, boot up the floppy you
+	made and wait for it to detect the aic7xxx controller.  If the kernel
+	finds the controller fine, says scsi : x hosts and then tries to
+	detect your devices like normal, up to the point where it fails to
+	mount your root file system and panics, then you're fine.  If, on
+	the other hand, the system goes into an infinite reset loop, then
+	you need to use this option and/or the previous option to force the
+	proper termination settings on your controller.   If this happens,
+	then you next need to figure out what your settings should be.
+
+	To find the correct settings, power your machine back down, connect
+	back up the SCSI cables, and boot back into your machine like normal.
+	However, boot with the aic7xxx=verbose:0x39 option.  Record the
+	initial DEVCONFIG values for each of your aic7xxx controllers as
+	they are listed, and also record what the machine is detecting as
+	the proper termination on your controllers.  NOTE: the order in
+	which the initial DEVCONFIG values are printed out is not gauranteed
+	to be the same order as the SCSI controllers are registered.  The
+	above option and this option both work on the order of the SCSI
+	controllers as they are registered, so make sure you match the right
+	DEVCONFIG values with the right controllers if you have more than
+	one aic7xxx controller.
+
+	Once you have the detected termination settings and the initial
+	DEVCONFIG values for each controller, then figure out what the
+	termination on each of the controllers *should* be.  Hopefully, that
+	part is correct, but it could possibly be wrong if there is
+	bogus cable detection logic on your controller or something similar.
+	If all the controllers have the correct termination settings, then
+	don't set the aic7xxx=override_term variable at all, leave it alone.
+	Next, on any controllers that go into an infinite reset loop when
+	you unplug all the SCSI cables, get the starting DEVCONFIG value.
+	If the initial DEVCONFIG value is divisible by 2, then the correct
+	setting for that controller is 0.  If it's an odd number, then
+	the correct setting for that controller is 1.  For any other
+	controllers that didn't have an infinite reset problem, then reverse
+	the above options.  If DEVCONFIG was even, then the correct setting
+	is 1, if not then the correct setting is 0.
+
+	Now that you know what the correct setting was for each controller,
+	we need to encode that into the aic7xxx=stpwlev:0x... variable.
+	This variable is a bit field encoded variable.  Bit 0 is for the first
+	aic7xxx controller, bit 1 for the next, etc.  Put all these bits
+	together and you get a number.  For example, if the third aic7xxx
+	needed a 1, but the second and first both needed a 0, then the bits
+	would be 100 in binary.  This then translates to 0x04.  You would
+	therefore set aic7xxx=stpwlev:0x04.  This is fairly standard binary
+	to hexadecimal conversions here.  If you aren't up to speed on the
+	binary->hex conversion then send an email to the aic7xxx mailing
+	list and someone can help you out.
+
+    "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
+        or enable Tagged Command Queueing (TCQ) on specific devices.  As of
+	driver version 5.1.11, TCQ is now either on or off by default
+	according to the setting you choose during the make config process.
+	In order to en/disable TCQ for certian devices at boot time, a user
+	may use this boot param.  The driver will then parse this message out
+        and en/disable the specific device entries that are present based upon
+        the value given.  The param line is parsed in the following manner:
+
+          { - first instance indicates the start of this parameter values
+              second instance is the start of entries for a particular
+              device entry
+          } - end the entries for a particular host adapter, or end the entire
+              set of parameter entries
+          , - move to next entry.  Inside of a set of device entries, this
+              moves us to the next device on the list.  Outside of device
+              entries, this moves us to the next host adapter
+          . - Same effect as , but is safe to use with insmod.
+          x - the number to enter into the array at this position.  
+              0 = Enable tagged queueing on this device and use the default
+                  queue depth
+              1-254 = Enable tagged queueing on this device and use this
+                      number as the queue depth
+              255 = Disable tagged queueing on this device.
+              Note: anything above 32 for an actual queue depth is wasteful
+                    and not recommended.
+
+        A few examples of how this can be used:
+
+        tag_info:{{8,12,,0,,255,4}}
+          This line will only effect the first aic7xxx card registered.  It
+          will set scsi id 0 to a queue depth of 8, id 1 to 12, leave id 2
+          at the default, set id 3 to tagged queueing enabled and use the
+          default queue depth, id 4 default, id 5 disabled, and id 6 to 4.
+          Any not specified entries stay at the default value, repeated
+          commas with no value specified will simply increment to the next id
+          without changing anything for the missing values.
+
+        tag_info:{,,,{,,,255}}
+          First, second, and third adapters at default values.  Fourth
+          adapter, id 3 is disabled.  Notice that leading commas simply
+	  increment what the first number effects, and there are no need
+	  for trailing commas.  When you close out an adapter, or the
+	  entire entry, anything not explicitly set stays at the default
+	  value.
+
+        A final note on this option.  The scanner I used for this isn't
+        perfect or highly robust.  If you mess the line up, the worst that
+        should happen is that the line will get ignored.  If you don't
+        close out the entire entry with the final bracket, then any other
+        aic7xxx options after this will get ignored.  So, in general, be
+        sure of what you are entering, and after you have it right, just
+        add it to the lilo.conf file so there won't be any mistakes.  As
+        a means of checking this parser, the entire tag_info array for
+        each card is now printed out in the /proc/scsi/aic7xxx/x file.  You
+        can use that to verify that your options were parsed correctly. 
+        
+    Boot command line options may be combined to form the proper set of options
+    a user might need.  For example, the following is valid:
+    
+    aic7xxx=verbose,extended,irq_trigger:1
+    
+    The only requirement is that individual options be separated by a comma or
+    a period on the command line.
+        
+  Module Loading command options
+  ------------------------------
+    When loading the aic7xxx driver as a module, the exact same options are
+    available to the user.  However, the syntax to specify the options changes
+    slightly.  For insmod, you need to wrap the aic7xxx= argument in quotes
+    and replace all ',' with '.'.  So, for example, a valid insmod line
+    would be:
+
+    insmod aic7xxx aic7xxx='verbose.irq_trigger:1.extended'
+
+    This line should result in the *exact* same behaviour as if you typed
+    it in at the lilo prompt and the driver was compiled into the kernel
+    instead of being a module.  The reason for the single quote is so that
+    the shell won't try to interpret anything in the line, such as {. 
+    Insmod assumes any options starting with a letter instead of a number
+    is a character string (which is what we want) and by switching all of
+    the commas to periods, insmod won't interpret this as more than one
+    string and write junk into our binary image.  I consider it a bug in
+    the insmod program that even if you wrap your string in quotes (quotes
+    that pass the shell mind you and that insmod sees) it still treates
+    a comma inside of those quotes as starting a new variable, resulting
+    in memory scribbles if you don't switch the commas to periods.
+
+
+  Kernel Compile options
+  ------------------------------
+    The various kernel compile time options for this driver are now fairly
+    well documented in the file Documentation/Configure.help.  In order to
+    see this documentation, you need to use one of the advanced configuration
+    programs (menuconfig and xconfig).  If you are using the "make menuconfig"
+    method of configuring your kernel, then you would simply highlight the
+    option in question and hit the ? key.  If you are using the "make xconfig"
+    method of configuring your kernel, then simply click on the help button
+    next to the option you have questions about.  The help information from
+    the Configure.help file will then get automatically displayed.
+
+  /proc support
+  ------------------------------
+    The /proc support for the AIC7xxx can be found in the /proc/scsi/aic7xxx/
+    directory. That directory contains a file for each SCSI controller in
+    the system. Each file presents the current configuration and transfer
+    statistics (enabled with #define in aic7xxx.c) for each controller.
+
+    Thanks to Michael Neuffer for his upper-level SCSI help, and
+    Matthew Jacob for statistics support.
+
+  Debugging the driver
+  ------------------------------
+    Should you have problems with this driver, and would like some help in
+    getting them solved, there are a couple debugging items built into
+    the driver to facilitate getting the needed information from the system.
+    In general, I need a complete description of the problem, with as many
+    logs as possible concerning what happens.  To help with this, there is
+    a command option aic7xxx=panic_on_abort.  This option, when set, forces
+    the driver to panic the kernel on the first SCSI abort issued by the
+    mid level SCSI code.  If your system is going to reset loops and you
+    can't read the screen, then this is what you need.  Not only will it
+    stop the system, but it also prints out a large amount of state
+    information in the process.  Second, if you specify the option
+    "aic7xxx=verbose:0x1ffff", the system will print out *SOOOO* much
+    information as it runs that you won't be able to see anything.
+    However, this can actually be very useful if your machine simply
+    locks up when trying to boot, since it will pin-point what was last
+    happening (in regards to the aic7xxx driver) immediately prior to
+    the lockup.  This is really only useful if your machine simply can
+    not boot up successfully.  If you can get your machine to run, then
+    this will produce far too much information.
+
+  FTP sites
+  ------------------------------
+    ftp://ftp.redhat.com/pub/aic/
+      - Out of date.  I used to keep stuff here, but too many people
+        complained about having a hard time getting into Red Hat's ftp
+	server.  So use the web site below instead.
+    ftp://ftp.pcnet.com/users/eischen/Linux/
+      - Dan Eischen's driver distribution area
+    ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
+      - European Linux mirror of Teleport site
+
+  Web sites
+  ------------------------------
+    http://people.redhat.com/dledford/
+      - My web site, also the primary aic7xxx site with several related
+        pages.
+
+Dean W. Gehnert
+deang@teleport.com
+
+$Revision: 3.0 $
+
+Modified by Doug Ledford 1998-2000
+
diff -Nru a/Documentation/scsi/cpqfc.txt b/Documentation/scsi/cpqfc.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/cpqfc.txt	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,273 @@
+Notes for CPQFCTS driver for Compaq Tachyon TS
+Fibre Channel Host Bus Adapter, PCI 64-bit, 66MHz
+for Linux (RH 6.1, 6.2 kernel 2.2.12-32, 2.2.14-5)
+SMP tested
+Tested in single and dual HBA configuration, 32 and 64bit busses,
+33 and 66MHz.  Only supports FC-AL.
+SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() 
+	max of 128k bytes contiguous.
+
+Ver 2.5.4  Oct 03, 2002
+   * fixed memcpy of sense buffer in ioctl to copy the smaller defined size
+Ver 2.5.3  Aug 01, 2002
+   * fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
+Ver 2.5.1  Jul 30, 2002
+   * fix ioctl to pay attention to the specified LUN.
+Ver 2.5.0  Nov 29, 2001
+   * eliminated io_request_lock.  This change makes the driver specific
+     to the 2.5.x kernels.
+   * silenced excessively noisy printks.
+
+Ver 2.1.2  July 23, 2002
+   * initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
+
+Ver 2.1.1  Oct 18, 2001
+   * reinitialize Cmnd->SCp.sent_command (used to identify commands as
+     passthrus) on calling scsi_done, since the scsi mid layer does not
+     use (or reinitialize) this field to prevent subsequent comands from
+     having it set incorrectly. 
+
+Ver 2.1.0  Aug 27, 2001
+   * Revise driver to use new kernel 2.4.x PCI DMA API, instead of 
+     virt_to_bus().  (enables driver to work w/ ia64 systems with >2Gb RAM.)
+     Rework main scatter-gather code to handle cases where SG element
+     lengths are larger than 0x7FFFF bytes and use as many scatter 
+     gather pages as necessary. (Steve Cameron)
+   * Makefile changes to bring cpqfc into line w/ rest of SCSI drivers
+     (thanks to Keith Owens)
+
+Ver 2.0.5  Aug 06, 2001
+   * Reject non-existent luns in the driver rather than letting the 
+     hardware do it.  (some HW behaves differently than others in this area.)
+   * Changed Makefile to rely on "make dep" instead of explicit dependencies
+   * ifdef'ed out fibre channel analyzer triggering debug code
+   * fixed a jiffies wrapping issue
+
+Ver 2.0.4  Aug 01, 2001
+   * Incorporated fix for target device reset from Steeleye
+   * Fixed passthrough ioctl so it doesn't hang.
+   * Fixed hang in launch_FCworker_thread() that occurred on some machines.
+   * Avoid problem when number of volumes in a single cabinet > 8
+
+Ver 2.0.2  July 23, 2001
+   Changed the semiphore changes so the driver would compile in 2.4.7. 
+   This version is for 2.4.7 and beyond. 
+ 
+Ver 2.0.1  May 	7, 2001
+   Merged version 1.3.6 fixes into version 2.0.0.   
+
+Ver 2.0.0  May   7, 2001
+  Fixed problem so spinlock is being initialized to UNLOCKED. 
+  Fixed updated driver so it compiles in the 2.4 tree. 
+ 
+ Ver 1.3.6  Feb  27, 2001
+   Added Target_Device_Reset function for SCSI error handling
+   Fixed problem with not reseting addressing mode after implicit logout
+ 
+
+Ver 1.3.4  Sep   7, 2000
+  Added Modinfo information
+  Fixed problem with statically linking the driver
+
+Ver 1.3.3, Aug  23, 2000
+  Fixed device/function number in ioctl
+
+Ver 1.3.2, July 27, 2000
+  Add include for Alpha compile on 2.2.14 kernel (cpq*i2c.c)
+  Change logic for different FCP-RSP sense_buffer location for HSG80 target
+  And search for Agilent Tachyon XL2 HBAs (not finished! - in test)
+
+Tested with 
+(storage):
+           Compaq RA-4x000, RAID firmware ver 2.40 - 2.54
+           Seagate FC drives model ST39102FC, rev 0006
+           Hitachi DK31CJ-72FC rev J8A8
+           IBM DDYF-T18350R rev F60K
+           Compaq FC-SCSI bridge w/ DLT 35/70 Gb DLT (tape)
+(servers):
+           Compaq PL-1850R
+           Compaq PL-6500 Xeon (400MHz)
+	   Compaq PL-8500 (500MHz, 66MHz, 64bit PCI)
+           Compaq Alpha DS20 (RH 6.1)
+(hubs):
+           Vixel Rapport 1000 (7-port "dumb")
+	   Gadzoox Gibralter (12-port "dumb")
+	   Gadzoox Capellix 2000, 3000 
+(switches):
+           Brocade 2010, 2400, 2800, rev 2.0.3a (& later)
+           Gadzoox 3210 (Fabric blade beta)
+           Vixel 7100 (Fabric beta firmare - known hot plug issues)
+using "qa_test" (esp. io_test script) suite modified from Unix tests.
+	
+Installation:
+make menuconfig
+  (select SCSI low-level, Compaq FC HBA)
+make dep
+make modules
+make modules_install
+
+e.g. insmod -f cpqfc
+
+Due to Fabric/switch delays, driver requires 4 seconds 
+to initialize.  If adapters are found, there will be a entries at
+/proc/scsi/cpqfcTS/*
+
+sample contents of startup messages
+
+*************************
+ scsi_register allocating 3596 bytes for CPQFCHBA
+ ioremap'd Membase: c887e600
+  HBA Tachyon RevId 1.2
+Allocating 119808 for 576 Exchanges @ c0dc0000
+Allocating 112904 for LinkQ @ c0c20000 (576 elements)
+Allocating 110600 for TachSEST for 512 Exchanges
+  cpqfcTS: writing IMQ BASE 7C0000h    PI 7C4000h
+  cpqfcTS: SEST c0e40000(virt): Wrote base E40000h @ c887e740
+cpqfcTS: New FC port 0000E8h WWN: 500507650642499D SCSI Chan/Trgt 0/0
+cpqfcTS: New FC port 0000EFh WWN: 50000E100000D5A6 SCSI Chan/Trgt 0/1
+cpqfcTS: New FC port 0000E4h WWN: 21000020370097BB SCSI Chan/Trgt 0/2
+cpqfcTS: New FC port 0000E2h WWN: 2100002037009946 SCSI Chan/Trgt 0/3
+cpqfcTS: New FC port 0000E1h WWN: 21000020370098FE SCSI Chan/Trgt 0/4
+cpqfcTS: New FC port 0000E0h WWN: 21000020370097B2 SCSI Chan/Trgt 0/5
+cpqfcTS: New FC port 0000DCh WWN: 2100002037006CC1 SCSI Chan/Trgt 0/6
+cpqfcTS: New FC port 0000DAh WWN: 21000020370059F6 SCSI Chan/Trgt 0/7
+cpqfcTS: New FC port 00000Fh WWN: 500805F1FADB0E20 SCSI Chan/Trgt 0/8
+cpqfcTS: New FC port 000008h WWN: 500805F1FADB0EBA SCSI Chan/Trgt 0/9
+cpqfcTS: New FC port 000004h WWN: 500805F1FADB1EB9 SCSI Chan/Trgt 0/10
+cpqfcTS: New FC port 000002h WWN: 500805F1FADB1ADE SCSI Chan/Trgt 0/11
+cpqfcTS: New FC port 000001h WWN: 500805F1FADBA2CA SCSI Chan/Trgt 0/12
+scsi4 : Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2: WWN 500508B200193F50
+ on PCI bus 0 device 0xa0fc irq 5 IObaseL 0x3400, MEMBASE 0xc6ef8600
+PCI bus width 32 bits, bus speed 33 MHz
+FCP-SCSI Driver v1.3.0
+GBIC detected: Short-wave.  LPSM 0h Monitor
+scsi : 5 hosts.
+  Vendor: IBM       Model: DDYF-T18350R      Rev: F60K
+  Type:   Direct-Access                      ANSI SCSI revision: 03
+Detected scsi disk sdb at scsi4, channel 0, id 0, lun 0
+  Vendor: HITACHI   Model: DK31CJ-72FC       Rev: J8A8
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdc at scsi4, channel 0, id 1, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdd at scsi4, channel 0, id 2, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sde at scsi4, channel 0, id 3, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdf at scsi4, channel 0, id 4, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdg at scsi4, channel 0, id 5, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdh at scsi4, channel 0, id 6, lun 0
+  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdi at scsi4, channel 0, id 7, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdj at scsi4, channel 0, id 8, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdk at scsi4, channel 0, id 8, lun 1
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdl at scsi4, channel 0, id 9, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdm at scsi4, channel 0, id 9, lun 1
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdn at scsi4, channel 0, id 10, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdo at scsi4, channel 0, id 11, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdp at scsi4, channel 0, id 11, lun 1
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdq at scsi4, channel 0, id 12, lun 0
+  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
+  Type:   Direct-Access                      ANSI SCSI revision: 02
+Detected scsi disk sdr at scsi4, channel 0, id 12, lun 1
+resize_dma_pool: unknown device type 12
+resize_dma_pool: unknown device type 12
+SCSI device sdb: hdwr sector= 512 bytes. Sectors= 35843670 [17501 MB] [17.5 GB]
+ sdb: sdb1
+SCSI device sdc: hdwr sector= 512 bytes. Sectors= 144410880 [70513 MB] [70.5 GB]
+ sdc: sdc1
+SCSI device sdd: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sdd: sdd1
+SCSI device sde: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sde: sde1
+SCSI device sdf: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sdf: sdf1
+SCSI device sdg: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sdg: sdg1
+SCSI device sdh: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sdh: sdh1
+SCSI device sdi: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
+ sdi: sdi1
+SCSI device sdj: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
+ sdj: sdj1
+SCSI device sdk: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
+ sdk: sdk1
+SCSI device sdl: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
+ sdl: sdl1
+SCSI device sdm: hdwr sector= 512 bytes. Sectors= 8380320 [4091 MB] [4.1 GB]
+ sdm: sdm1
+SCSI device sdn: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
+ sdn: sdn1
+SCSI device sdo: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
+ sdo: sdo1
+SCSI device sdp: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
+ sdp: sdp1
+SCSI device sdq: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
+ sdq: sdq1
+SCSI device sdr: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
+ sdr: sdr1
+
+*************************
+
+If a GBIC of type Short-wave, Long-wave, or Copper is detected, it will
+print out; otherwise, "none" is displayed.  If the cabling is correct
+and a loop circuit is completed, you should see "Monitor"; otherwise, 
+"LoopFail" (on open circuit) or some LPSM number/state with bit 3 set.
+
+
+ERRATA:
+1. Normally, Linux Scsi queries FC devices with INQUIRY strings.  All LUNs
+found according to INQUIRY should get READ commands at sector 0 to find
+partition table, etc.  Older kernels only query the first 4 devices.  Some
+Linux kernels only look for one LUN per target (i.e. FC device).
+
+2. Physically removing a device, or a malfunctioning system which hides a
+device, leads to a 30-second timeout and subsequent _abort call.  
+In some process contexts, this will hang the kernel (crashing the system).
+Single bit errors in frames and virtually all hot plugging events are 
+gracefully handled with internal driver timer and Abort processing.
+
+3. Some SCSI drives with error conditions will not handle the 7 second timeout
+in this software driver, leading to infinite retries on timed out SCSI commands.
+The 7 secs balances the need to quickly recover from lost frames (esp. on sequence
+initiatives) and time needed by older/slower/error-state drives in responding.
+This can be easily changed in "Exchanges[].timeOut".
+
+4. Due to the nature of FC soft addressing, there is no assurance that the 
+same LUNs (drives) will have the same path (e.g. /dev/sdb1) from one boot to
+next.  Dynamic soft address changes (i.e. 24-bit FC port_id) are
+supported during run time (e.g. due to hot plug event) by the use of WWN to
+SCSI Nexus (channel/target/LUN) mapping.
+
+5. Compaq RA4x00 firmware version 2.54 and later supports SSP (Selective 
+Storage Presentation), which maps LUNs to a WWN.  If RA4x00 firmware prior
+2.54 (e.g. older controller) is used, or the FC HBA is replaced (another WWN
+is used), logical volumes on the RA4x00 will no longer be visible.
+
+
+Send questions/comments to:
+Amy Vanzant-Hodge (fibrechannel@compaq.com)
+
diff -Nru a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/dpti.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,83 @@
+ /* TERMS AND CONDITIONS OF USE
+ * 
+ * Redistribution and use in source form, with or without modification, are
+ * permitted provided that redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following disclaimer.
+ * 
+ * This software is provided `as is' by Adaptec and
+ * any express or implied warranties, including, but not limited to, the
+ * implied warranties of merchantability and fitness for a particular purpose,
+ * are disclaimed. In no event shall Adaptec be
+ * liable for any direct, indirect, incidental, special, exemplary or
+ * consequential damages (including, but not limited to, procurement of
+ * substitute goods or services; loss of use, data, or profits; or business
+ * interruptions) however caused and on any theory of liability, whether in
+ * contract, strict liability, or tort (including negligence or otherwise)
+ * arising in any way out of the use of this driver software, even if advised
+ * of the possibility of such damage.
+ * 
+ ****************************************************************
+ * This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards.
+ *
+ * CREDITS:
+ * The original linux driver was ported to Linux by Karen White while at 
+ * Dell Computer.  It was ported from Bob Pasteur's (of DPT) original 
+ * non-Linux driver.  Mark Salyzyn and Bob Pasteur consulted on the original
+ * driver. 
+ * 
+ * 2.0 version of the driver by Deanna Bonds and Mark Salyzyn.
+ *
+ * HISTORY:
+ * The driver was originally ported to linux version 2.0.34 
+ *
+ * V2.0 Rewrite of driver.  Re-architectured based on i2o subsystem.
+ *   This was the first full GPL version since the last version used
+ *   i2osig headers which were not GPL.  Developer Testing version.
+ * V2.1 Internal testing
+ * V2.2 First released version
+ *
+ * V2.3 
+ *   Changes:
+ *      Added Raptor Support
+ *      Fixed bug causing system to hang under extreme load with 
+ *         management utilities running (removed GFP_DMA from kmalloc flags)
+ *
+ *
+ * V2.4 First version ready to be submitted to be embedded in the kernel
+ *   Changes: 
+ *      Implemented suggestions from Alan Cox
+ *      Added calculation of resid for sg layer
+ *      Better error handling
+ *         Added checking underflow condtions 
+ *         Added DATAPROTECT checking
+ *         Changed error return codes
+ *         Fixed pointer bug in bus reset routine
+ *      Enabled hba reset from ioctls (allows a FW flash to reboot and use the new
+ *         FW without having to reboot)
+ *      Changed proc output
+ *
+ * TODO:
+ *      Add 64 bit Scatter Gather when compiled on 64 bit architectures
+ *      Add sparse lun scanning 
+ *      Add code that checks if a device that had been taken offline is
+ *         now online (at the FW level) when test unit ready or inquiry 
+ *         command from scsi-core
+ *      Add proc read interface
+ *         busrescan command
+ *         rescan command
+ *      Add code to rescan routine that notifies scsi-core about new devices
+ *      Add support for C-PCI (hotplug stuff)
+ *      Add ioctl passthru error recovery
+ *
+ * NOTES:
+ * The DPT card optimizes the order of processing commands.  Consequently,
+ * a command may take up to 6 minutes to complete after it has been sent
+ * to the board.  
+ *
+ * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the
+ * interface files for Adaptecs managment routines.  These define the structures used
+ * in the ioctls.  They are written to be portable.  They are hard to read, but I need
+ * to use them 'as is' or I can miss changes in the interface.
+ *
+ */
+
diff -Nru a/Documentation/scsi/dtc3x80.txt b/Documentation/scsi/dtc3x80.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/dtc3x80.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,43 @@
+README file for the Linux DTC3180/3280 scsi driver.
+by Ray Van Tassle (rayvt@comm.mot.com)  March 1996
+Based on the generic & core NCR5380 code by Drew Eckhard
+
+SCSI device driver for the DTC 3180/3280.
+Data Technology Corp---a division of Qume.
+
+The 3280 has a standard floppy interface.
+
+The 3180 does not.  Otherwise, they are identical.
+
+The DTC3x80 does not support DMA but it does have Pseudo-DMA which is
+supported by the driver.
+
+It's DTC406 scsi chip is supposedly compatible with the NCR 53C400.
+It is memory mapped, uses an IRQ, but no dma or io-port.  There is
+internal DMA, between SCSI bus and an on-chip 128-byte buffer.  Double
+buffering is done automagically by the chip.  Data is transferred
+between the on-chip buffer and CPU/RAM via memory moves.
+
+The driver detects the possible memory addresses (jumper selectable):
+	CC00, DC00, C800, and D800
+The possible IRQ's (jumper selectable) are:
+	IRQ 10, 11, 12, 15
+Parity is supported by the chip, but not by this driver.
+Information can be obtained from /proc/scsi/dtc3c80/N.
+
+Note on interrupts:
+
+The documentation says that it can be set to interrupt whenever the
+on-chip buffer needs CPU attention.  I couldn't get this to work.  So
+the driver polls for data-ready in the pseudo-DMA transfer routine.
+The interrupt support routines in the NCR3280.c core modules handle
+scsi disconnect/reconnect, and this (mostly) works.  However.....  I
+have tested it with 4 totally different hard drives (both SCSI-1 and
+SCSI-2), and one CDROM drive.  Interrupts works great for all but one
+specific hard drive.  For this one, the driver will eventually hang in
+the transfer state.  I have tested with: "dd bs=4k count=2k
+of=/dev/null if=/dev/sdb".  It reads ok for a while, then hangs.
+After beating my head against this for a couple of weeks, getting
+nowhere, I give up.  So.....This driver does NOT use interrupts, even
+if you have the card jumpered to an IRQ.  Probably nobody will ever
+care.
diff -Nru a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/g_NCR5380.txt	Sun Nov 17 20:30:13 2002
@@ -0,0 +1,63 @@
+README file for the Linux g_NCR5380 driver.
+
+(c) 1993 Drew Eckhard
+NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin
+
+This file documents the NCR53c400 extensions by Kevin Lentin and some
+enhancements to the NCR5380 core.
+
+This driver supports both NCR5380 and NCR53c400 cards in port or memory
+mapped modes. Currently this driver can only support one of those mapping
+modes at a time but it does support both of these chips at the same time.
+The next release of this driver will support port & memory mapped cards at
+the same time. It should be able to handle multiple different cards in the
+same machine.
+
+The drivers/scsi/Makefile has an override in it for the most common
+NCR53c400 card, the Trantor T130B in its default configuration:
+	Port: 0x350
+	IRQ : 5
+
+The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
+supported by the driver.
+
+If the default configuration does not work for you, you can use the kernel
+command lines (eg using the lilo append command):
+	ncr5380=port,irq,dma
+	ncr53c400=port,irq
+or
+	ncr5380=base,irq,dma
+	ncr53c400=base,irq
+
+The driver does not probe for any addresses or ports other than those in
+the OVERRIDE or given to the kernel as above.
+
+This driver provides some information on what it has detected in
+/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot
+time. More info to come in the future.
+
+When NCR53c400 support is compiled in, BIOS parameters will be returned by
+the driver (the raw 5380 driver does not and I don't plan to fiddle with
+it!).
+
+This driver works as a module.
+When included as a module, parameters can be passed on the insmod/modprobe
+command line:
+  ncr_irq=xx   the interrupt
+  ncr_addr=xx  the port or base address (for port or memory
+               mapped, resp.)
+  ncr_dma=xx   the DMA
+  ncr_5380=1   to set up for a NCR5380 board
+  ncr_53c400=1 to set up for a NCR53C400 board
+e.g.
+modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
+  for a port mapped NCR5380 board or
+modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
+  for a memory mapped NCR53C400 board with interrupts disabled.
+
+(255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
+     IRQ line if overridden on the command line.)
+
+
+Kevin Lentin
+K.Lentin@cs.monash.edu.au
diff -Nru a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ibmmca.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,1402 @@
+
+               -=< The IBM Microchannel SCSI-Subsystem >=-
+	       
+	                 for the IBM PS/2 series
+		 
+	  	   Low Level Software-Driver for Linux
+		 
+     Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU 
+  General Public License. Originally written by Martin Kolinek, December 1995.
+   Officially modified and maintained by Michael Lang since January 1999.
+	   
+ 	                       Version 4.0a
+	
+   Last update: January 3, 2001
+   
+   Before you Start
+   ----------------
+   This is the common README.ibmmca file for all driver releases of the 
+   IBM MCA SCSI driver for Linux. Please note, that driver releases 4.0
+   or newer do not work with kernel versions older than 2.4.0, while driver
+   versions older than 4.0 do not work with kernels 2.4.0 or later! If you
+   try to compile your kernel with the wrong driver source, the 
+   compilation is aborted and you get a corresponding error message. This is
+   no bug in the driver. It prevents you from using the wrong sourcecode
+   with the wrong kernel version.
+
+   Authors of this Driver
+   ----------------------
+    - Chris Beauregard (improvement of the SCSI-device mapping by the driver)
+    - Martin Kolinek (origin, first release of this driver)
+    - Klaus Kudielka (multiple SCSI-host management/detection, adaption to
+                      Linux Kernel 2.1.x, module support)
+    - Michael Lang (assigning original pun/lun mapping, dynamical ldn
+                    assignment, rewritten adapter detection, this file, 
+		    patches, official driver maintenance and subsequent 
+		    debugging, related with the driver)
+
+   Table of Contents
+   -----------------
+   1 Abstract
+   2 Driver Description
+     2.1  IBM SCSI-Subsystem Detection
+     2.2  Physical Units, Logical Units, and Logical Devices
+     2.3  SCSI-Device Recognition and dynamical ldn Assignment
+     2.4  SCSI-Device Order
+     2.5  Regular SCSI-Command-Processing
+     2.6  Abort & Reset Commands
+     2.7  Disk Geometry
+     2.8  Kernel Boot Option
+     2.9  Driver Module Support
+     2.10 Multiple Hostadapter Support
+     2.11 /proc/scsi-Filesystem Information
+     2.12 /proc/mca-Filesystem Information
+     2.13 Supported IBM SCSI-Subsystems
+     2.14 Linux Kernel Versions
+   3 Code History
+   4 To do
+   5 Users' Manual
+     5.1 Commandline Parameters
+     5.2 Troubleshooting
+     5.3 Bugreports
+     5.4 Support WWW-page
+   6 References
+   7 Credits to
+     7.1 People
+     7.2 Sponsors & Supporters
+   8 Trademarks
+   9 Disclaimer
+
+                              * * *
+
+   1 Abstract
+   ----------
+   This README-file describes the IBM SCSI-subsystem low level driver for 
+   Linux. The descriptions which were formerly kept in the source-code have 
+   been taken out to this file to easify the codes' readability. The driver 
+   description has been updated, as most of the former description was already
+   quite outdated. The history of the driver development is also kept inside 
+   here. Multiple historical developments have been summarized to shorten the 
+   textsize a bit. At the end of this file you can find a small manual for 
+   this driver and hints to get it running on your machine.
+
+   2 Driver Description
+   --------------------
+   2.1 IBM SCSI-Subsystem Detection
+   --------------------------------
+   This is done in the ibmmca_detect() function. It first checks, if the
+   Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
+   Microchannel. In a next step, a free interrupt is chosen and the main
+   interrupt handler is connected to it to handle answers of the SCSI-
+   subsystem(s). If the F/W SCSI-adapter is forced by the BIOS to use IRQ11
+   instead of IRQ14, IRQ11 is used for the IBM SCSI-2 F/W adapter. In a 
+   further step it is checked, if the adapter gets detected by force from
+   the kernel commandline, where the I/O port and the SCSI-subsystem id can 
+   be specified. The next step checks if there is an integrated SCSI-subsystem
+   installed. This register area is fixed through all IBM PS/2 MCA-machines 
+   and appears as something like a virtual slot 10 of the MCA-bus. On most
+   PS/2 machines, the POS registers of slot 10 are set to 0xff or 0x00 if not
+   integrated SCSI-controller is available. But on certain PS/2s, like model 
+   9595, this slot 10 is used to store other information which at earlier
+   stage confused the driver and resulted in the detection of some ghost-SCSI. 
+   If POS-register 2 and 3 are not 0x00 and not 0xff, but all other POS
+   registers are either 0xff or 0x00, there must be an integrated SCSI-
+   subsystem present and it will be registered as IBM Integrated SCSI-
+   Subsystem. The next step checks, if there is a slot-adapter installed on 
+   the MCA-bus. To get this, the first two POS-registers, that represent the 
+   adapter ID are checked. If they fit to one of the ids, stored in the 
+   adapter list, a SCSI-subsystem is assumed to be found in a slot and will be 
+   registered. This check is done through all possible MCA-bus slots to allow 
+   more than one SCSI-adapter to be present in the PS/2-system and this is 
+   already the first point of problems. Looking into the technical reference 
+   manual for the IBM PS/2 common interfaces, the POS2 register must have 
+   different interpretation of its single bits to avoid overlapping I/O
+   regions. While one can assume, that the integrated subsystem has a fix 
+   I/O-address at 0x3540 - 0x3547, further installed IBM SCSI-adapters must 
+   use a different I/O-address. This is expressed by bit 1 to 3 of POS2 
+   (multiplied by 8 + 0x3540). Bits 2 and 3 are reserved for the integrated 
+   subsystem, but not for the adapters! The following list shows, how the 
+   bits of POS2 and POS3 should be interpreted.
+   
+   The POS2-register of all PS/2 models' integrated SCSI-subsystems has the 
+   following interpretation of bits:
+                           Bit 7 - 4 : Chip Revision ID (Release)
+                           Bit 3 - 2 : Reserved
+                           Bit 1     : 8k NVRAM Disabled
+                           Bit 0     : Chip Enable (EN-Signal)
+   The POS3-register is interpreted as follows (for most IBM SCSI-subsys.):
+                           Bit 7 - 5 : SCSI ID
+                           Bit 4 - 0 : Reserved = 0
+   The slot-adapters have different interpretation of these bits. The IBM SCSI
+   adapter (w/Cache) and the IBM SCSI-2 F/W adapter use the following
+   interpretation of the POS2 register:
+                           Bit 7 - 4 : ROM Segment Address Select
+			   Bit 3 - 1 : Adapter I/O Address Select (*8+0x3540)
+			   Bit 0     : Adapter Enable (EN-Signal)
+   and for the POS3 register:
+                           Bit 7 - 5 : SCSI ID 
+			   Bit 4     : Fairness Enable (SCSI ID3 f. F/W)
+			   Bit 3 - 0 : Arbitration Level
+   The most modern product of the series is the IBM SCSI-2 F/W adapter, it 
+   allows dual-bus SCSI and SCSI-wide addressing, which means, PUNs may be
+   between 0 and 15. Here, Bit 4 is the high-order bit of the 4-bit wide
+   adapter PUN expression. In short words, this means, that IBM PS/2 machines 
+   can only support 1 single integrated subsystem by default. Additional
+   slot-adapters get ports assigned by the automatic configuration tool.
+
+   One day I found a patch in ibmmca_detect(), forcing the I/O-address to be 
+   0x3540 for integrated SCSI-subsystems, there was a remark placed, that on 
+   integrated IBM SCSI-subsystems of model 56, the POS2 register was showing 5.
+   This means, that really for these models, POS2 has to be interpreted
+   sticking to the technical reference guide. In this case, the bit 2 (4) is 
+   a reserved bit and may not be interpreted. These differences between the 
+   adapters and the integrated controllers are taken into account by the 
+   detection routine of the driver on from version >3.0g. 
+
+   Every time, a SCSI-subsystem is discovered, the ibmmca_register() function
+   is called. This function checks first, if the requested area for the I/O-
+   address of this SCSI-subsystem is still available and assigns this I/O-
+   area to the SCSI-subsystem. There are always 8 sequential I/O-addresses
+   taken for each individual SCSI-subsystem found, which are:
+   
+     Offset            Type                  Permissions
+       0     Command Interface Register 1    Read/Write
+       1     Command Interface Register 2    Read/Write
+       2     Command Interface Register 3    Read/Write
+       3     Command Interface Register 4    Read/Write
+       4     Attention Register              Read/Write
+       5     Basic Control Register          Read/Write
+       6     Interrupt Status Register       Read
+       7     Basic Status Register           Read
+   
+   After the I/O-address range is assigned, the host-adapter is assigned
+   to a local structure which keeps all adapter information needed for the
+   driver itself and the mid- and higher-level SCSI-drivers. The SCSI pun/lun
+   and the adapters' ldn tables are initialized and get probed afterwards by
+   the check_devices() function. If no further adapters are found, 
+   ibmmca_detect() quits.
+   
+   2.2 Physical Units, Logical Units, and Logical Devices
+   ------------------------------------------------------
+   There can be up to 56 devices on the SCSI bus (besides the adapter):
+   there are up to 7 "physical units" (each identified by physical unit 
+   number or pun, also called the scsi id, this is the number you select
+   with hardware jumpers), and each physical unit can have up to 8 
+   "logical units" (each identified by logical unit number, or lun, 
+   between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two
+   busses and provides support for 30 logical devices at the same time, where
+   in wide-addressing mode you can have 16 puns with 32 luns on each device.
+   This section dexribes you the handling of devices on non-F/W adapters.
+   Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter
+   which means a lot of possible devices for such a small machine.
+
+   Typically the adapter has pun=7, so puns of other physical units
+   are between 0 and 6(15). On a wide-adapter a pun higher than 7 is
+   possible, but is normally not used. Almost all physical units have only 
+   one logical unit, with lun=0. A CD-ROM jukebox would be an example of a 
+   physical unit with more than one logical unit.
+
+   The embedded microprocessor of the IBM SCSI-subsystem hides the complex
+   two-dimensional (pun,lun) organization from the operating system.
+   When the machine is powered-up (or rebooted), the embedded microprocessor 
+   checks, on its own, all 56 possible (pun,lun) combinations, and the first 
+   15 devices found are assigned into a one-dimensional array of so-called 
+   "logical devices", identified by "logical device numbers" or ldn. The last 
+   ldn=15 is reserved for the subsystem itself. Wide adapters may have 
+   to check up to 15 * 8 = 120 pun/lun combinations.
+   
+   2.3 SCSI-Device Recognition and Dynamical ldn Assignment
+   --------------------------------------------------------
+   One consequence of information hiding is that the real (pun,lun)    
+   numbers are also hidden. The two possibilities to get around this problem
+   is to offer fake pun/lun combinations to the operating system or to 
+   delete the whole mapping of the adapter and to reassign the ldns, using
+   the immediate assign command of the SCSI-subsystem for probing through
+   all possible pun/lun combinations. a ldn is a "logical device number"
+   which is used by IBM SCSI-subsystems to access some valid SCSI-device.
+   At the beginning of the development of this driver, the following approach 
+   was used:
+   
+   First, the driver checked the ldn's (0 to 6) to find out which ldn's
+   have devices assigned. This was done by the functions check_devices() and
+   device_exists(). The interrupt handler has a special paragraph of code
+   (see local_checking_phase_flag) to assist in the checking. Assume, for
+   example, that three logical devices were found assigned at ldn 0, 1, 2.
+   These are presented to the upper layer of Linux SCSI driver
+   as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0). 
+   On the other hand, if the upper layer issues a command to device
+   say (4,0), this driver returns DID_NO_CONNECT error.
+
+   In a second step of the driver development, the following improvement has
+   been applied: The first approach limited the number of devices to 7, far
+   fewer than the 15 that it could usem then it just maped ldn -> 
+   (ldn/8,ldn%8) for pun,lun.  We ended up with a real mishmash of puns
+   and luns, but it all seemed to work.
+
+   The latest development, which is implemented from the driver version 3.0
+   and later, realizes the device recognition in the following way:
+   The physical SCSI-devices on the SCSI-bus are probed via immediate_assign- 
+   and device_inquiry-commands, that is all implemented in a completely new
+   made check_devices() subroutine. This delivers an exact map of the physical
+   SCSI-world that is now stored in the get_scsi[][]-array. This means,
+   that the once hidden pun,lun assignment is now known to this driver.
+   It no longer believes in default-settings of the subsystem and maps all
+   ldns to existing pun,lun "by foot". This assures full control of the ldn
+   mapping and allows dynamical remapping of ldns to different pun,lun, if
+   there are more SCSI-devices installed than ldns available (n>15). The
+   ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
+   excluding the pun of the subsystem. This assures, that at least simple 
+   SCSI-installations have optimum access-speed and are not touched by
+   dynamical remapping. The ldns 7 to 14 are put to existing devices with 
+   lun>0 or to non-existing devices, in order to satisfy the subsystem, if 
+   there are less than 15 SCSI-devices connected. In the case of more than 15 
+   devices, the dynamical mapping goes active. If the get_scsi[][] reports a 
+   device to be existant, but it has no ldn assigned, it gets a ldn out of 7 
+   to 14. The numbers are assigned in cyclic order. Therefore it takes 8 
+   dynamical reassignments on the SCSI-devices, until a certain device 
+   looses its ldn again. This assures, that dynamical remapping is avoided 
+   during intense I/O between up to 15 SCSI-devices (means pun,lun 
+   combinations). A further advantage of this method is, that people who
+   build their kernel without probing on all luns will get what they expect,
+   because the driver just won't assign everything with lun>0 when 
+   multpile lun probing is inactive.
+ 
+   2.4 SCSI-Device Order
+   ---------------------
+   Because of the now correct recognition of physical pun,lun, and 
+   their report to mid-level- and higher-level-drivers, the new reported puns
+   can be different from the old, faked puns. Therefore, Linux will eventually
+   change /dev/sdXXX assignments and prompt you for corrupted superblock
+   repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
+   You have to reboot (CTRL-D) with an old kernel and set the /etc/fstab-file
+   entries right. After that, the system should come up as errorfree as before.
+   If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
+   in a Linux session booted on old kernel and run lilo before reboot. Check
+   lilo.conf anyway to get boot on other partitions with foreign OSes right
+   again. But there exists a feature of this driver that allows you to change
+   the assignment order of the SCSI-devices by flipping the PUN-assignment.
+   See the next paragraph for a description.
+ 
+   The problem for this is, that Linux does not assign the SCSI-devices in the
+   way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to 
+   the device with at minimum id 0. But the first drive should be at id 6,
+   because for historical reasons, drive at id 6 has, by hardware, the highest
+   priority and a drive at id 0 the lowest. IBM was one of the rare producers,
+   where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most 
+   other producers' BIOS does not (I think even Adaptec-BIOS). The 
+   IBMMCA_SCSI_ORDER_STANDARD flag, which you set while configuring the
+   kernel enables to choose the preferred way of SCSI-device-assignment. 
+   Defining this flag would result in Linux determining the devices in the 
+   same order as DOS and OS/2 does on your MCA-machine. This is also standard 
+   on most industrial computers and OSes, like e.g. OS-9. Leaving this flag 
+   undefined will get your devices ordered in the default way of Linux. See 
+   also the remarks of Chris Beauregard from Dec 15, 1997 and the followups 
+   in section 3.
+   
+   2.5 Regular SCSI-Command-Processing
+   -----------------------------------
+   Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
+   and interrupt_handler().
+
+   The upper layer issues a scsi command by calling function 
+   ibmmca_queuecommand(). This function fills a "subsystem control block"
+   (scb) and calls a local function issue_cmd(), which writes a scb 
+   command into subsystem I/O ports. Once the scb command is carried out, 
+   the interrupt_handler() is invoked. If a device is determined to be 
+   existant and it has not assigned any ldn, it gets one dynamically.
+   For this, the whole stuff is done in ibmmca_queuecommand().
+
+   2.6 Abort & Reset Commands
+   --------------------------
+   These are implemented with busy waiting for interrupt to arrive.
+   ibmmca_reset() and ibmmca_abort() do not work sufficently well
+   up to now and need still a lot of development work. But, this seems
+   to be even a problem with other SCSI-low level drivers, too. However,
+   this should be no excuse.
+
+   2.7 Disk Geometry
+   -----------------
+   The ibmmca_biosparams() function should return the same disk geometry 
+   as the bios. This is needed for fdisk, etc. The returned geometry is 
+   certainly correct for disks smaller than 1 gigabyte. In the meantime,
+   it has been proved, that this works fine even with disks larger than
+   1 gigabyte.
+
+   2.8 Kernel Boot Option
+   ----------------------
+   The function ibmmca_scsi_setup() is called if option ibmmcascsi=n 
+   is passed to the kernel. See file linux/init/main.c for details.
+   
+   2.9 Driver Module Support
+   -------------------------
+   Is implemented and tested by K. Kudielka. This could probably not work
+   on kernels <2.1.0.
+  
+   2.10 Multiple Hostadapter Support
+   ---------------------------------
+   This driver supports up to eight interfaces of type IBM-SCSI-Subsystem. 
+   Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
+   IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
+ 
+   2.11 /proc/scsi-Filesystem Information
+   --------------------------------------
+   Information about the driver condition is given in 
+   /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
+   
+   This table is quite informative for interested users. It shows the load
+   of commands on the subsystem and wether you are running the bypassed 
+   (software) or integrated (hardware) SCSI-command set (see below). The
+   amount of accesses is shown. Read, write, modeselect is shown seperately
+   in order to help debugging problems with CD-ROMs or tapedrives.
+   
+   The following table shows the list of 15 logical device numbers, that are
+   used by the SCSI-subsystem. The load on each ldn is shown in the table,
+   again, read and write commands are split. The last column shows the amount
+   of reassignments, that have been applied to the ldns, if you have more than
+   15 pun/lun combinations available on the SCSI-bus.
+   
+   The last two tables show the pun/lun map and the positions of the ldns
+   on this pun/lun map. This may change during operation, when a ldn is
+   reassigned to another pun/lun combination. If the necessity for dynamical
+   assignments is set to 'no', the ldn structure keeps static.
+   
+   2.12 /proc/mca-Filesystem Information
+   -------------------------------------
+   The slot-file contains all default entries and in addition chip and I/O-
+   address information of the SCSI-subsystem. This information is provided
+   by ibmmca_getinfo().
+   
+   2.13 Supported IBM SCSI-Subsystems
+   ----------------------------------
+   The following IBM SCSI-subsystems are supported by this driver:
+   
+     - IBM Fast/Wide SCSI-2 Adapter
+     - IBM 7568 Industrial Computer SCSI Adapter w/Cache
+     - IBM Expansion Unit SCSI Controller
+     - IBM SCSI Adapter w/Cache
+     - IBM SCSI Adapter
+     - IBM Integrated SCSI Controller
+     - All clones, 100% compatible with the chipset and subsystem command
+       system of IBM SCSI-adapters (forced detection)
+     
+   2.14 Linux Kernel Versions
+   --------------------------
+   The IBM SCSI-subsystem low level driver is prepared to be used with
+   all versions of Linux between 2.0.x and 2.4.x. The compatibility checks
+   are fully implemented up from version 3.1e of the driver. This means, that
+   you just need the latest ibmmca.h and ibmmca.c file and copy it in the
+   linux/drivers/scsi directory. The code is automatically adapted during 
+   kernel compilation. This is different from kernel 2.4.0! Here version 
+   4.0 or later of the driver must be used for kernel 2.4.0 or later. Version
+   4.0 or later does not work together with older kernels! Driver versions
+   older than 4.0 do not work together with kernel 2.4.0 or later. They work
+   on all older kernels.
+
+   3 Code History
+   --------------
+   Jan 15 1996:  First public release.
+   - Martin Kolinek
+
+   Jan 23 1996:  Scrapped code which reassigned scsi devices to logical
+   device numbers. Instead, the existing assignment (created
+   when the machine is powered-up or rebooted) is used. 
+   A side effect is that the upper layer of Linux SCSI 
+   device driver gets bogus scsi ids (this is benign), 
+   and also the hard disks are ordered under Linux the 
+   same way as they are under dos (i.e., C: disk is sda, 
+   D: disk is sdb, etc.).
+   - Martin Kolinek
+
+   I think that the CD-ROM is now detected only if a CD is 
+   inside CD_ROM while Linux boots. This can be fixed later,
+   once the driver works on all types of PS/2's.
+   - Martin Kolinek
+
+   Feb 7 1996:   Modified biosparam function. Fixed the CD-ROM detection. 
+   For now, devices other than harddisk and CD_ROM are 
+   ignored. Temporarily modified abort() function 
+   to behave like reset().
+   - Martin Kolinek
+
+   Mar 31 1996:  The integrated scsi subsystem is correctly found
+   in PS/2 models 56,57, but not in model 76. Therefore
+   the ibmmca_scsi_setup() function has been added today.
+   This function allows the user to force detection of
+   scsi subsystem. The kernel option has format
+   ibmmcascsi=n
+   where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
+   - Martin Kolinek
+
+   Aug 21 1996:  Modified the code which maps ldns to (pun,0).  It was
+   insufficient for those of us with CD-ROM changers.
+   - Chris Beauregard
+ 
+   Dec 14 1996: More improvements to the ldn mapping.  See check_devices
+   for details.  Did more fiddling with the integrated SCSI detection,
+   but I think it's ultimately hopeless without actually testing the
+   model of the machine.  The 56, 57, 76 and 95 (ultimedia) all have
+   different integrated SCSI register configurations.  However, the 56
+   and 57 are the only ones that have problems with forced detection.
+   - Chris Beauregard
+ 
+   Mar 8-16 1997: Modified driver to run as a module and to support 
+   multiple adapters. A structure, called ibmmca_hostdata, is now
+   present, containing all the variables, that were once only
+   available for one single adapter. The find_subsystem-routine has vanished.
+   The hardware recognition is now done in ibmmca_detect directly.
+   This routine checks for presence of MCA-bus, checks the interrupt
+   level and continues with checking the installed hardware.
+   Certain PS/2-models do not recognize a SCSI-subsystem automatically.
+   Hence, the setup defined by command-line-parameters is checked first.
+   Thereafter, the routine probes for an integrated SCSI-subsystem.
+   Finally, adapters are checked. This method has the advantage to cover all
+   possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
+   eight SCSI-subsystems can be recognized and announced to the upper-level
+   drivers with this improvement. A set of defines made changes to other
+   routines as small as possible.
+   - Klaus Kudielka
+   
+   May 30 1997: (v1.5b)
+   1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
+      This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which 
+      allows data to be written from the system to the device. It is a
+      necessary step to be allowed to set blocksize of SCSI-tape-drives and 
+      the tape-speed, whithout confusing the SCSI-Subsystem.
+   2) The recognition of a tape is included in the check_devices routine.
+      This is done by checking for TYPE_TAPE, that is already defined in
+      the kernel-scsi-environment. The markup of a tape is done in the 
+      global ldn_is_tape[] array. If the entry on index ldn 
+      is 1, there is a tapedrive connected.
+   3) The ldn_is_tape[] array is necessary to distinguish between tape- and 
+      other devices. Fixed blocklength devices should not cause a problem
+      with the SCB-command for read and write in the ibmmca_queuecommand
+      subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
+      the tape-devices, as recommended by IBM in this Technical Reference,
+      mentioned below. (IBM recommends to avoid using the read/write of the
+      subsystem, but the fact was, that read/write causes a command error from
+      the subsystem and this causes kernel-panic.)
+   4) In addition, I propose to use the ldn instead of a fix char for the
+      display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
+      devices that are accessed. It shows activity and easyfies debugging.   
+   The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
+   (I do not know yet the type). Optimization and CD-ROM audio-support, 
+   I am working on ...
+   - Michael Lang
+   
+   June 19 1997: (v1.6b)
+   1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
+      device-array. 
+   2) CD-ROM Audio-Play seems to work now.
+   3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
+      0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears 
+      also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that 
+      the problem is independent of the low-level-driver/bus-architecture.
+   4) Hexadecimal ldn on PS/2-95 LED-display.
+   5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
+      does not confuse the disk_rw_in_progress counter.
+   - Michael Lang
+  
+   June 21 1997: (v1.7b)
+   1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
+      outer-world about operational load statistics on the different ldns,
+      seen by the driver. Everybody that has more than one IBM-SCSI should
+      test this, because I only have one and cannot see what happens with more
+      than one IBM-SCSI hosts.
+   2) Definition of a driver version-number to have a better recognition of 
+      the source when there are existing too much releases that may confuse
+      the user, when reading about release-specific problems. Up to know,
+      I calculated the version-number to be 1.7. Because we are in BETA-test
+      yet, it is today 1.7b.
+   3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
+      CD-ROM did not work any more! The C7-command was a fake impression
+      I got while programming. Now, the READ and WRITE commands for CD-ROM are
+      no longer running over the subsystem, but just over 
+      IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
+      much faster(!) and hopefully all fancy multimedia-functions, like direct
+      digital recording from audio-CDs also work. (I tried it with cdda2wav
+      from the cdwtools-package and it filled up the harddisk immediately :-).)
+      To easify boolean logics, a further local device-type in ld[], called
+      is_cdrom has been included.
+   4) If one uses a SCSI-device of unsupported type/commands, one
+      immediately runs into a kernel-panic caused by Command Error. To better
+      understand which SCSI-command caused the problem, I extended this
+      specific panic-message slightly.
+   - Michael Lang
+ 
+   June 25 1997: (v1.8b)
+   1) Some cosmetical changes for the handling of SCSI-device-types.
+      Now, also CD-Burners / WORMs and SCSI-scanners should work. For
+      MO-drives I have no experience, therefore not yet supported.
+      In logical_devices I changed from different type-variables to one
+      called 'device_type' where the values, corresponding to scsi.h,
+      of a SCSI-device are stored.
+   2) There existed a small bug, that maps a device, coming after a SCSI-tape
+      wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
+      -> problem removed.
+   3) Extension of the logical_device structure. Now it contains also device,
+      vendor and revision-level of a SCSI-device for internal usage.
+   - Michael Lang
+
+   June 26-29 1997: (v2.0b)
+   1) The release number 2.0b is necessary because of the completely new done
+      recognition and handling of SCSI-devices with the adapter. As I got
+      from Chris the hint, that the subsystem can reassign ldns dynamically,
+      I remembered this immediate_assign-command, I found once in the handbook.
+      Now, the driver first kills all ldn assignments that are set by default
+      on the SCSI-subsystem. After that, it probes on all puns and luns for
+      devices by going through all combinations with immediate_assign and
+      probing for devices, using device_inquiry. The found physical(!) pun,lun
+      structure is stored in get_scsi[][] as device types. This is followed
+      by the assignment of all ldns to existing SCSI-devices. If more ldns
+      than devices are available, they are assigned to non existing pun,lun
+      combinations to satisfy the adapter. With this, the dynamical mapping
+      was possible to implement. (For further info see the text in the 
+      source-code and in the description below. Read the description
+      below BEFORE installing this driver on your system!)
+   2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
+   3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
+      (pun) of the accessed SCSI-device. This is now senseful, because the 
+      pun known within the driver is exactly the pun of the physical device
+      and no longer a fake one.
+   4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
+      hit-statistics of ldns is shown and a second part, where the maps of 
+      physical and logical SCSI-devices are displayed. This could be very 
+      interesting, when one is using more than 15 SCSI-devices in order to 
+      follow the dynamical remapping of ldns.
+   - Michael Lang
+ 
+   June 26-29 1997: (v2.0b-1)
+   1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
+      in the dynamical remapping part in ibmmca_queuecommand for the 
+      device_exist routine. Sorry.
+   - Michael Lang
+ 
+   July 1-13 1997: (v3.0b,c)
+   1) Merging of the driver-developments of Klaus Kudielka and Michael Lang 
+      in order to get a optimum and unified driver-release for the 
+      IBM-SCSI-Subsystem-Adapter(s).
+         For people, using the Kernel-release >=2.1.0, module-support should 
+      be no problem. For users, running under <2.1.0, module-support may not 
+      work, because the methods have changed between 2.0.x and 2.1.x.
+   2) Added some more effective statistics for /proc-output.
+   3) Change typecasting at necessary points from (unsigned long) to
+      virt_to_bus().
+   4) Included #if... at special points to have specific adaption of the
+      driver to kernel 2.0.x and 2.1.x. It should therefore also run with 
+      later releases.
+   5) Magneto-Optical drives and medium-changers are also recognized, now.
+      Therefore, we have a completely gapfree recognition of all SCSI-
+      device-types, that are known by Linux up to kernel 2.1.31.
+   6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
+      the configuration, each connected SCSI-device will get a reset command
+      during boottime. This can be necessary for some special SCSI-devices.
+      This flag should be included in Config.in.
+      (See also the new Config.in file.)
+   Probable next improvement: bad disk handler.
+   - Michael Lang
+ 
+   Sept 14 1997: (v3.0c)
+   1) Some debugging and speed optimization applied.
+   - Michael Lang
+
+   Dec 15, 1997
+    - chrisb@truespectra.com
+    - made the front panel display thingy optional, specified from the
+    command-line via ibmmcascsi=display.  Along the lines of the /LED
+    option for the OS/2 driver.
+    - fixed small bug in the LED display that would hang some machines.
+    - reversed ordering of the drives (using the
+    IBMMCA_SCSI_ORDER_STANDARD define).  This is necessary for two main
+    reasons:
+	- users who've already installed Linux won't be screwed.  Keep
+	in mind that not everyone is a kernel hacker.
+	- be consistent with the BIOS ordering of the drives.  In the
+	BIOS, id 6 is C:, id 0 might be D:.  With this scheme, they'd be
+	backwards.  This confuses the crap out of those heathens who've
+	got a impure Linux installation (which, <wince>, I'm one of).
+    This whole problem arises because IBM is actually non-standard with
+    the id to BIOS mappings.  You'll find, in fdomain.c, a similar
+    comment about a few FD BIOS revisions.  The Linux (and apparently
+    industry) standard is that C: maps to scsi id (0,0).  Let's stick
+    with that standard.
+    - Since this is technically a branch of my own, I changed the
+    version number to 3.0e-cpb.
+
+   Jan 17, 1998: (v3.0f)
+   1) Addition of some statistical info for /proc in proc_info.
+   2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
+      1997. In fact, IBM is right, concerning the assignment of SCSI-devices 
+      to driveletters. It is conform to the ANSI-definition of the SCSI-
+      standard to assign drive C: to SCSI-id 6, because it is the highest
+      hardware priority after the hostadapter (that has still today by
+      default everywhere id 7). Also realtime-operating systems that I use, 
+      like LynxOS and OS9, which are quite industrial systems use top-down
+      numbering of the harddisks, that is also starting at id 6. Now, one
+      sits a bit between two chairs. On one hand side, using the define
+      IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
+      the IBM- and ANSI-SCSI-standard and keeps this driver downward
+      compatible to older releases, on the other hand side, people is quite
+      habituated in believing that C: is assigned to (0,0) and much other
+      SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD 
+      define out of the driver and put it into Config.in as subitem of 
+      'IBM SCSI support'. A help, added to Documentation/Configure.help 
+      explains the differences between saying 'y' or 'n' to the user, when 
+      IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to 
+      choose the way of assignment, depending on his own situation and gusto.
+   3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
+      now called IBMMCA_SCSI_DEV_RESET.
+   4) Optimization of proc_info and its subroutines.
+   5) Added more in-source-comments and extended the driver description by
+      some explanation about the SCSI-device-assignment problem.
+   - Michael Lang
+   
+   Jan 18, 1998: (v3.0g)
+   1) Correcting names to be absolutely conform to the later 2.1.x releases.
+      This is necessary for 
+            IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
+            IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+   - Michael Lang
+ 
+   Jan 18, 1999: (v3.1 MCA-team internal)
+   1) The multiple hosts structure is accessed from every subroutine, so there
+      is no longer the address of the device structure passed from function
+      to function, but only the hostindex. A call by value, nothing more. This
+      should really be understood by the compiler and the subsystem should get
+      the right values and addresses.
+   2) The SCSI-subsystem detection was not complete and quite hugely buggy up
+      to now, compared to the technical manual. The interpretation of the pos2
+      register is not as assumed by people before, therefore, I dropped a note
+      in the ibmmca_detect function to show the registers' interpretation.
+      The pos-registers of integrated SCSI-subsystems do not contain any 
+      information concerning the IO-port offset, really. Instead, they contain
+      some info about the adapter, the chip, the NVRAM .... The I/O-port is
+      fixed to 0x3540 - 0x3547. There can be more than one adapters in the 
+      slots and they get an offset for the I/O area in order to get their own
+      I/O-address area. See chapter 2 for detailed description. At least, the 
+      detection should now work right, even on models other than 95. The 95ers
+      came happily around the bug, as their pos2 register contains always 0 
+      in the critical area. Reserved bits are not allowed to be interpreted, 
+      therefore, IBM is allowed to set those bits as they like and they may 
+      really vary between different PS/2 models. So, now, no interpretation 
+      of reserved bits - hopefully no trouble here anymore.
+   3) The command error, which you may get on models 55, 56, 57, 70, 77 and
+      P70 may have been caused by the fact, that adapters of older design do
+      not like sending commands to non-existing SCSI-devices and will react
+      with a command error as a sign of protest. While this error is not
+      present on IBM SCSI Adapter w/cache, it appears on IBM Integrated SCSI
+      Adapters. Therefore, I implemented a workarround to forgive those 
+      adapters their protests, but it is marked up in the statisctis, so
+      after a successful boot, you can see in /proc/scsi/ibmmca/<host_number>
+      how often the command errors have been forgiven to the SCSI-subsystem.
+      If the number is bigger than 0, you have a SCSI subsystem of older
+      design, what should no longer matter.
+   4) ibmmca_getinfo() has been adapted very carefully, so it shows in the 
+      slotn file really, what is senseful to be presented.
+   5) ibmmca_register() has been extended in its parameter list in order to
+      pass the right name of the SCSI-adapter to Linux.
+   - Michael Lang
+
+   Feb 6, 1999: (v3.1)
+   1) Finally, after some 3.1Beta-releases, the 3.1 release. Sorry, for 
+      the delayed release, but it was not finished with the release of 
+      Kernel 2.2.0.
+   - Michael Lang
+   
+   Feb 10, 1999 (v3.1)
+   1) Added a new commandline parameter called 'bypass' in order to bypass
+      every integrated subsystem SCSI-command consequently in case of
+      troubles.
+   2) Concatenated read_capacity requests to the harddisks. It gave a lot
+      of troubles with some controllers and after I wanted to apply some
+      extensions, it jumped out in the same situation, on my w/cache, as like 
+      on D. Weinehalls' Model 56, having integrated SCSI. This gave me the 
+      descissive hint to move the code-part out and declare it global. Now,
+      it seems to work by far much better an more stable. Let us see, what
+      the world thinks of it...
+   3) By the way, only Sony DAT-drives seem to show density code 0x13. A
+      test with a HP drive gave right results, so the problem is vendor-
+      specific and not a problem of the OS or the driver.
+   - Michael Lang
+   
+   Feb 18, 1999 (v3.1d)
+   1) The abort command and the reset function have been checked for 
+      inconsistencies. From the logical point of thinking, they work
+      at their optimum, now, but as the subsystem does not answer with an
+      interrupt, abort never finishes, sigh...
+   2) Everything, that is accessed by a busmaster request from the adapter
+      is now declared as global variable, even the return-buffer in the
+      local checking phase. This assures, that no accesses to undefined memory
+      areas are performed.
+   3) In ibmmca.h, the line unchecked_isa_dma is added with 1 in order to
+      avoid memory-pointers for the areas higher than 16MByte in order to
+      be sure, it also works on 16-Bit Microchannel bus systems.
+   4) A lot of small things have been found, but nothing that endangered the
+      driver operations. Just it should be more stable, now.
+   - Michael Lang
+      
+   Feb 20, 1999 (v3.1e)
+   1) I took the warning from the Linux Kernel Hackers Guide serious and 
+      checked the cmd->result return value to the done-function very carefully.
+      It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
+      some error appeared, else it is undefined. Now, this is fixed. Before
+      any SCB command gets queued, the tsb.dev_status is set to 0, so the 
+      cmd->result won't screw up Linux higher level drivers.
+   2) The reset-function has slightly improved. This is still planed for 
+      abort. During the abort and the reset function, no interrupts are 
+      allowed. This is however quite hard to cope with, so the INT-status
+      register is read. When the interrupt gets queued, one can find its
+      status immediately on that register and is enabled to continue in the
+      reset function. I had no chance to test this really, only in a bogus 
+      situation, I got this function running, but the situation was too much
+      worse for Linux :-(, so tests will continue.
+   3) Buffers got now consistent. No open address mapping, as before and
+      therefore no further troubles with the unassigned memory segmentation
+      faults that scrambled probes on 95XX series and even on 85XX series,
+      when the kernel is done in a not so perfectly fitting way.
+   4) Spontaneous interrupts from the subsystem, appearing without any
+      command previously queued are answered with a DID_BAD_INTR result.
+   5) Taken into account ZP Gus' proposals to reverse the SCSI-device
+      scan order. As it does not work on Kernel 2.1.x or 2.2.x, as proposed
+      by him, I implemented it in a slightly derived way, which offers in 
+      addition more flexibility.
+   - Michael Lang
+
+   Apr 23, 2000 (v3.2pre1)
+   1) During a very long time, I collected a huge amount of bugreports from
+      various people, trying really quite different things on their SCSI-
+      PS/2s. Today, all these bugreports are taken into account and should be
+      mostly solved. The major topics were:
+      - Driver crashes during boottime by no obvious reason.
+      - Driver panics while the midlevel-SCSI-driver is trying to inquire
+        the SCSI-device properties, even though hardware is in perfect state.
+      - Displayed info for the various slot-cards is interpreted wrong.
+      The main reasons for the crashes were two:
+      1) The commands to check for device information like INQUIRY, 
+         TEST_UNIT_READY, REQUEST_SENSE and MODE_SENSE cause the devices
+	 to deliver information of up to 255 bytes. Midlevel drivers offer
+	 1024 bytes of space for the answer, but the IBM-SCSI-adapters do
+	 not accept this, as they stick quite near to ANSI-SCSI and report
+	 a COMMAND_ERROR message which causes the driver to panic. The main
+	 problem was located around the INQUIRY command. Now, for all the
+	 mentioned commands, the buffersize, sent to the adapter is at 
+	 maximum 255 which seems to be a quite reasonable solution. 
+	 TEST_UNIT_READY gets a buffersize of 0 to make sure, that no 
+	 data is transferred in order to avoid any possible command failure.
+      2) On unsuccessful TEST_UNIT_READY, the midlevel-driver has to send
+         a REQUEST_SENSE in order to see, where the problem is located. This
+	 REQUEST_SENSE may have various length in its answer-buffer. IBM
+	 SCSI-subsystems report a command failure, if the returned buffersize
+	 is different from the sent buffersize, but this can be supressed by
+	 a special bit, which is now done and problems seem to be solved.
+   2) Code adaption to all kernel-releases. Now, the 3.2 code compiles on 
+      2.0.x, 2.1.x, 2.2.x and 2.3.x kernel releases without any code-changes.
+   3) Commandline-parameters are recognized again, even under Kernel 2.3.x or
+      higher.
+   - Michael Lang   
+
+   April 27, 2000 (v3.2pre2)
+   1) Bypassed commands get read by the adapter by one cycle instead of two.
+      This increases SCSI-performance.
+   2) Synchronous datatransfer is provided for sure to be 5 MHz on older
+      SCSI and 10 MHz on internal F/W SCSI-adapter.
+   3) New commandline parameters allow to force the adapter to slow down while
+      in synchronous transfer. Could be helpful for very old devices.
+   - Michael Lang
+   
+   June 2, 2000 (v3.2pre5)
+   1) Added Jim Shorney's contribution to make the activity indicator
+      flashing in addition to the LED-alphanumeric display-panel on
+      models 95A. To be enabled to choose this feature freely, a new
+      commandline parameter is added, called 'activity'.
+   2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
+   3) Added some suppress_exception bits to read_device_capacity and
+      all device_inquiry occurences in the driver code.
+   4) Complaints about the various KERNEL_VERSION implementations are
+      taken into account. Every local_LinuxKernelVersion occurence is
+      now replaced by KERNEL_VERSION, defined in linux/version.h. 
+      Corresponding changes were applied to ibmmca.h, too. This was a
+      contribution to all kernel-parts by Philipp Hahn.
+   - Michael Lang
+   
+   July 17, 2000 (v3.2pre8)
+   A long period of collecting bugreports from all corners of the world
+   now lead to the following corrections to the code:
+   1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this 
+      was, that it is possible to disbale Fast-SCSI for the external bus.
+      The feature-control command, where this crash appeared regularly tried
+      to set the maximum speed of 10MHz synchronous transfer speed and that
+      reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now,
+      the feature-command probes down from maximum speed until the adapter 
+      stops to complain, which is at the same time the maximum possible
+      speed selected in the reference program. So, F/W external can run at
+      5 MHz (slow-) or 10 MHz (fast-SCSI). During feature probing, the 
+      COMMAND ERROR message is used to detect if the adapter does not complain.
+   2) Up to now, only combined busmode is supported, if you use external
+      SCSI-devices, attached to the F/W-controller. If dual bus is selected,
+      only the internal SCSI-devices get accessed by Linux. For most 
+      applications, this should do fine. 
+   3) Wide-SCSI-addressing (16-Bit) is now possible for the internal F/W
+      bus on the F/W adapter. If F/W adapter is detected, the driver
+      automatically uses the extended PUN/LUN <-> LDN mapping tables, which
+      are now new from 3.2pre8. This allows PUNs between 0 and 15 and should
+      provide more fun with the F/W adapter.
+   4) Several machines use the SCSI: POS registers for internal/undocumented
+      storage of system relevant info. This confused the driver, mainly on
+      models 9595, as it expected no onboard SCSI only, if all POS in
+      the integrated SCSI-area are set to 0x00 or 0xff. Now, the mechanism
+      to check for integrated SCSI is much more restrictive and these problems
+      should be history.
+   - Michael Lang          
+
+   July 18, 2000 (v3.2pre9)
+   This develop rather quickly at the moment. Two major things were still
+   missing in 3.2pre8:
+   1) The adapter PUN for F/W adapters has 4-bits, while all other adapters
+      have 3-bits. This is now taken into account for F/W.
+   2) When you select CONFIG_IBMMCA_SCSI_ORDER_STANDARD, you should 
+      normally get the inverse probing order of your devices on the SCSI-bus.
+      The ANSI device order gets scrambled in version 3.2pre8!! Now, a new
+      and tested algorithm inverts the device-order on the SCSI-bus and
+      automatically avoids accidental access to whatever SCSI PUN the adapter 
+      is set and works with SCSI- and Wide-SCSI-addressing.
+   - Michael Lang
+
+   July 23, 2000 (v3.2pre10 unpublished) 
+   1) LED panel display supports wide-addressing in ibmmca=display mode.
+   2) Adapter-information and autoadaption to address-space is done.
+   3) Auto-probing for maximum synchronous SCSI transfer rate is working.
+   4) Optimization to some embedded function calls is applied.
+   5) Added some comment for the user to wait for SCSI-devices beeing probed.
+   6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
+   - Michael Lang
+   
+   July 26, 2000 (v3.2pre11)
+   1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and
+      a model 9595. Asking around in the community, nobody except of me has
+      seen such errors. Weired, but I am trying to recompile everything on
+      the model 9595. Maybe, as I use a specially modified gcc, that could
+      cause problems. But, it was not the reason. The true background was,
+      that the kernel was compiled for i386 and the 9595 has a 486DX-2. 
+      Normally, no troubles should appear, but for this special machine,
+      only the right processor support is working fine!
+   2) Previous problems with synchronous speed, slowing down from one adapter 
+      to the next during probing are corrected. Now, local variables store
+      the synchronous bitmask for every single adapter found on the MCA bus.
+   3) LED alphanumeric panel support for XX95 systems is now showing some
+      alive rotator during boottime. This makes sense, when no monitor is 
+      connected to the system. You can get rid of all display activity, if
+      you do not use any parameter or just ibmmcascsi=activity, for the 
+      harddrive activity LED, existant on all PS/2, except models 8595-XXX.
+      If no monitor is available, please use ibmmcascsi=display, which works
+      fine together with the linuxinfo utility for the LED-panel.
+   - Michael Lang
+   
+   July 29, 2000 (v3.2)
+   1) Submission of this driver for kernel 2.4test-XX and 2.2.17.
+   - Michael Lang
+   
+   December 28, 2000 (v3.2d / v4.0)
+   1) The interrupt handler had some wrong statement to wait for. This
+      was done due to experimental reasons during 3.2 development but it
+      has shown that this is not stable enough. Going back to wait for the
+      adapter to be not busy is best.
+   2) Inquiry requests can be shorter than 255 bytes of return buffer. Due
+      to a bug in the ibmmca_queuecommand routine, this buffer was forced
+      to 255 at minimum. If the memory address, this return buffer is pointing
+      to does not offer more space, invalid memory accesses destabilized the
+      kernel.
+   3) version 4.0 is only valid for kernel 2.4.0 or later. This is necessary
+      to remove old kernel version dependant waste from the driver. 3.2d is
+      only distributed with older kernels but keeps compatibility with older
+      kernel versions. 4.0 and higher versions cannot be used with older 
+      kernels anymore!! You must have at least kernel 2.4.0!!
+   4) The commandline argument 'bypass' and all its functionality got removed
+      in version 4.0. This was never really necessary, as all troubles were
+      based on non-command related reasons up to now, so bypassing commands
+      did not help to avoid any bugs. It is kept in 3.2X for debugging reasons.
+   5) Dynamical reassignment of ldns was again verified and analyzed to be
+      completely inoperational. This is corrected and should work now.
+   6) All commands that get sent to the SCSI adapter were verified and
+      completed in such a way, that they are now completely conform to the
+      demands in the technical description of IBM. Main candidates were the
+      DEVICE_INQUIRY, REQUEST_SENSE and DEVICE_CAPACITY commands. They must
+      be tranferred by bypassing the internal command buffer of the adapter
+      or else the response can be a random result. GET_POS_INFO would be more
+      safe in usage, if one could use the SUPRESS_EXCEPTION_SHORT, but this
+      is not allowed by the technical references of IBM. (Sorry, folks, the
+      model 80 problem is still a task to be solved in a different way.)
+   7) v3.2d is still hold back for some days for testing, while 4.0 is 
+      released.
+   - Michael Lang
+   
+   January 3, 2001 (v4.0a)
+   1) A lot of complains after the 2.4.0-prerelease kernel came in about
+      the impossibility to compile the driver as a module. This problem is
+      solved. In combination with that problem, some unprecise declaration
+      of the function option_setup() gave some warnings during compilation.
+      This is solved, too by a forward declaration in ibmmca.c.
+   2) #ifdef argument concerning CONFIG_SCSI_IBMMCA is no longer needed and
+      was entirely removed.
+   3) Some switch statements got optimized in code, as some minor variables
+      in internal SCSI-command handlers.
+   - Michael Lang
+
+   4 To do
+   -------
+        - IBM SCSI-2 F/W external SCSI bus support in seperate mode!
+	- It seems that the handling of bad disks is really bad -
+	  non-existent, in fact. However, a low-level driver cannot help
+	  much, if such things happen.
+
+   5 Users' Manual
+   ---------------
+   5.1 Commandline Parameters
+   --------------------------
+   There exist several features for the IBM SCSI-subsystem driver.
+   The commandline parameter format is:
+   
+         ibmmcascsi=<command1>,<command2>,<command3>,...
+	 
+   where commandN can be one of the following:
+   
+         display    Owners of a model 95 or other PS/2 systems with an
+	            alphanumeric LED display may set this to have their
+		    display showing the following output of the 8 digits:
+		      
+		                ------DA
+				
+		    where '-' stays dark, 'D' shows the SCSI-device id
+		    and 'A' shows the SCSI hostindex, beeing currently 
+		    accessed. During boottime, this will give the message
+		    
+		                SCSIini*
+				
+                    on the LED-panel, where the * represents a rotator, 
+		    showing the activity during the probing phase of the
+		    driver which can take up to two minutes per SCSI-adapter.
+	 adisplay   This works like display, but gives more optical overview 
+	            of the activities on the SCSI-bus. The display will have
+		    the following output:
+		    
+		                6543210A
+				
+		    where the numbers 0 to 6 light up at the shown position,
+		    when the SCSI-device is accessed. 'A' shows again the SCSI
+		    hostindex. If display nor adisplay is set, the internal
+		    PS/2 harddisk LED is used for media-activities. So, if
+		    you really do not have a system with a LED-display, you
+		    should not set display or adisplay. Keep in mind, that
+		    display and adisplay can only be used alternatively. It
+		    is not recommended to use this option, if you have some
+		    wide-addressed devices e.g. at the SCSI-2 F/W adapter in
+		    your system. In addition, the usage of the display for
+		    other tasks in parallel, like the linuxinfo-utility makes 
+		    no sense with this option.
+	 activity   This enables the PS/2 harddisk LED activity indicator.
+	            Most PS/2 have no alphanumeric LED display, but some
+		    indicator. So you should use this parameter to activate it.
+		    If you own model 9595 (Server95), you can have both, the 
+		    LED panel and the activity indicator in parallel. However,
+		    some PS/2s, like the 8595 do not have any harddisk LED 
+		    activity indicator, which means, that you must use the
+		    alphanumeric LED display if you want to monitor SCSI-
+		    activity.
+	 bypass     This is obsolete from driver version 4.0, as the adapters
+	            got that far understood, that the selection between 
+		    integrated and bypassed commands should now work completely
+		    correct! For historical reasons, the old description is
+		    kept here:
+	            This commandline parameter forces the driver never to use
+	            SCSI-subsystems' integrated SCSI-command set. Except of
+		    the immediate assign, which is of vital importance for
+		    every IBM SCSI-subsystem to set its ldns right. Instead,
+		    the ordinary ANSI-SCSI-commands are used and passed by the
+		    controller to the SCSI-devices, therefore 'bypass'. The
+		    effort, done by the subsystem is quite bogus and at a
+		    minimum and therefore it should work everywhere. This
+		    could maybe solve troubles with old or integrated SCSI-
+		    controllers and nasty harddisks. Keep in mind, that using 
+		    this flag will slow-down SCSI-accesses slightly, as the 
+		    software generated commands are always slower than the 
+		    hardware. Non-harddisk devices always get read/write-
+		    commands in bypass mode. On the most recent releases of 
+		    the Linux IBM-SCSI-driver, the bypass command should be
+		    no longer a necessary thing, if you are sure about your
+		    SCSI-hardware!
+	 normal     This is the parameter, introduced on the 2.0.x development
+	            rail by ZP Gu. This parameter defines the SCSI-device
+		    scan order in the new industry standard. This means, that
+		    the first SCSI-device is the one with the lowest pun.
+		    E.g. harddisk at pun=0 is scanned before harddisk at
+		    pun=6, which means, that harddisk at pun=0 gets sda
+		    and the one at pun=6 gets sdb.
+	 ansi       The ANSI-standard for the right scan order, as done by
+	            IBM, Microware and Microsoft, scans SCSI-devices starting
+		    at the highest pun, which means, that e.g. harddisk at
+		    pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
+		    like to have the same SCSI-device order, as in DOS, OS-9
+		    or OS/2, just use this parameter.
+         fast       SCSI-I/O in synchronous mode is done at 5 MHz for IBM-
+                    SCSI-devices. SCSI-2 Fast/Wide Adapter/A external bus
+                    should then run at 10 MHz if Fast-SCSI is enabled,
+                    and at 5 MHz if Fast-SCSI is disabled on the external
+                    bus. This is the default setting when nothing is 
+                    specified here.
+         medium     Synchronous rate is at 50% approximately, which means
+                    2.5 MHz for IBM SCSI-adapters and 5.0 MHz for F/W ext.
+                    SCSI-bus (when Fast-SCSI speed enabled on external bus).
+         slow       The slowest possible synchronous transfer rate is set. 
+                    This means 1.82 MHz for IBM SCSI-adapters and 2.0 MHz
+                    for F/W external bus at Fast-SCSI speed on the external
+		    bus.
+		    
+   A further option is that you can force the SCSI-driver to accept a SCSI-
+   subsystem at a certain I/O-address with a predefined adapter PUN. This
+   is done by entering 
+
+                  commandN   = I/O-base
+		  commandN+1 = adapter PUN
+		  
+   e.g. ibmmcascsi=0x3540,7 will force the driver to detect a SCSI-subsystem 
+   at I/O-address 0x3540 with adapter PUN 7. Please only use this method, if
+   the driver does really not recognize your SCSI-adapter! With driver version
+   3.2, this recognition of various adapters was hugely improved and you
+   should try first to remove your commandline arguments of such type with a 
+   newer driver. I bet, it will be recognized correctly. Even multiple and 
+   different types of IBM SCSI-adapters should be recognized correctly, too.
+   Use the forced detection method only as last solution!
+   
+   Examples:
+   
+        ibmmcascsi=adisplay
+	
+   This will use the advanced display mode for the model 95 LED alphanumeric
+   display.
+   
+        ibmmcascsi=display,0x3558,7
+	
+   This will activate the default display mode for the model 95 LED display
+   and will force the driver to accept a SCSI-subsystem at I/O-base 0x3558
+   with adapter PUN 7.
+   
+   5.2 Troubleshooting
+   -------------------
+   The following FAQs should help you to solve some major problems with this
+   driver.
+   
+     Q: "Reset SCSI-devices at boottime" halts the system at boottime, why?
+     A: This is only tested with the IBM SCSI Adapter w/cache. It is not
+        yet prooved to run on other adapters, however you may be lucky.
+	In version 3.1d this has been hugely improved and should work better,
+	now. Normally you really won't need to activate this flag in the
+	kernel configuration, as all post 1989 SCSI-devices should accept
+	the reset-signal, when the computer is switched on. The SCSI-
+	subsystem generates this reset while beeing initialized. This flag
+	is really reserved for users with very old, very strange or self-made
+	SCSI-devices.
+     Q: Why is the SCSI-order of my drives mirrored to the device-order
+        seen from OS/2 or DOS ?
+     A: It depends on the operating system, if it looks at the devices in
+        ANSI-SCSI-standard (starting from pun 6 and going down to pun 0) or
+	if it just starts at pun 0 and counts up. If you want to be conform
+	with OS/2 and DOS, you have to activate this flag in the kernel
+	configuration or you should set 'ansi' as parameter for the kernel.
+	The parameter 'normal' sets the new industry standard, starting
+	from pun 0, scanning up to pun 6. This allows you to change your 
+	opinion still after having already compiled the kernel.
+     Q: Why I cannot find the IBM MCA SCSI support in the config menue?
+     A: You have to activate MCA bus support, first.
+     Q: Where can I find the latest info about this driver?
+     A: See the file MAINTAINERS for the current WWW-address, which offers
+        updates, info and Q/A lists. At this files' origin, the webaddress
+	was: http://www.uni-mainz.de/~langm000/linux.html
+     Q: My SCSI-adapter is not recognized by the driver, what can I do?
+     A: Just force it to be recognized by kernel parameters. See section 5.1.
+        If this really happens, do also send e-mail to the maintainer, as
+	forced detection should be never necessary. Forced detection is in
+	principal some flaw of the driver adapter detection and goes into 
+	bugreports.
+     Q: The driver screws up, if it starts to probe SCSI-devices, is there
+        some way out of it?
+     A: Yes, that was some recognition problem of the correct SCSI-adapter
+        and its I/O base addresses. Upgrade your driver to the latest release
+	and it should be fine again.
+     Q: I get a message: panic IBM MCA SCSI: command error .... , what can
+        I do against this?
+     A: Previously, I followed the way by ignoring command errors by using
+        ibmmcascsi=forgiveall, but this command no longer exists and is
+	obsolete. If such a problem appears, it is caused by some segmentation
+	fault of the driver, which maps to some unallowed area. The latest 
+	version of the driver should be ok, as most bugs have been solved.
+     Q: There are still kernel panics, even after having set 
+        ibmmcascsi=forgiveall. Are there other possibilities to prevent
+	such panics?
+     A: No, get just the latest release of the driver and it should work 
+        better and better with increasing version number. Forget about this
+	ibmmcascsi=forgiveall, as also ignorecmd are obsolete.!
+     Q: Linux panics or stops without any comment, but it is probable, that my
+        harddisk(s) have bad blocks.
+     A: Sorry, the bad-block handling is still a feeble point of this driver,
+        but is on the schedule for development in the near future.
+     Q: Linux panics while dynamically assigning SCSI-ids or ldns.
+     A: If you disconnect a SCSI-device from the machine, while Linux is up
+        and the driver uses dynamical reassignment of logical device numbers
+	(ldn), it really gets "angry" if it won't find devices, that were still
+	present at boottime and stops Linux.
+     Q: The system does not recover after an abort-command has been generated.
+     A: This is regrettably true, as it is not yet understood, why the 
+        SCSI-adapter does really NOT generate any interrupt at the end of
+	the abort-command. As no interrupt is generated, the abort command
+	cannot get finished and the system hangs, sorry, but checks are 
+	running to hunt down this problem. If there is a real pending command,
+	the interrupt MUST get generated after abort. In this case, it
+	should finish well.
+     Q: The system gets in bad shape after a SCSI-reset, is this known?
+     A: Yes, as there are a lot of prescriptions (see the Linux Hackers'
+        Guide) what has to be done for reset, we still share the bad shape of
+	the reset functions with all other low level SCSI-drivers. 
+	Astonishingly, reset works in most cases quite ok, but the harddisks
+	won't run in synchonous mode anymore after a reset, until you reboot.
+     Q: Why does my XXX w/Cache adapter not use read-prefetch?
+     A: Ok, that is not completely possible. If a cache is present, the 
+        adapter tries to use it internally. Explicitly, one can use the cache
+	with a read prefetch command, maybe in future, but this requires
+	some major overhead of SCSI-commands that risks the performance to
+	go down more than it gets improved. Tests with that are running.
+     Q: I have a IBM SCSI-2 Fast/Wide adapter, it boots in some way and hangs.
+     A: Yes, that is understood, as for sure, your SCSI-2 Fast/Wide adapter
+        was in such a case recognized as integrated SCSI-adapter or something 
+	else, but not as the correct adapter. As the I/O-ports get assigned 
+	wrongly by that reason, the system should crash in most cases. You 
+	should upgrade to the latest release of the SCSI-driver. The 
+	recommended version is 3.2 or later. Here, the F/W support is in
+	a stable and reliable condition. Wide-addressing is in addition 
+	supported.
+     Q: I get a Ooops message and something like "killing interrupt".
+     A: The reason for this is that the IBM SCSI-subsystem only sends a 
+        termination status back, if some error appeared. In former releases
+	of the driver, it was not checked, if the termination status block
+	is NULL. From version 3.2, it is taken care of this.
+     Q: I have a F/W adapter and the driver sees my internal SCSI-devices,
+        but ignores the external ones.
+     A: Select combined busmode in the IBM config-program and check for that
+        no SCSI-id on the external devices appears on internal devices.
+        Reboot afterwards. Dual busmode is supported, but works only for the
+	internal bus, yet. External bus is still ignored. Take care for your
+	SCSI-ids. If combined bus-mode is activated, on some adapters, 
+	the wide-addressing is not possible, so devices with ids between 8 
+	and 15 get ignored by the driver & adapter!
+     Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck.
+        A COMMAND ERROR is reported and characters on the screen are missing.
+	Warm reboot is not possible. Things look like quite weired.
+     A: Check the processor type of your 9595. If you have an 80486 or 486DX-2
+        processor complex on your mainboard and you compiled a kernel that
+	supports 80386 processors, it is possible, that the kernel cannot
+	keep track of the PS/2 interrupt handling and stops on an NMI. Just
+	compile a kernel for the correct processor type of your PS/2 and
+	everything should be fine. This is necessary even if one assumes,
+	that some 80486 system should be downward compatible to 80386
+	software.
+     Q: Some commands hang and interrupts block the machine. After some
+        timeout, the syslog reports that it tries to call abort, but the
+	machine is frozen.
+     A: This can be a busy wait bug in the interrupt handler of driver 
+        version 3.2. You should at least upgrade to 3.2c if you use 
+	kernel < 2.4.0 and driver version 4.0 if you use kernel 2.4.0 or 
+	later (including all test releases).
+     Q: I have a PS/2 model 80 and more than 16 MBytes of RAM. The driver
+        completely refuses to work, reports NMIs, COMMAND ERRORs or other
+	ambiguous stuff. When reducing the RAM size down below 16 MB, 
+	everything is running smoothly.
+     A: No real answer, yet. In any case, one should force the kernel to
+        present SCBs only below the 16 MBytes barrier. Maybe this solves the
+	problem. Not yet tried, but guessing that it could work. To get this,
+	set unchecked_isa_dma argument of ibmmca.h from 0 to 1.
+
+   5.3 Bugreports
+   --------------
+   If you really find bugs in the sourcecode or the driver will successfully
+   refuse to work on your machine, you should send a bug report to me. The
+   best for this is to follow the instructions on the WWW-page for this
+   driver. Fill out the bug-report form, placed on the WWW-page and ship it,
+   so the bugs can be taken into account with maximum efforts. But, please
+   do not send bug reports about this driver to Linus Torvalds or Leonard
+   Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
+   SCSI-drivers and won't have the time left to look inside every single
+   driver to fix a bug and especially DO NOT send modified code to Linus
+   Torvalds or Alan J. Cox which has not been checked here!!! They are both
+   quite burried in E-mail (as me, sometimes, too) and one should first check
+   for problems on my local teststand. Recently, I got a lot of 
+   bugreports for errors in the ibmmca.c code, which I could not imagine, but
+   a look inside some Linux-distribution showed me quite often some modified
+   code, which did no longer work on most other machines than the one of the
+   modifier. Ok, so now that there is maintenance service available for this
+   driver, please use this address first in order to keep the level of
+   confusion low. Thank you!
+   
+   When you get a SCSI-error message that panics your system, a list of
+   register-entries of the SCSI-subsystem is shown (from Version 3.1d). With 
+   this list, it is very easy for the maintainer to localize the problem in 
+   the driver or in the configuration of the user. Please write down all the 
+   values from this report and send them to the maintainer. This would really 
+   help a lot and makes life easier concerning misunderstandings.
+   
+   Use the bug-report form (see 5.4 for its address) to send all the bug-
+   stuff to the maintainer or write e-mail with the values from the table. 
+   
+   5.4 Support WWW-page
+   --------------------
+   The address of the IBM SCSI-subsystem supporting WWW-page is:
+   
+        http://www.uni-mainz.de/~langm000/linux.html
+	
+   Here you can find info about the background of this driver, patches,
+   troubleshooting support, news and a bugreport form. Please check that
+   WWW-page regularly for latest hints. If ever this URL changes, please 
+   refer to the MAINTAINERS file in order to get the latest address.
+   
+   For the bugreport, please fill out the formular on the corresponding
+   WWW-page. Read the dedicated instructions and write as much as you
+   know about your problem. If you do not like such formulars, please send
+   some e-mail directly, but at least with the same information as required by
+   the formular.
+   
+   If you have extensive bugreports, including Ooops messages and 
+   screen-shots, please feel free to send it directly to the address
+   of the maintainer, too. The current address of the maintainer is:
+   
+            Michael Lang <langa2@kph.uni-mainz.de>
+   
+   6 References
+   ------------
+   IBM Corp., "Update for the PS/2 Hardware Interface Technical Reference, 
+   Common Interfaces", Armonk, September 1991, PN 04G3281, 
+   (available in the U.S. for $21.75 at 1-800-IBM-PCTB or in Germany for
+   around 40,-DM at "Hallo IBM").
+  
+   IBM Corp., "Personal System/2 Micro Channel SCSI
+   Adapter with Cache Technical Reference", Armonk, March 1990, PN 68X2365.
+
+   IBM Corp., "Personal System/2 Micro Channel SCSI
+   Adapter Technical Reference", Armonk, March 1990, PN 68X2397.
+
+   IBM Corp., "SCSI-2 Fast/Wide Adapter/A Technical Reference - Dual Bus",
+   Armonk, March 1994, PN 83G7545.
+ 
+   Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
+   Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
+   Addison Wesley, 1996.
+   
+   Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
+   Hill - North Carolina, 1995
+   
+   Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
+   1993
+   
+   Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
+   Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
+   
+   7 Credits to
+   ------------
+   7.1 People
+   ----------
+   Klaus Grimm
+                who already a long time ago gave me the old code from the
+		SCSI-driver in order to get it running for some old machine
+		in our institute.
+   Martin Kolinek
+                who wrote the first release of the IBM SCSI-subsystem driver.
+   Chris Beauregard
+                who for a long time maintained MCA-Linux and the SCSI-driver
+		in the beginning. Chris, wherever you are: Cheers to you!
+   Klaus Kudielka
+                with whom in the 2.1.x times, I had a quite fruitful
+                cooperation to get the driver running as a module and to get
+		it running with multiple SCSI-adapters.
+   David Weinehall
+                for his excellent maintenance of the MCA-stuff and the quite 
+		detailed bug reports and ideas for this driver (and his 
+		patience ;-)).
+   Alan J. Cox  
+                for his bugreports and his bold activities in cross-checking
+		the driver-code with his teststand.
+		
+   7.2 Sponsors & Supporters
+   -------------------------
+   "Hallo IBM",
+   IBM-Deutschland GmbH
+                the service of IBM-Deutschland for customers. Their E-Mail
+		service is unbeatable. Whatever old stuff I asked for, I 
+		always got some helpful answers.
+   Karl-Otto Reimers,
+   IBM Klub - Sparte IBM Geschichte, Sindelfingen
+                for sending me a copy of the w/Cache manual from the 
+		IBM-Deutschland archives.
+   Harald Staiger
+                for his extensive hardware donations which allows me today
+		still to test the driver in various constellations.
+   Erich Fritscher
+                for his very kind sponsoring.
+   Louis Ohland,
+   Charles Lasitter
+                for support by shipping me an IBM SCSI-2 Fast/Wide manual.
+                In addition, the contribution of various hardware is quite 
+                decessive and will make it possible to add FWSR (RAID)
+                adapter support to the driver in the near future! So,
+                complaints about no RAID support won't remain forever.
+                Yes, folks, that is no joke, RAID support is going to rise!
+   Erik Weber
+                for the great deal we made about a model 9595 and the nice
+                surrounding equipment and the cool trip to Mannheim
+                second-hand computer market. In addition, I would like
+		to thank him for his exhaustive SCSI-driver testing on his 
+		95er PS/2 park.
+   Anthony Hogbin
+                for his direct shipment of a SCSI F/W adapter, which allowed
+                me immediately on the first stage to try it on model 8557
+                together with onboard SCSI adapter and some SCSI w/Cache.
+   Andreas Hotz
+                for his support by memory and an IBM SCSI-adapter. Collecting
+                all this together now allows me to try really things with
+                the driver at maximum load and variety on various models in
+                a very quick and efficient way.
+   Peter Jennewein
+                for his model 30, which serves me as part of my teststand
+		and his cool remark about how you make an ordinary diskette
+		drive working and how to connect it to an IBM-diskette port.
+   Johannes Gutenberg-Universitaet, Mainz &
+   Institut fuer Kernphysik, Mainz Microtron (MAMI)
+                for the offered space, the link, placed on the central
+                homepage and the space to store and offer the driver and 
+		related material and the free working times, which allow
+                me to answer all your e-mail.
+                   
+   8 Trademarks
+   ------------
+   IBM, PS/2, OS/2, Microchannel are registered trademarks of International 
+   Business Machines Corporation
+   
+   MS-DOS is a registered trademark of Microsoft Corporation
+   
+   Microware, OS-9 are registered trademarks of Microware Systems
+   
+   9 Disclaimer
+   ------------
+   Beside the GNU General Public License and the dependant disclaimers and disclaimers
+   concerning the Linux-kernel in special, this SCSI-driver comes without any
+   warranty. Its functionality is tested as good as possible on certain 
+   machines and combinations of computer hardware, which does not exclude,
+   that dataloss or severe damage of hardware is possible while using this
+   part of software on some arbitrary computer hardware or in combination 
+   with other software packages. It is highly recommended to make backup
+   copies of your data before using this software. Furthermore, personal
+   injuries by hardware defects, that could be caused by this SCSI-driver are
+   not excluded and it is highly recommended to handle this driver with a
+   maximum of carefulness.
+   
+   This driver supports hardware, produced by International Business Machines
+   Corporation (IBM).
+   
+------
+Michael Lang 
+(langa2@kph.uni-mainz.de)
diff -Nru a/Documentation/scsi/in2000.txt b/Documentation/scsi/in2000.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/in2000.txt	Sun Nov 17 20:30:13 2002
@@ -0,0 +1,202 @@
+
+UPDATE NEWS: version 1.33 - 26 Aug 98
+
+   Interrupt management in this driver has become, over
+   time, increasingly odd and difficult to explain - this
+   has been mostly due to my own mental inadequacies. In
+   recent kernels, it has failed to function at all when
+   compiled for SMP. I've fixed that problem, and after
+   taking a fresh look at interrupts in general, greatly
+   reduced the number of places where they're fiddled
+   with. Done some heavy testing and it looks very good.
+   The driver now makes use of the __initfunc() and
+   __initdata macros to save about 4k of kernel memory.
+   Once again, the same code works for both 2.0.xx and
+   2.1.xx kernels.
+
+UPDATE NEWS: version 1.32 - 28 Mar 98
+
+   Removed the check for legal IN2000 hardware versions:
+   It appears that the driver works fine with serial
+   EPROMs (the 8-pin chip that defines hardware rev) as
+   old as 2.1, so we'll assume that all cards are OK.
+
+UPDATE NEWS: version 1.31 - 6 Jul 97
+
+   Fixed a bug that caused incorrect SCSI status bytes to be
+   returned from commands sent to LUN's greater than 0. This
+   means that CDROM changers work now! Fixed a bug in the
+   handling of command-line arguments when loaded as a module.
+   Also put all the header data in in2000.h where it belongs.
+   There are no longer any differences between this driver in
+   the 2.1.xx source tree and the 2.0.xx tree, as of 2.0.31
+   and 2.1.45 (or is it .46?) - this makes things much easier
+   for me...
+
+UPDATE NEWS: version 1.30 - 14 Oct 96
+
+   Fixed a bug in the code that sets the transfer direction
+   bit (DESTID_DPD in the WD_DESTINATION_ID register). There
+   are quite a few SCSI commands that do a write-to-device;
+   now we deal with all of them correctly. Thanks to Joerg
+   Dorchain for catching this one.
+
+UPDATE NEWS: version 1.29 - 24 Sep 96
+
+   The memory-mapped hardware on the card is now accessed via
+   the 'readb()' and 'readl()' macros - required by the new
+   memory management scheme in the 2.1.x kernel series.
+   As suggested by Andries Brouwer, 'bios_param()' no longer
+   forces an artificial 1023 track limit on drives. Also
+   removed some kludge-code left over from struggles with
+   older (buggy) compilers.
+
+UPDATE NEWS: version 1.28 - 07 May 96
+
+   Tightened up the "interrupts enabled/disabled" discipline
+   in 'in2000_queuecommand()' and maybe 1 or 2 other places.
+   I _think_ it may have been a little too lax, causing an
+   occasional crash during full moon. A fully functional
+   /proc interface is now in place - if you want to play
+   with it, start by doing 'cat /proc/scsi/in2000/0'. You
+   can also use it to change a few run-time parameters on
+   the fly, but it's mostly for debugging. The curious
+   should take a good look at 'in2000_proc_info()' in the
+   in2000.c file to get an understanding of what it's all
+   about; I figure that people who are really into it will
+   want to add features suited to their own needs...
+   Also, sync is now DISABLED by default.
+
+UPDATE NEWS: version 1.27 - 10 Apr 96
+
+   Fixed a well-hidden bug in the adaptive-disconnect code
+   that would show up every now and then during extreme
+   heavy loads involving 2 or more simultaneously active
+   devices. Thanks to Joe Mack for keeping my nose to the
+   grindstone on this one.
+
+UPDATE NEWS: version 1.26 - 07 Mar 96
+
+   1.25 had a nasty bug that bit people with swap partitions
+   and tape drives. Also, in my attempt to guess my way
+   through Intel assembly language, I made an error in the
+   inline code for IO writes. Made a few other changes and
+   repairs - this version (fingers crossed) should work well.
+
+UPDATE NEWS: version 1.25 - 05 Mar 96
+
+   Kernel 1.3.70 interrupt mods added; old kernels still OK.
+   Big help from Bill Earnest and David Willmore on speed
+   testing and optimizing: I think there's a real improvement
+   in this area.
+   New! User-friendly command-line interface for LILO and
+   module loading - the old method is gone, so you'll need
+   to read the comments for 'setup_strings' near the top
+   of in2000.c. For people with CDROM's or other devices
+   that have a tough time with sync negotiation, you can
+   now selectively disable sync on individual devices -
+   search for the 'nosync' keyword in the command-line
+   comments. Some of you disable the BIOS on the card, which
+   caused the auto-detect function to fail; there is now a
+   command-line option to force detection of a ROM-less card.
+
+UPDATE NEWS: version 1.24a - 24 Feb 96
+
+   There was a bug in the synchronous transfer code. Only
+   a few people downloaded before I caught it - could have
+   been worse.
+
+UPDATE NEWS: version 1.24 - 23 Feb 96
+
+   Lots of good changes. Advice from Bill Earnest resulted
+   in much better detection of cards, more efficient usage
+   of the fifo, and (hopefully) faster data transfers. The
+   jury is still out on speed - I hope it's improved some.
+   One nifty new feature is a cool way of doing disconnect/
+   reselect. The driver defaults to what I'm calling
+   'adaptive disconnect' - meaning that each command is
+   evaluated individually as to whether or not it should be
+   run with the option to disconnect/reselect (if the device
+   chooses), or as a "SCSI-bus-hog". When several devices
+   are operating simultaneously, disconnects are usually an
+   advantage. In a single device system, or if only 1 device
+   is being accessed, transfers usually go faster if disconnects
+   are not allowed.
+
+
+
+The default arguments (you get these when you don't give an 'in2000'
+command-line argument, or you give a blank argument) will cause
+the driver to do adaptive disconnect, synchronous transfers, and a
+minimum of debug messages. If you want to fool with the options,
+search for 'setup_strings' near the top of the in2000.c file and
+check the 'hostdata->args' section in in2000.h - but be warned! Not
+everything is working yet (some things will never work, probably).
+I believe that disabling disconnects (DIS_NEVER) will allow you
+to choose a LEVEL2 value higher than 'L2_BASIC', but I haven't
+spent a lot of time testing this. You might try 'ENABLE_CLUSTERING'
+to see what happens: my tests showed little difference either way.
+There's also a define called 'DEFAULT_SX_PER'; this sets the data
+transfer speed for the asynchronous mode. I've put it at 500 ns
+despite the fact that the card could handle settings of 376 or
+252, because higher speeds may be a problem with poor quality
+cables or improper termination; 500 ns is a compromise. You can
+choose your own default through the command-line with the
+'period' keyword.
+
+
+------------------------------------------------
+***********  DIP switch settings  **************
+------------------------------------------------
+
+   sw1-1 sw1-2    BIOS address (hex)
+   -----------------------------------------
+    off   off     C8000 - CBFF0
+    on    off     D8000 - DBFF0
+    off   on      D0000 - D3FF0
+    on    on      BIOS disabled
+
+   sw1-3 sw1-4    IO port address (hex)
+   ------------------------------------
+    off   off     220 - 22F
+    on    off     200 - 20F
+    off   on      110 - 11F
+    on    on      100 - 10F
+
+   sw1-5 sw1-6 sw1-7    Interrupt
+   ------------------------------
+    off   off   off     15
+    off   on    off     14
+    off   off   on      11
+    off   on    on      10
+    on    -     -       disabled
+
+   sw1-8 function depends on BIOS version. In earlier versions this
+   controlled synchronous data transfer support for MSDOS:
+      off = disabled
+      on  = enabled
+   In later ROMs (starting with 01.3 in April 1994) sw1-8 controls
+   the "greater than 2 disk drive" feature that first appeared in
+   MSDOS 5.0 (ignored by Linux):
+      off = 2 drives maximum
+      on  = 7 drives maximum
+
+   sw1-9    Floppy controller
+   --------------------------
+    off     disabled
+    on      enabled
+
+------------------------------------------------
+
+   I should mention that Drew Eckhardt's 'Generic NCR5380' sources
+   were my main inspiration, with lots of reference to the IN2000
+   driver currently distributed in the kernel source. I also owe
+   much to a driver written by Hamish Macdonald for Linux-m68k(!).
+   And to Eric Wright for being an ALPHA guinea pig. And to Bill
+   Earnest for 2 tons of great input and information. And to David
+   Willmore for extensive 'bonnie' testing. And to Joe Mack for
+   continual testing and feedback.
+
+
+            John Shifflett    jshiffle@netcom.com
+
diff -Nru a/Documentation/scsi/ncr53c7xx.txt b/Documentation/scsi/ncr53c7xx.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ncr53c7xx.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,40 @@
+README for WarpEngine/A4000T/A4091 SCSI kernels.
+
+Use the following options to disable options in the SCSI driver.
+
+Using amiboot for example.....
+
+To disable Synchronous Negotiation....
+
+	amiboot -k kernel 53c7xx=nosync:0	
+
+To disable Disconnection....
+	
+	amiboot -k kernel 53c7xx=nodisconnect:0
+
+To disable certain SCSI devices...
+
+	amiboot -k kernel 53c7xx=validids:0x3F
+
+	this allows only device ID's 0,1,2,3,4 and 5 for linux to handle.
+	(this is a bitmasked field - i.e. each bit represents a SCSI ID)
+
+These commands work on a per controller basis and use the option 'next' to
+move to the next controller in the system.
+
+e.g.
+	amiboot -k kernel 53c7xx=nodisconnect:0,next,nosync:0
+
+	this uses No Disconnection on the first controller and Asynchronous
+	SCSI on the second controller.
+
+Known Issues:
+
+Two devices are known not to function with the default settings of using
+synchronous SCSI. These are the Archive Viper 150 Tape Drive and the 
+SyQuest SQ555 removeable hard drive. When using these devices on a controller
+use the 'nosync:0' option.
+
+Please try these options and post any problems/successes to me.
+
+Alan Hourihane <alanh@fairlite.demon.co.uk>
diff -Nru a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ncr53c8xx.txt	Sun Nov 17 20:30:02 2002
@@ -0,0 +1,1854 @@
+The Linux NCR53C8XX/SYM53C8XX drivers README file
+
+Written by Gerard Roudier <groudier@free.fr>
+21 Rue Carnot
+95170 DEUIL LA BARRE - FRANCE
+
+29 May 1999
+===============================================================================
+
+1.  Introduction
+2.  Supported chips and SCSI features
+3.  Advantages of the enhanced 896 driver
+      3.1 Optimized SCSI SCRIPTS
+      3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
+4.  Memory mapped I/O versus normal I/O
+5.  Tagged command queueing
+6.  Parity checking
+7.  Profiling information
+8.  Control commands
+      8.1  Set minimum synchronous period
+      8.2  Set wide size
+      8.3  Set maximum number of concurrent tagged commands
+      8.4  Set order type for tagged command
+      8.5  Set debug mode
+      8.6  Clear profile counters
+      8.7  Set flag (no_disc)
+      8.8  Set verbose level
+      8.9  Reset all logical units of a target
+      8.10 Abort all tasks of all logical units of a target
+9.  Configuration parameters
+10. Boot setup commands
+      10.1 Syntax
+      10.2 Available arguments
+             10.2.1  Master parity checking
+             10.2.2  Scsi parity checking
+             10.2.3  Scsi disconnections
+             10.2.4  Special features
+             10.2.5  Ultra SCSI support
+             10.2.6  Default number of tagged commands
+             10.2.7  Default synchronous period factor
+             10.2.8  Negotiate synchronous with all devices
+             10.2.9  Verbosity level
+             10.2.10 Debug mode
+             10.2.11 Burst max
+             10.2.12 LED support
+             10.2.13 Max wide
+             10.2.14 Differential mode
+             10.2.15 IRQ mode
+             10.2.16 Reverse probe
+             10.2.17 Fix up PCI configuration space
+             10.2.18 Serial NVRAM
+             10.2.19 Check SCSI BUS 
+             10.2.20 Exclude a host from being attached
+             10.2.21 Suggest a default SCSI id for hosts
+             10.2.22 Enable use of IMMEDIATE ARBITRATION
+      10.3 Advised boot setup commands
+      10.4 PCI configuration fix-up boot option
+      10.5 Serial NVRAM support boot option
+      10.6 SCSI BUS checking boot option
+      10.7 IMMEDIATE ARBITRATION boot option
+11. Some constants and flags of the ncr53c8xx.h header file
+12. Installation
+13. Architecture dependent features
+14. Known problems
+      14.1 Tagged commands with Iomega Jaz device
+      14.2 Device names change when another controller is added
+      14.3 Using only 8 bit devices with a WIDE SCSI controller.
+      14.4 Possible data corruption during a Memory Write and Invalidate
+      14.5 IRQ sharing problems
+15. SCSI problem troubleshooting
+      15.1 Problem tracking
+      15.2 Understanding hardware error reports
+16. Synchonous transfer negotiation tables
+      16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
+      16.2 Synchronous timings for fast SCSI-2 53C8XX controllers
+17. Serial NVRAM support (by Richard Waltham)
+      17.1 Features
+      17.2 Symbios NVRAM layout
+      17.3 Tekram  NVRAM layout
+18. Support for Big Endian
+      18.1 Big Endian CPU
+      18.2 NCR chip in Big Endian mode of operations
+
+===============================================================================
+
+1. Introduction
+
+The initial Linux ncr53c8xx driver has been a port of the ncr driver from 
+FreeBSD that has been achieved in November 1995 by:
+          Gerard Roudier              <groudier@free.fr>
+
+The original driver has been written for 386bsd and FreeBSD by:
+          Wolfgang Stanglmeier        <wolf@cologne.de>
+          Stefan Esser                <se@mi.Uni-Koeln.de>
+
+It is now available as a bundle of 2 drivers:
+
+- ncr53c8xx generic driver that supports all the SYM53C8XX family including 
+  the ealiest 810 rev. 1, the latest 896 (2 channel LVD SCSI controller) and
+  the new 895A (1 channel LVD SCSI controller).
+- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest 
+  chips in order to gain advantage of new features, as LOAD/STORE intructions 
+  available since the 810A and hardware phase mismatch available with the 
+  896 and the 895A.
+
+You can find technical information about the NCR 8xx family in the
+PCI-HOWTO written by Michael Will and in the SCSI-HOWTO written by
+Drew Eckhardt.
+
+Information about new chips is available at LSILOGIC web server:
+
+          http://www.lsilogic.com/
+
+SCSI standard documentations are available at SYMBIOS ftp server:
+
+          ftp://ftp.symbios.com/
+
+Usefull SCSI tools written by Eric Youngdale are available at tsx-11:
+
+          ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz
+          ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz
+
+These tools are not ALPHA but quite clean and work quite well.
+It is essential you have the 'scsiinfo' package.
+
+This short documentation describes the features of the generic and enhanced
+drivers, configuration parameters and control commands available through 
+the proc SCSI file system read / write operations.
+
+This driver has been tested OK with linux/i386, Linux/Alpha and Linux/PPC.
+
+Latest driver version and patches are available at:
+
+          ftp://ftp.tux.org/pub/people/gerard-roudier
+or
+          ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers
+
+I am not a native speaker of English and there are probably lots of
+mistakes in this README file. Any help will be welcome.
+
+
+2. Supported chips and SCSI features
+
+The following features are supported for all chips:
+
+	Synchronous negotiation
+	Disconnection
+	Tagged command queuing
+	SCSI parity checking
+	Master parity checking
+
+"Wide negotiation" is supported for chips that allow it.  The
+following table shows some characteristics of NCR 8xx family chips 
+and what drivers support them.
+
+                                                  Supported by   Supported by
+       On board                                   the generic    the enhanced 
+Chip   SDMS BIOS   Wide   SCSI std.   Max. sync   driver         driver
+----   ---------   ----   ---------   ----------  ------------   -------------
+810        N         N      FAST10    10 MB/s        Y             N
+810A       N         N      FAST10    10 MB/s        Y             Y
+815        Y         N      FAST10    10 MB/s        Y             N
+825        Y         Y      FAST10    20 MB/s        Y             N
+825A       Y         Y      FAST10    20 MB/s        Y             Y
+860        N         N      FAST20    20 MB/s        Y             Y
+875        Y         Y      FAST20    40 MB/s        Y             Y
+876        Y         Y      FAST20    40 MB/s        Y             Y
+895        Y         Y      FAST40    80 MB/s        Y             Y
+895A       Y         Y      FAST40    80 MB/s        Y             Y
+896        Y         Y      FAST40    80 MB/s        Y             Y
+897        Y         Y      FAST40    80 MB/s        Y             Y
+1510D      Y         Y      FAST40    80 MB/s        Y             Y
+1010       Y         Y      FAST80   160 MB/s        N             Y
+1010_66*   Y         Y      FAST80   160 MB/s        N             Y
+
+* Chip supports 33MHz and 66MHz PCI buses.
+
+
+Summary of other supported features:
+
+Module:                allow to load the driver
+Memory mapped I/O:     increases performance
+Profiling information: read operations from the proc SCSI file system
+Control commands:      write operations to the proc SCSI file system
+Debugging information: written to syslog (expert only)
+Scatter / gather
+Shared interrupt
+Boot setup commands
+Serial NVRAM:          Symbios and Tekram formats
+
+
+3. Advantages of the enhanced 896 driver
+
+3.1 Optimized SCSI SCRIPTS.
+
+The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions 
+named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register 
+to/from memory much faster that the MOVE MEMORY instruction that is supported 
+by the 53c7xx and 53c8xx family.
+The LOAD/STORE instructions support absolute and DSA relative addressing 
+modes.  The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead 
+of MOVE MEMORY instructions.
+
+3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
+
+The 896 and the 895A allows handling of the phase mismatch context from 
+SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor 
+until the C code has saved the context of the transfer).
+Implementing this without using LOAD/STORE instructions would be painfull 
+and I did'nt even want to try it.
+
+The 896 chip supports 64 bit PCI transactions and addressing, while the 
+895A supports 32 bit PCI transactions and 64 bit addressing.
+The SCRIPTS processor of these chips is not true 64 bit, but uses segment 
+registers for bit 32-63. Another interesting feature is that LOAD/STORE 
+instructions that address the on-chip RAM (8k) remain internal to the chip.
+
+Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not 
+support the following chips:
+- SYM53C810 revision < 0x10 (16)
+- SYM53C815 all revisions
+- SYM53C825 revision < 0x10 (16)
+
+4. Memory mapped I/O versus normal I/O
+
+Memory mapped I/O has less latency than normal I/O.  Since
+linux-1.3.x, memory mapped I/O is used rather than normal I/O.  Memory
+mapped I/O seems to work fine on most hardware configurations, but
+some poorly designed motherboards may break this feature.
+
+The configuration option CONFIG_SCSI_NCR53C8XX_IOMAPPED forces the
+driver to use normal I/O in all cases.
+
+
+5. Tagged command queueing
+
+Queuing more than 1 command at a time to a device allows it to perform 
+optimizations based on actual head positions and its mechanical 
+characteristics. This feature may also reduce average command latency.
+In order to really gain advantage of this feature, devices must have 
+a reasonnable cache size (No miracle is to be expected for a low-end 
+hard disk with 128 KB or less).
+Some kown SCSI devices do not properly support tagged command queuing.
+Generally, firmware revisions that fix this kind of problems are available 
+at respective vendor web/ftp sites.
+All I can say is that the hard disks I use on my machines behave well with 
+this driver with tagged command queuing enabled:
+
+- IBM S12 0662
+- Conner 1080S
+- Quantum Atlas I
+- Quantum Atlas II
+
+If your controller has NVRAM, you can configure this feature per target 
+from the user setup tool. The Tekram Setup program allows to tune the 
+maximum number of queued commands up to 32. The Symbios Setup only allows 
+to enable or disable this feature.
+
+The maximum number of simultaneous tagged commands queued to a device
+is currently set to 8 by default.  This value is suitable for most SCSI
+disks.  With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
+<= 10 ms), using a larger value may give better performances.
+
+The sym53c8xx driver supports up to 255 commands per device, and the 
+generic ncr53c8xx driver supports up to 64, but using more than 32 is 
+generally not worth-while, unless you are using a very large disk or disk 
+array. It is noticeable that most of recent hard disks seem not to accept 
+more than 64 simultaneous commands. So, using more than 64 queued commands 
+is probably just resource wasting.
+
+If your controller does not have NVRAM or if it is managed by the SDMS 
+BIOS/SETUP, you can configure tagged queueing feature and device queue 
+depths from the boot command-line. For example:
+
+  ncr53c8xx=tags:4/t2t3q15-t4q7/t1u0q32
+
+will set tagged commands queue depths as follow:
+
+- target 2  all luns  on controller 0 --> 15
+- target 3  all luns  on controller 0 --> 15
+- target 4  all luns  on controller 0 -->  7
+- target 1  lun 0     on controller 1 --> 32
+- all other target/lun                -->  4
+
+In some special conditions, some SCSI disk firmwares may return a
+QUEUE FULL status for a SCSI command. This behaviour is managed by the
+driver using the following heuristic:
+
+- Each time a QUEUE FULL status is returned, tagged queue depth is reduced 
+  to the actual number of disconnected commands. 
+
+- Every 1000 successfully completed SCSI commands, if allowed by the
+  current limit, the maximum number of queueable commands is incremented.
+
+Since QUEUE FULL status reception and handling is resource wasting, the 
+driver notifies by default this problem to user by indicating the actual 
+number of commands used and their status, as well as its decision on the 
+device queue depth change.
+The heuristic used by the driver in handling QUEUE FULL ensures that the 
+impact on performances is not too bad. You can get rid of the messages by 
+setting verbose level to zero, as follow:
+
+1st method: boot your system using 'ncr53c8xx=verb:0' option.
+2nd method: apply "setverbose 0" control command to the proc fs entry 
+            corresponding to your controller after boot-up.
+
+6. Parity checking
+
+The driver supports SCSI parity checking and PCI bus master parity
+checking.  These features must be enabled in order to ensure safe data
+transfers.  However, some flawed devices or mother boards will have
+problems with parity. You can disable either PCI parity or SCSI parity 
+checking by entering appropriate options from the boot command line.
+(See 10: Boot setup commands).
+
+7. Profiling information
+
+Profiling information is available through the proc SCSI file system.
+Since gathering profiling information may impact performances, this 
+feature is disabled by default and requires a compilation configuration 
+option to be set to Y.
+
+The device associated with a host has the following pathname:
+
+          /proc/scsi/ncr53c8xx/N     (N=0,1,2 ....)
+
+Generally, only 1 board is used on hardware configuration, and that device is:
+          /proc/scsi/ncr53c8xx/0
+
+However, if the driver has been made as module, the number of the
+hosts is incremented each time the driver is loaded.
+
+In order to display profiling information, just enter:
+
+         cat /proc/scsi/ncr53c8xx/0
+
+and you will get something like the following text:
+
+-------------------------------------------------------
+General information:
+  Chip NCR53C810, device id 0x1, revision id 0x2
+  IO port address 0x6000, IRQ number 10
+  Using memory mapped IO at virtual address 0x282c000
+  Synchronous transfer period 25, max commands per lun 4
+Profiling information:
+  num_trans    = 18014
+  num_kbytes   = 671314
+  num_disc     = 25763
+  num_break    = 1673
+  num_int      = 1685
+  num_fly      = 18038
+  ms_setup     = 4940
+  ms_data      = 369940
+  ms_disc      = 183090
+  ms_post      = 1320
+-------------------------------------------------------
+
+General information is easy to understand. The device ID and the
+revision ID identify the SCSI chip as follows:
+
+Chip    Device id     Revision Id
+----    ---------     -----------
+810       0x1            <  0x10
+810A      0x1            >= 0x10
+815       0x4
+825       0x3            <  0x10
+860       0x6
+825A      0x3            >= 0x10
+875       0xf
+895       0xc
+
+The profiling information is updated upon completion of SCSI commands.
+A data structure is allocated and zeroed when the host adapter is
+attached. So, if the driver is a module, the profile counters are
+cleared each time the driver is loaded.  The "clearprof" command
+allows you to clear these counters at any time.
+
+The following counters are available:
+
+("num" prefix means "number of",
+"ms" means milli-seconds)
+
+num_trans
+	Number of completed commands
+	Example above: 18014 completed commands
+
+num_kbytes
+	Number of kbytes transferred
+	Example above: 671 MB transferred
+
+num_disc
+	Number of SCSI disconnections
+	Example above: 25763 SCSI disconnections
+
+num_break
+	number of script interruptions (phase mismatch)
+	Example above: 1673 script interruptions
+
+num_int
+	Number of interrupts other than "on the fly"
+	Example above: 1685 interruptions not "on the fly"
+
+num_fly
+	Number of interrupts "on the fly"
+	Example above: 18038 interruptions "on the fly"
+
+ms_setup
+	Elapsed time for SCSI commands setups
+	Example above: 4.94 seconds
+
+ms_data
+	Elapsed time for data transfers
+	Example above: 369.94 seconds spent for data transfer
+
+ms_disc
+	Elapsed time for SCSI disconnections
+	Example above: 183.09 seconds spent disconnected
+
+ms_post
+	Elapsed time for command post processing
+	(time from SCSI status get to command completion call)
+	Example above: 1.32 seconds spent for post processing
+
+Due to the 1/100 second tick of the system clock, "ms_post" time may
+be wrong.
+
+In the example above, we got 18038 interrupts "on the fly" and only
+1673 script breaks generally due to disconnections inside a segment 
+of the scatter list.
+
+
+8. Control commands
+
+Control commands can be sent to the driver with write operations to
+the proc SCSI file system. The generic command syntax is the
+following:
+
+      echo "<verb> <parameters>" >/proc/scsi/ncr53c8xx/0
+      (assumes controller number is 0)
+
+Using "all" for "<target>" parameter with the commands below will
+apply to all targets of the SCSI chain (except the controller).
+
+Available commands:
+
+8.1 Set minimum synchronous period factor
+
+    setsync <target> <period factor>
+
+    target:    target number
+    period:    minimum synchronous period.
+               Maximum speed = 1000/(4*period factor) except for special
+               cases below.
+
+    Specify a period of 255, to force asynchronous transfer mode.
+
+      10 means 25 nano-seconds synchronous period
+      11 means 30 nano-seconds synchronous period
+      12 means 50 nano-seconds synchronous period
+
+8.2 Set wide size
+
+    setwide <target> <size>
+
+    target:    target number
+    size:      0=8 bits, 1=16bits
+
+8.3 Set maximum number of concurrent tagged commands
+ 
+    settags <target> <tags>
+
+    target:    target number
+    tags:      number of concurrent tagged commands
+               must not be greater than SCSI_NCR_MAX_TAGS (default: 8)
+
+8.4 Set order type for tagged command
+
+    setorder <order>
+
+    order:     3 possible values:
+               simple: use SIMPLE TAG for all operations (read and write)
+               ordered: use ORDERED TAG for all operations
+               default: use default tag type,
+                        SIMPLE  TAG for read  operations
+                        ORDERED TAG for write operations
+
+
+8.5 Set debug mode
+
+    setdebug <list of debug flags>
+
+    Available debug flags:
+        alloc:   print info about memory allocations (ccb, lcb)
+        queue:   print info about insertions into the command start queue
+        result:  print sense data on CHECK CONDITION status
+        scatter: print info about the scatter process
+        scripts: print info about the script binding process
+	tiny:    print minimal debugging information
+	timing:  print timing information of the NCR chip
+	nego:    print information about SCSI negotiations
+	phase:   print information on script interruptions
+
+    Use "setdebug" with no argument to reset debug flags.
+
+
+8.6 Clear profile counters
+
+    clearprof
+
+    The profile counters are automatically cleared when the amount of
+    data transferred reaches 1000 GB in order to avoid overflow.
+    The "clearprof" command allows you to clear these counters at any time.
+
+
+8.7 Set flag (no_disc)
+ 
+    setflag <target> <flag>
+
+    target:    target number
+
+    For the moment, only one flag is available:
+
+        no_disc:   not allow target to disconnect.
+
+    Do not specify any flag in order to reset the flag. For example:
+    - setflag 4
+      will reset no_disc flag for target 4, so will allow it disconnections.
+    - setflag all
+      will allow disconnection for all devices on the SCSI bus.
+
+
+8.8 Set verbose level
+
+    setverbose #level
+
+    The driver default verbose level is 1. This command allows to change 
+    th driver verbose level after boot-up.
+
+8.9 Reset all logical units of a target
+
+    resetdev <target>
+
+    target:    target number
+    The driver will try to send a BUS DEVICE RESET message to the target.
+    (Only supported by the SYM53C8XX driver and provided for test purpose)
+
+8.10 Abort all tasks of all logical units of a target
+
+    cleardev <target>
+
+    target:    target number
+    The driver will try to send a ABORT message to all the logical units 
+    of the target.
+    (Only supported by the SYM53C8XX driver and provided for test purpose)
+
+
+9. Configuration parameters
+
+If the firmware of all your devices is perfect enough, all the
+features supported by the driver can be enabled at start-up.  However,
+if only one has a flaw for some SCSI feature, you can disable the
+support by the driver of this feature at linux start-up and enable
+this feature after boot-up only for devices that support it safely.
+
+CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT  (default answer: n)
+    This option must be set for profiling information to be gathered 
+    and printed out through the proc file system. This features may 
+    impact performances.
+
+CONFIG_SCSI_NCR53C8XX_IOMAPPED       (default answer: n)
+    Answer "y" if you suspect your mother board to not allow memory mapped I/O.
+    May slow down performance a little.  This option is required by
+    Linux/PPC and is used no matter what you select here.  Linux/PPC
+    suffers no performance loss with this option since all IO is memory
+    mapped anyway.
+
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS    (default answer: 8)
+    Default tagged command queue depth.
+
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS         (default answer: 8)
+    This option allows you to specify the maximum number of tagged commands 
+    that can be queued to a device. The maximum supported value is 32.
+
+CONFIG_SCSI_NCR53C8XX_SYNC            (default answer: 5)
+    This option allows you to specify the frequency in MHz the driver 
+    will use at boot time for synchronous data transfer negotiations.
+    This frequency can be changed later with the "setsync" control command.
+    0 means "asynchronous data transfers".
+
+CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO (default answer: n)
+    Force synchronous negotiation for all SCSI-2 devices.
+    Some SCSI-2 devices do not report this feature in byte 7 of inquiry 
+    response but do support it properly (TAMARACK scanners for example).
+
+CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT   (default and only reasonnable answer: n)
+    If you suspect a device of yours does not properly support disconnections,
+    you can answer "y". Then, all SCSI devices will never disconnect the bus 
+    even while performing long SCSI operations.
+
+CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
+    Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 
+    bit as a flag indicating singled-ended/differential interface.
+    If all the boards of your system are genuine SYMBIOS boards or use
+    BIOS and drivers from SYMBIOS, you would want to enable this option.
+    This option must NOT be enabled if your system has at least one 53C8XX 
+    based scsi board with a vendor-specific BIOS.
+    For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers 
+    use a vendor-specific BIOS and are known to not use SYMBIOS compatible 
+    GPIO wiring. So, this option must not be enabled if your system has 
+    such a board installed.
+
+CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+    Enable support for reading the serial NVRAM data on Symbios and
+    some Symbios compatible cards, and Tekram DC390W/U/F cards. Useful for
+    systems with more than one Symbios compatible controller where at least
+    one has a serial NVRAM, or for a system with a mixture of Symbios and
+    Tekram cards. Enables setting the boot order of host adaptors
+    to something other than the default order or "reverse probe" order. 
+    Also enables Symbios and Tekram cards to be distinguished so
+    CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in a system with a
+    mixture of Symbios and Tekram cards so the Symbios cards can make use of
+    the full range of Symbios features, differential, led pin, without
+    causing problems for the Tekram card(s).
+
+10. Boot setup commands
+
+10.1 Syntax
+
+Setup commands can be passed to the driver either at boot time or as a 
+string variable using 'insmod'.
+
+A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the 
+driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects 
+an optionnal list of integers separated with comma followed by an optional 
+list of  comma-separated strings. Example of boot setup command under lilo 
+prompt:
+
+lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200
+
+- enable tagged commands, up to 4 tagged commands queued.
+- set synchronous negotiation speed to 10 Mega-transfers / second.
+- set DEBUG_NEGO flag.
+
+Since comma seems not to be allowed when defining a string variable using  
+'insmod', the driver also accepts <space> as option separator. 
+The following command will install driver module with the same options as 
+above.
+
+    insmod ncr53c8xx.o ncr53c8xx="tags:4 sync:10 debug:0x200"
+
+For the moment, the integer list of arguments is discarded by the driver. 
+It will be used in the future in order to allow a per controller setup.
+
+Each string argument must be specified as "keyword:value". Only lower-case 
+characters and digits are allowed.
+
+In a system that contains multiple 53C8xx adapters insmod will install the 
+specified driver on each adapter. To exclude a chip use the 'excl' keyword.
+
+The sequence of commands, 
+
+    insmod sym53c8xx sym53c8xx=excl:0x1400
+    insmod ncr53c8xx
+
+installs the sym53c8xx driver on all adapters except the one at IO port 
+address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO 
+port address 0x1400.
+
+
+10.2 Available arguments
+
+10.2.1  Master parity checking
+        mpar:y     enabled
+        mpar:n     disabled
+
+10.2.2  Scsi parity checking
+        spar:y     enabled
+        spar:n     disabled
+
+10.2.3  Scsi disconnections
+        disc:y     enabled
+        disc:n     disabled
+ 
+10.2.4  Special features
+   Only apply to 810A, 825A, 860, 875 and 895 controllers.
+   Have no effect with other ones.
+        specf:y    (or 1) enabled
+        specf:n    (or 0) disabled
+        specf:3           enabled except Memory Write And Invalidate
+   The default driver setup is 'specf:3'. As a consequence, option 'specf:y' 
+   must be specified in the boot setup command to enable Memory Write And 
+   Invalidate.
+
+10.2.5  Ultra SCSI support
+   Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers.
+   Have no effect with other ones.
+        ultra:n    All ultra speeds enabled
+        ultra:2    Ultra2 enabled
+        ultra:1    Ultra enabled
+        ultra:0    Ultra speeds disabled
+
+10.2.6  Default number of tagged commands
+        tags:0     (or tags:1 ) tagged command queuing disabled
+        tags:#tags (#tags  > 1) tagged command queuing enabled
+  #tags will be truncated to the max queued commands configuration parameter.
+  This option also allows to specify a command queue depth for each device 
+  that support tagged command queueing.
+  Example:
+      ncr53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
+               will set devices queue depth as follow:
+      - controller #0 target #2 and target #3                  -> 16 commands,
+      - controller #0 target #5                                -> 24 commands,
+      - controller #1 target #1 logical unit #2                -> 32 commands,
+      - all other logical units (all targets, all controllers) -> 10 commands.
+
+10.2.7  Default synchronous period factor
+        sync:255     disabled (asynchronous transfer mode)
+        sync:#factor
+  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
+  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
+  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
+  #factor < 50     Fast    SCSI-2
+
+  In all cases, the driver will use the minimum transfer period supported by 
+  controllers according to NCR53C8XX chip type.
+
+10.2.8  Negotiate synchronous with all devices
+        (force sync nego)
+        fsn:y      enabled
+        fsn:n      disabled
+
+10.2.9  Verbosity level
+        verb:0     minimal
+        verb:1     normal
+        verb:2     too much
+
+10.2.10 Debug mode
+        debug:0	 clear debug flags
+        debug:#x   set debug flags
+  #x is an integer value combining the following power-of-2 values:
+  DEBUG_ALLOC       0x1
+  DEBUG_PHASE       0x2
+  DEBUG_POLL        0x4
+  DEBUG_QUEUE       0x8
+  DEBUG_RESULT     0x10
+  DEBUG_SCATTER    0x20
+  DEBUG_SCRIPT     0x40
+  DEBUG_TINY       0x80
+  DEBUG_TIMING    0x100
+  DEBUG_NEGO      0x200
+  DEBUG_TAGS      0x400
+  DEBUG_FREEZE    0x800
+  DEBUG_RESTART  0x1000
+
+  You can play safely with DEBUG_NEGO. However, some of these flags may 
+  generate bunches of syslog messages. 
+
+10.2.11 Burst max
+        burst:0    burst disabled
+        burst:255  get burst length from initial IO register settings.
+        burst:#x   burst enabled (1<<#x burst transfers max)
+  #x is an integer value which is log base 2 of the burst transfers max.
+  The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7).
+  Other chips only support up to 16 (#x = 4).
+  This is a maximum value. The driver set the burst length according to chip 
+  and revision ids. By default the driver uses the maximum value supported 
+  by the chip.
+
+10.2.12 LED support
+        led:1      enable  LED support
+        led:0      disable LED support
+  Donnot enable LED support if your scsi board does not use SDMS BIOS.
+  (See 'Configuration parameters')
+
+10.2.13 Max wide
+        wide:1      wide scsi enabled
+        wide:0      wide scsi disabled
+  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
+  If you have connected a wide device with a 50 pins to 68 pins cable 
+  converter, any accepted wide negotiation will break further data transfers.
+  In such a case, using "wide:0" in the bootup command will be helpfull. 
+
+10.2.14 Differential mode
+        diff:0	never set up diff mode
+        diff:1	set up diff mode if BIOS set it
+        diff:2	always set up diff mode
+        diff:3	set diff mode if GPIO3 is not set
+
+10.2.15 IRQ mode
+        irqm:0     always open drain
+        irqm:1     same as initial settings (assumed BIOS settings)
+        irqm:2     always totem pole
+        irqm:0x10  driver will not use SA_SHIRQ flag when requesting irq
+        irqm:0x20  driver will not use SA_INTERRUPT flag when requesting irq
+
+    (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
+
+10.2.16 Reverse probe
+        revprob:n   probe chip ids from the PCI configuration in this order:
+                    810, 815, 820, 860, 875, 885, 895, 896
+        revprob:y   probe chip ids in the reverse order.
+
+10.2.17 Fix up PCI configuration space
+        pcifix:<option bits>
+
+    Available option bits:
+        0x0:   No attempt to fix PCI configuration space registers values.
+        0x1:   Set PCI cache-line size register if not set.
+        0x2:   Set write and invalidate bit in PCI command register.
+        0x4:   Increase if necessary PCI latency timer according to burst max.
+
+    Use 'pcifix:7' in order to allow the driver to fix up all PCI features.
+
+10.2.18 Serial NVRAM
+        nvram:n     do not look for serial NVRAM
+        nvram:y     test controllers for onboard serial NVRAM
+        (alternate binary form)
+        mvram=<bits options>
+        0x01   look for NVRAM  (equivalent to nvram=y)
+        0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
+        0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
+        0x08   ignore NVRAM "Scan at boot time" parameter for all devices
+        0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+10.2.19 Check SCSI BUS 
+        buschk:<option bits>
+
+    Available option bits:
+        0x0:   No check.
+        0x1:   Check and donnot attach the controller on error.  
+        0x2:   Check and just warn on error.
+        0x4:   Disable SCSI bus integrity checking.
+
+10.2.20 Exclude a host from being attached
+        excl=<io_address>
+
+    Prevent host at a given io address from being attached.
+    For example 'ncr53c8xx=excl:0xb400,excl:0xc000' indicate to the 
+    ncr53c8xx driver not to attach hosts at address 0xb400 and 0xc000.
+
+10.2.21 Suggest a default SCSI id for hosts
+        hostid:255	no id suggested.
+        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
+
+    If a host SCSI id is available from the NVRAM, the driver will ignore 
+    any value suggested as boot option. Otherwise, if a suggested value 
+    different from 255 has been supplied, it will use it. Otherwise, it will 
+    try to deduce the value previously set in the hardware and use value 
+    7 if the hardware value is zero.
+
+10.2.22 Enable use of IMMEDIATE ARBITRATION
+        (only supported by the sym53c8xx driver. See 10.7 for more details)
+        iarb:0    donnot use this feature.
+        iarb:#x   use this feature according to bit fields as follow:
+
+    bit 0 (1) : enable IARB each time the initiator has been reselected 
+                when it arbitrated for the SCSI BUS.
+    (#x >> 4) : maximum number of successive settings of IARB if the initiator 
+                win arbitration and it has other commands to send to a device.
+
+Boot fail safe
+    safe:y	load the following assumed fail safe initial setup
+
+  master parity			disabled		mpar:n
+  scsi parity			enabled			spar:y
+  disconnections		not allowed		disc:n
+  special features		disabled		specf:n
+  ultra scsi			disabled		ultra:n
+  force sync negotiation	disabled		fsn:n
+  reverse probe			disabled		revprob:n
+  PCI fix up                    disabled                pcifix:0
+  serial NVRAM                  enabled                 nvram:y
+  verbosity level		2			verb:2
+  tagged command queuing	disabled		tags:0
+  synchronous negotiation	disabled		sync:255
+  debug flags			none			debug:0
+  burst length			from BIOS settings	burst:255
+  LED support			disabled		led:0
+  wide support			disabled		wide:0
+  settle time			10 seconds		settle:10
+  differential support		from BIOS settings	diff:1
+  irq mode			from BIOS settings	irqm:1
+  SCSI BUS check		donnot attach on error	buschk:1
+  immediate arbitration		disabled		iarb:0
+
+10.3 Advised boot setup commands
+
+If the driver has been configured with default options, the equivalent 
+boot setup is:
+
+   ncr53c8xx=mpar:y,spar:y,disc:y,specf:3,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\
+             tags:0,sync:50,debug:0,burst:7,led:0,wide:1,settle:2,diff:0,irqm:0
+
+For an installation diskette or a safe but not fast system,
+boot setup can be:
+
+    ncr53c8xx=safe:y,mpar:y,disc:y
+    ncr53c8xx=safe:y,disc:y
+    ncr53c8xx=safe:y,mpar:y
+    ncr53c8xx=safe:y
+
+My personnal system works flawlessly with the following equivalent setup:
+
+   ncr53c8xx=mpar:y,spar:y,disc:y,specf:1,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\
+             tags:32,sync:12,debug:0,burst:7,led:1,wide:1,settle:2,diff:0,irqm:0
+
+The driver prints its actual setup when verbosity level is 2. You can try 
+"ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" 
+to your boot setup command in order to check the actual setup the driver is 
+using.
+
+10.4 PCI configuration fix-up boot option
+
+pcifix:<option bits>
+
+Available option bits:
+    0x1:     Set PCI cache-line size register if not set.
+    0x2:     Set write and invalidate bit in PCI command register.
+
+Use 'pcifix:3' in order to allow the driver to fix both PCI features.
+
+These options only apply to new SYMBIOS chips 810A, 825A, 860, 875 
+and 895 and are only supported for Pentium and 486 class processors.
+Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
+and PCI write and invalidate commands. These features require the 
+cache line size register to be properly set in the PCI configuration 
+space of the chips. On the other hand, chips will use PCI write and 
+invalidate commands only if the corresponding bit is set to 1 in the 
+PCI command register.
+
+Not all PCI bioses set the PCI cache line register and the PCI write and 
+invalidate bit in the PCI configuration space of 53C8XX chips.
+Optimized PCI accesses may be broken for some PCI/memory controllers or 
+make problems with some PCI boards.
+
+This fix-up worked flawlessly on my previous system.
+(MB Triton HX / 53C875 / 53C810A)
+I use these options at my own risks as you will do if you decide to 
+use them too.
+
+
+10.5 Serial NVRAM support boot option
+
+nvram:n     do not look for serial NVRAM
+nvram:y     test controllers for onboard serial NVRAM
+
+This option can also been entered as an hexadecimal value that allows 
+to control what information the driver will get from the NVRAM and what 
+information it will ignore.
+For details see '17. Serial NVRAM support'.
+
+When this option is enabled, the driver tries to detect all boards using 
+a Serial NVRAM. This memory is used to hold user set up parameters.
+
+The parameters the driver is able to get from the NVRAM depend on the 
+data format used, as follow:
+
+                                 Tekram format      Symbios format
+General and host parameters
+    Boot order                         N                   Y
+    Host SCSI ID                       Y                   Y
+    SCSI parity checking               Y                   Y
+    Verbose boot messages              N                   Y
+SCSI devices parameters
+    Synchronous transfer speed         Y                   Y
+    Wide 16 / Narrow                   Y                   Y
+    Tagged Command Queuing enabled     Y                   Y
+    Disconnections enabled             Y                   Y
+    Scan at boot time                  N                   Y
+
+In order to speed up the system boot, for each device configured without 
+the "scan at boot time" option, the driver forces an error on the 
+first TEST UNIT READY command received for this device.
+
+Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
+hard disks. In such a situation you cannot configure the NVRAM with 
+optimized parameters value.
+
+The 'nvram' boot option can be entered in hexadecimal form in order 
+to ignore some options configured in the NVRAM, as follow:
+
+mvram=<bits options>
+      0x01   look for NVRAM  (equivalent to nvram=y)
+      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
+      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
+      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
+      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+Option 0x80 is only supported by the sym53c8xx driver and is disabled by 
+default. Result is that, by default (option not set), the sym53c8xx driver 
+will not attach controllers set to OFF in the NVRAM.
+
+The ncr53c8xx always tries to attach all the controllers. Option 0x80 has 
+not been added to the ncr53c8xx driver, since it has been reported to 
+confuse users who use this driver since a long time. If you desire a 
+controller not to be attached by the ncr53c8xx driver at Linux boot, you 
+must use the 'excl' driver boot option.
+
+10.6 SCSI BUS checking boot option.
+
+When this option is set to a non-zero value, the driver checks SCSI lines 
+logic state, 100 micro-seconds after having asserted the SCSI RESET line.
+The driver just reads SCSI lines and checks all lines read FALSE except RESET.
+Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI 
+RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
+Unfortunately, the following common SCSI BUS problems are not detected:
+- Only 1 terminator installed.
+- Misplaced terminators.
+- Bad quality terminators.
+On the other hand, either bad cabling, broken devices, not conformant 
+devices, ... may cause a SCSI signal to be wrong when te driver reads it.
+
+10.7 IMMEDIATE ARBITRATION boot option
+
+This option is only supported by the SYM53C8XX driver (not by the NCR53C8XX).
+
+SYMBIOS 53C8XX chips are able to arbitrate for the SCSI BUS as soon as they 
+have detected an expected disconnection (BUS FREE PHASE). For this process 
+to be started, bit 1 of SCNTL1 IO register must be set when the chip is 
+connected to the SCSI BUS.
+
+When this feature has been enabled for the current connection, the chip has 
+every chance to win arbitration if only devices with lower priority are 
+competing for the SCSI BUS. By the way, when the chip is using SCSI id 7, 
+then it will for sure win the next SCSI BUS arbitration.
+
+Since, there is no way to know what devices are trying to arbitrate for the 
+BUS, using this feature can be extremally unfair. So, you are not advised 
+to enable it, or at most enable this feature for the case the chip lost 
+the previous arbitration (boot option 'iarb:1').
+
+This feature has the following advantages:
+
+a) Allow the initiator with ID 7 to win arbitration when it wants so.
+b) Overlap at least 4 micro-seconds of arbitration time with the execution 
+   of SCRIPTS that deal with the end of the current connection and that 
+   starts the next job.
+
+Hmmm... But (a) may just prevent other devices from reselecting the initiator, 
+and delay data transfers or status/completions, and (b) may just waste 
+SCSI BUS bandwidth if the SCRIPTS execution lasts more than 4 micro-seconds.
+
+The use of IARB needs the SCSI_NCR_IARB_SUPPORT option to have been defined 
+at compile time and the 'iarb' boot option to have been set to a non zero 
+value at boot time. It is not that useful for real work, but can be used 
+to stress SCSI devices or for some applications that can gain advantage of 
+it. By the way, if you experience badnesses like 'unexpected disconnections', 
+'bad reselections', etc... when using IARB on heavy IO load, you should not 
+be surprised, because force-feeding anything and blocking its arse at the 
+same time cannot work for a long time. :-))
+
+
+11. Some constants and flags of the ncr53c8xx.h header file
+
+Some of these are defined from the configuration parameters.  To
+change other "defines", you must edit the header file.  Do that only
+if you know what you are doing.
+
+SCSI_NCR_SETUP_SPECIAL_FEATURES	(default: defined)
+	If defined, the driver will enable some special features according  
+	to chip and revision id.
+        For 810A, 860, 825A, 875 and 895 scsi chips, this option enables 
+	support of features that reduce load of PCI bus and memory accesses 
+	during  scsi transfer processing: burst op-code fetch, read multiple, 
+        read line, prefetch, cache line, write and invalidate, 
+        burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only).
+	Can be changed by the following boot setup command:
+		ncr53c8xx=specf:n
+
+SCSI_NCR_IOMAPPED		(default: not defined)
+	If defined, normal I/O is forced.
+
+SCSI_NCR_SHARE_IRQ		(default: defined)
+	If defined, request shared IRQ.
+	
+SCSI_NCR_MAX_TAGS		(default: 8)
+	Maximum number of simultaneous tagged commands to a device.
+	Can be changed by "settags <target> <maxtags>"
+
+SCSI_NCR_SETUP_DEFAULT_SYNC     (default: 50)
+	Transfer period factor the driver will use at boot time for synchronous 
+	negotiation. 0 means asynchronous.
+	Can be changed by "setsync <target> <period factor>"
+
+SCSI_NCR_SETUP_DEFAULT_TAGS     (default: 8)
+	Default number of simultaneous tagged commands to a device.
+	< 1 means tagged command queuing disabled at start-up.
+
+SCSI_NCR_ALWAYS_SIMPLE_TAG	(default: defined)
+	Use SIMPLE TAG for read and write commands.
+	Can be changed by "setorder <ordered|simple|default>"
+
+SCSI_NCR_SETUP_DISCONNECTION	(default: defined)
+	If defined, targets are allowed to disconnect.
+
+SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(default: not defined)
+	If defined, synchronous negotiation is tried for all SCSI-2 devices.
+	Can be changed by "setsync <target> <period>"
+
+SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
+	If defined, master parity checking is enabled.
+
+SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
+	If defined, SCSI parity checking is enabled.
+
+SCSI_NCR_PROFILE_SUPPORT	(default: not defined)
+	If defined, profiling information is gathered.
+
+SCSI_NCR_MAX_SCATTER		(default: 128)
+	Scatter list size of the driver ccb.
+
+SCSI_NCR_MAX_TARGET		(default: 16)
+	Max number of targets per host.
+
+SCSI_NCR_MAX_HOST		(default: 2)
+	Max number of host controllers.
+
+SCSI_NCR_SETTLE_TIME		(default: 2)
+	Number of seconds the driver will wait after reset.
+
+SCSI_NCR_TIMEOUT_ALERT		(default: 3)
+	If a pending command will time out after this amount of seconds,
+	an ordered tag is used for the next command.
+	Avoids timeouts for unordered tagged commands.
+
+SCSI_NCR_CAN_QUEUE		(default: 7*SCSI_NCR_MAX_TAGS)
+	Max number of commands that can be queued to a host.
+
+SCSI_NCR_CMD_PER_LUN		(default: SCSI_NCR_MAX_TAGS)
+	Max number of commands queued to a host for a device.
+
+SCSI_NCR_SG_TABLESIZE		(default: SCSI_NCR_MAX_SCATTER-1)
+	Max size of the Linux scatter/gather list.
+
+SCSI_NCR_MAX_LUN	(default: 8)
+	Max number of LUNs per target.
+
+
+12. Installation
+
+This driver is part of the linux kernel distribution.
+Driver files are located in the sub-directory "drivers/scsi" of the 
+kernel source tree.
+
+Driver files:
+
+	README.ncr53c8xx	: this file
+	ChangeLog.ncr53c8xx	: change log
+	ncr53c8xx.h		: definitions
+	ncr53c8xx.c		: the driver code
+
+New driver versions are made available separately in order to allow testing 
+changes and new features prior to including them into the linux kernel 
+distribution. The following URL provides informations on latest avalaible 
+patches: 
+
+      ftp://ftp.tux.org/pub/people/gerard-roudier/README
+
+
+13. Architecture dependent features.
+
+<Not yet written>
+
+
+14. Known problems
+
+14.1 Tagged commands with Iomega Jaz device
+
+I have not tried this device, however it has been reported to me the
+following: This device is capable of Tagged command queuing. However
+while spinning up, it rejects Tagged commands. This behaviour is
+conforms to 6.8.2 of SCSI-2 specifications. The current behaviour of
+the driver in that situation is not satisfying. So do not enable
+Tagged command queuing for devices that are able to spin down.  The
+other problem that may appear is timeouts. The only way to avoid
+timeouts seems to edit linux/drivers/scsi/sd.c and to increase the
+current timeout values.
+
+14.2 Device names change when another controller is added.
+
+When you add a new NCR53C8XX chip based controller to a system that already 
+has one or more controllers of this family, it may happen that the order 
+the driver registers them to the kernel causes problems due to device 
+name changes.
+When at least one controller uses NvRAM, SDMS BIOS version 4 allows you to 
+define the order the BIOS will scan the scsi boards. The driver attaches 
+controllers according to BIOS information if NvRAM detect option is set.
+
+If your controllers do not have NvRAM, you can:
+
+- Ask the driver to probe chip ids in reverse order from the boot command
+  line: ncr53c8xx=revprob:y
+- Make appropriate changes in the fstab.
+- Use the 'scsidev' tool from Eric Youngdale.
+
+14.3 Using only 8 bit devices with a WIDE SCSI controller.
+
+When only 8 bit NARROW devices are connected to a 16 bit WIDE SCSI controller, 
+you must ensure that lines of the wide part of the SCSI BUS are pulled-up.
+This can be achieved by ENABLING the WIDE TERMINATOR portion of the SCSI 
+controller card.
+The TYAN 1365 documentation revision 1.2 is not correct about such settings.
+(page 10, figure 3.3).
+
+14.4 Possible data corruption during a Memory Write and Invalidate
+
+This problem is described in SYMBIOS DEL 397, Part Number 69-039241, ITEM 4.
+
+In some complex situations, 53C875 chips revision <= 3 may start a PCI 
+Write and Invalidate Command at a not cache-line-aligned 4 DWORDS boundary.
+This is only possible when Cache Line Size is 8 DWORDS or greater.
+Pentium systems use a 8 DWORDS cache line size and so are concerned by 
+this chip bug, unlike i486 systems that use a 4 DWORDS cache line size.
+
+When this situation occurs, the chip may complete the Write and Invalidate 
+command after having only filled part of the last cache line involved in 
+the transfer, leaving to data corruption the remainder of this cache line.
+
+Not using Write And Invalidate obviously gets rid of this chip bug, and so 
+it is now the default setting of the driver.
+However, for people like me who want to enable this feature, I have added 
+part of a work-around suggested by SYMBIOS. This work-around resets the 
+addressing logic when the DATA IN phase is entered and so prevents the bug 
+from being triggered for the first SCSI MOVE of the phase. This work-around 
+should be enough according to the following:
+
+The only driver internal data structure that is greater than 8 DWORDS  and 
+that is moved by the SCRIPTS processor is the 'CCB header' that contains 
+the context of the SCSI transfer. This data structure is aligned on 8 DWORDS 
+boundary (Pentium Cache Line Size), and so is immune to this chip bug, at 
+least on Pentium systems.
+But the conditions of this bug can be met when a SCSI read command is 
+performed using a buffer that is 4 DWORDS but not cache-line aligned.
+This cannot happen under Linux when scatter/gather lists are used since 
+they only refer to system buffers that are well aligned. So, a work around 
+may only be needed under Linux when a scatter/gather list is not used and 
+when the SCSI DATA IN phase is reentered after a phase mismatch.
+
+14.5 IRQ sharing problems
+
+When an IRQ is shared by devices that are handled by different drivers, it 
+may happen that one driver complains about the request of the IRQ having 
+failed. Inder Linux-2.0, this may be due to one driver having requested the 
+IRQ using the SA_INTERRUPT flag but some other having requested the same IRQ 
+without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by 
+one driver not having requested the IRQ with the SA_SHIRQ flag.
+
+By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the 
+SA_INTERRUPT and the SA_SHIRQ flag under Linux-2.0 and with only the SA_SHIRQ 
+flag under Linux-2.2.
+
+Under Linux-2.0, you can disable use of SA_INTERRUPT flag from the boot 
+command line by using the following option:
+
+     ncr53c8xx=irqm:0x20   (for the generic ncr53c8xx driver)
+     sym53c8xx=irqm:0x20   (for the sym53c8xx driver)
+
+If this does not fix the problem, then you may want to check how all other 
+drivers are requesting the IRQ and report the problem. Note that if at least 
+a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ), 
+then the request of the IRQ obviously will not succeed for all the drivers.
+
+15. SCSI problem troubleshooting
+
+15.1 Problem tracking
+
+Most SCSI problems are due to a non conformant SCSI bus or to buggy
+devices.  If infortunately you have SCSI problems, you can check the
+following things:
+
+- SCSI bus cables
+- terminations at both end of the SCSI chain
+- linux syslog messages (some of them may help you)
+
+If you donnot find the source of problems, you can configure the
+driver with no features enabled.
+
+- only asynchronous data transfers
+- tagged commands disabled
+- disconnections not allowed
+
+Now, if your SCSI bus is ok, your system have every chance to work
+with this safe configuration but performances will not be optimal.
+
+If it still fails, then you can send your problem description to
+appropriate mailing lists or news-groups.  Send me a copy in order to
+be sure I will receive it.  Obviously, a bug in the driver code is
+possible.
+
+     My email address: Gerard Roudier <groudier@free.fr>
+
+Allowing disconnections is important if you use several devices on
+your SCSI bus but often causes problems with buggy devices.
+Synchronous data transfers increases throughput of fast devices like
+hard disks.  Good SCSI hard disks with a large cache gain advantage of
+tagged commands queuing.
+
+Try to enable one feature at a time with control commands.  For example:
+
+- echo "setsync all 25" >/proc/scsi/ncr53c8xx/0
+  Will enable fast synchronous data transfer negotiation for all targets.
+
+- echo "setflag 3" >/proc/scsi/ncr53c8xx/0
+  Will reset flags (no_disc) for target 3, and so will allow it to disconnect 
+  the SCSI Bus.
+
+- echo "settags 3 8" >/proc/scsi/ncr53c8xx/0
+  Will enable tagged command queuing for target 3 if that device supports it.
+
+Once you have found the device and the feature that cause problems, just 
+disable that feature for that device.
+
+15.2 Understanding hardware error reports
+
+When the driver detects an unexpected error condition, it may display a 
+message of the following pattern.
+
+sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000).
+sym53c876-0: script cmd = 19000000
+sym53c876-0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.
+
+Some fields in such a message may help you understand the cause of the 
+problem, as follows:
+
+sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000).
+............A.........B.C....D.E..F....G.H.......I.....J...K.......
+
+Field A : target number.
+  SCSI ID of the device the controller was talking with at the moment the 
+  error occurs.
+
+Field B : DSTAT io register (DMA STATUS)
+  Bit 0x40 : MDPE Master Data Parity Error
+             Data parity error detected on the PCI BUS.
+  Bit 0x20 : BF   Bus Fault
+             PCI bus fault condition detected
+  Bit 0x01 : IID  Illegal Instruction Detected
+             Set by the chip when it detects an Illegal Instruction format 
+             on some condition that makes an instruction illegal.
+  Bit 0x80 : DFE Dma Fifo Empty
+             Pure status bit that does not indicate an error.
+  If the reported DSTAT value contains a combination of MDPE (0x40), 
+  BF (0x20), then the cause may be likely due to a PCI BUS problem.
+
+Field C : SIST io register (SCSI Interrupt Status)
+  Bit 0x08 : SGE  SCSI GROSS ERROR
+             Indicates that the chip detected a severe error condition 
+             on the SCSI BUS that prevents the SCSI protocol from functionning
+             properly.
+  Bit 0x04 : UDC  Undexpected Disconnection
+             Indicates that the device released the SCSI BUS when the chip 
+             was not expecting this to happen. A device may behave so to 
+             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occurred.
+  Bit 0x02 : RST  SCSI BUS Reset
+             Generally SCSI targets donnot reset the SCSI BUS, although any 
+             device on the BUS can reset it at any time.
+  Bit 0x01 : PAR  Parity
+             SCSI parity error detected.
+  On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and 
+  PAR (0x01) may be detected by the chip. If your SCSI system sometimes 
+  encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI 
+  BUS problem is likely the cause of these errors.
+
+For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file 
+that contains some minimal comments on IO register bits.
+Field D : SOCL  Scsi Output Control Latch
+          This register reflects the state of the SCSI control lines the 
+          chip want to drive or compare against.
+Field E : SBCL  Scsi Bus Control Lines
+          Actual value of control lines on the SCSI BUS.
+Field F : SBDL  Scsi Bus Data Lines
+          Actual value of data lines on the SCSI BUS.
+Field G : SXFER  SCSI Transfer
+          Contains the setting of the Synchronous Period for output and 
+          the current Synchronous offset (offset 0 means asynchronous).
+Field H : SCNTL3 Scsi Control Register 3
+          Contains the setting of timing values for both asynchronous and 
+          synchronous data transfers. 
+
+Understanding Fields I, J, K and dumps requires to have good knowledge of 
+SCSI standards, chip cores functionnals and internal driver data structures.
+You are not required to decode and understand them, unless you want to help 
+maintain the driver code.
+
+16. Synchonous transfer negotiation tables
+
+Tables below have been created by calling the routine the driver uses
+for synchronisation negotiation timing calculation and chip setting.
+The first table corresponds to Ultra chips 53875 and 53C860 with 80 MHz 
+clock and 5 clock divisors.
+The second one has been calculated by setting the scsi clock to 40 Mhz 
+and using 4 clock divisors and so applies to all NCR53C8XX chips in fast 
+SCSI-2 mode.
+
+Periods are in nano-seconds and speeds are in Mega-transfers per second.
+1 Mega-transfers/second means 1 MB/s with 8 bits SCSI and 2 MB/s with 
+Wide16 SCSI.
+
+16.1 Synchronous timings for 53C895, 53C875 and 53C860 SCSI controllers
+
+ ----------------------------------------------
+ Negotiated                     NCR settings
+ Factor   Period   Speed        Period   Speed
+ ------   ------   ------       ------   ------
+ 10       25       40.000       25       40.000   (53C895 only)
+ 11       30.2     33.112       31.25    32.000   (53C895 only)
+ 12       50       20.000       50       20.000
+ 13       52       19.230       62       16.000
+ 14       56       17.857       62       16.000
+ 15       60       16.666       62       16.000
+ 16       64       15.625       75       13.333
+ 17       68       14.705       75       13.333
+ 18       72       13.888       75       13.333
+ 19       76       13.157       87       11.428
+ 20       80       12.500       87       11.428
+ 21       84       11.904       87       11.428
+ 22       88       11.363       93       10.666
+ 23       92       10.869       93       10.666
+ 24       96       10.416      100       10.000
+ 25      100       10.000      100       10.000
+ 26      104        9.615      112        8.888
+ 27      108        9.259      112        8.888
+ 28      112        8.928      112        8.888
+ 29      116        8.620      125        8.000
+ 30      120        8.333      125        8.000
+ 31      124        8.064      125        8.000
+ 32      128        7.812      131        7.619
+ 33      132        7.575      150        6.666
+ 34      136        7.352      150        6.666
+ 35      140        7.142      150        6.666
+ 36      144        6.944      150        6.666
+ 37      148        6.756      150        6.666
+ 38      152        6.578      175        5.714
+ 39      156        6.410      175        5.714
+ 40      160        6.250      175        5.714
+ 41      164        6.097      175        5.714
+ 42      168        5.952      175        5.714
+ 43      172        5.813      175        5.714
+ 44      176        5.681      187        5.333
+ 45      180        5.555      187        5.333
+ 46      184        5.434      187        5.333
+ 47      188        5.319      200        5.000
+ 48      192        5.208      200        5.000
+ 49      196        5.102      200        5.000
+
+
+16.2 Synchronous timings for fast SCSI-2 53C8XX controllers
+
+ ----------------------------------------------
+ Negotiated                     NCR settings
+ Factor   Period   Speed        Period   Speed
+ ------   ------   ------       ------   ------
+ 25      100       10.000      100       10.000
+ 26      104        9.615      125        8.000
+ 27      108        9.259      125        8.000
+ 28      112        8.928      125        8.000
+ 29      116        8.620      125        8.000
+ 30      120        8.333      125        8.000
+ 31      124        8.064      125        8.000
+ 32      128        7.812      131        7.619
+ 33      132        7.575      150        6.666
+ 34      136        7.352      150        6.666
+ 35      140        7.142      150        6.666
+ 36      144        6.944      150        6.666
+ 37      148        6.756      150        6.666
+ 38      152        6.578      175        5.714
+ 39      156        6.410      175        5.714
+ 40      160        6.250      175        5.714
+ 41      164        6.097      175        5.714
+ 42      168        5.952      175        5.714
+ 43      172        5.813      175        5.714
+ 44      176        5.681      187        5.333
+ 45      180        5.555      187        5.333
+ 46      184        5.434      187        5.333
+ 47      188        5.319      200        5.000
+ 48      192        5.208      200        5.000
+ 49      196        5.102      200        5.000
+
+
+17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk)
+
+17.1 Features
+
+Enabling serial NVRAM support enables detection of the serial NVRAM included
+on Symbios and some Symbios compatible host adaptors, and Tekram boards. The 
+serial NVRAM is used by Symbios and Tekram to hold set up parameters for the 
+host adaptor and it's attached drives.
+
+The Symbios NVRAM also holds data on the boot order of host adaptors in a
+system with more than one host adaptor. This enables the order of scanning
+the cards for drives to be changed from the default used during host adaptor
+detection.
+
+This can be done to a limited extent at the moment using "reverse probe" but
+this only changes the order of detection of different types of cards. The
+NVRAM boot order settings can do this as well as change the order the same
+types of cards are scanned in, something "reverse probe" cannot do.
+
+Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
+and this is used to distinguish between Symbios compatible and Tekram host 
+adaptors. This is used to disable the Symbios compatible "diff" setting
+incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT 
+configuration parameter is set enabling both Symbios and Tekram boards to be 
+used together with the Symbios cards using all their features, including
+"diff" support. ("led pin" support for Symbios compatible cards can remain
+enabled when using Tekram cards. It does nothing useful for Tekram host
+adaptors but does not cause problems either.)
+
+
+17.2 Symbios NVRAM layout
+
+typical data at NVRAM address 0x100 (53c810a NVRAM)
+-----------------------------------------------------------
+00 00
+64 01
+8e 0b
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62 
+04 00 03 00 00 10 00 58 00 00 01 00 00 63 
+04 00 01 00 00 10 00 48 00 00 01 00 00 61 
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+fe fe
+00 00
+00 00
+-----------------------------------------------------------
+NVRAM layout details
+
+NVRAM Address 0x000-0x0ff not used
+              0x100-0x26f initialised data
+              0x270-0x7ff not used
+
+general layout
+
+        header  -   6 bytes,
+        data    - 356 bytes (checksum is byte sum of this data)
+        trailer -   6 bytes
+                  ---
+        total     368 bytes
+
+data area layout
+
+        controller set up  -  20 bytes
+        boot configuration -  56 bytes (4x14 bytes)
+        device set up      - 128 bytes (16x8 bytes)
+        unused (spare?)    - 152 bytes (19x8 bytes)
+                             ---
+        total                356 bytes
+
+-----------------------------------------------------------
+header
+
+00 00   - ?? start marker
+64 01   - byte count (lsb/msb excludes header/trailer)
+8e 0b   - checksum (lsb/msb excludes header/trailer)
+-----------------------------------------------------------
+controller set up
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
+                   |     |           |     |
+                   |     |           |      -- host ID
+                   |     |           |
+                   |     |            --Removable Media Support
+                   |     |               0x00 = none
+                   |     |               0x01 = Bootable Device
+                   |     |               0x02 = All with Media
+                   |     |
+                   |      --flag bits 2
+                   |        0x00000001= scan order hi->low
+                   |            (default 0x00 - scan low->hi)
+                    --flag bits 1
+                       0x00000001 scam enable
+                       0x00000010 parity enable
+                       0x00000100 verbose boot msgs
+
+remaining bytes unknown - they do not appear to change in my
+current set up for any of the controllers.
+
+default set up is identical for 53c810a and 53c875 NVRAM
+(Removable Media added Symbios BIOS version 4.09)
+-----------------------------------------------------------
+boot configuration
+
+boot order set by order of the devices in this table
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
+04 00 03 00 00 10 00 58 00 00 01 00 00 63    2nd controller
+04 00 01 00 00 10 00 48 00 00 01 00 00 61    3rd controller
+00 00 00 00 00 00 00 00 00 00 00 00 00 00    4th controller
+       |  |  |  |     |        |     |  |
+       |  |  |  |     |        |      ---- PCI io port adr
+       |  |  |  |     |         --0x01 init/scan at boot time
+       |  |  |  |      --PCI device/function number (0xdddddfff)
+       |  |   ----- ?? PCI vendor ID (lsb/msb)
+        ----PCI device ID (lsb/msb)
+
+?? use of this data is a guess but seems reasonable
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+device set up (up to 16 devices - includes controller)
+
+0f 00 08 08 64 00 0a 00 - id 0
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 - id 15
+ |     |  |  |     |  |
+ |     |  |  |      ----timeout (lsb/msb)
+ |     |  |   --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
+ |     |  |                  (0x30 20 Mtrans/sec- fast 20)
+ |     |  |                  (0x64 10 Mtrans/sec- fast )
+ |     |  |                  (0xc8  5 Mtrans/sec)
+ |     |  |                  (0x00  asynchronous)
+ |     |   -- ?? max sync offset (0x08 in NVRAM on 53c810a) 
+ |     |                         (0x10 in NVRAM on 53c875)
+ |      --device bus width (0x08 narrow)
+ |                         (0x10 16 bit wide)
+  --flag bits
+    0x00000001 - disconnect enabled
+    0x00000010 - scan at boot time
+    0x00000100 - scan luns
+    0x00001000 - queue tags enabled
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+?? use of this data is a guess but seems reasonable 
+(but it could be max bus width)
+
+default set up for 53c810a NVRAM
+default set up for 53c875 NVRAM - bus width     - 0x10
+                                - sync offset ? - 0x10
+                                - sync period   - 0x30
+-----------------------------------------------------------
+?? spare device space (32 bit bus ??)
+
+00 00 00 00 00 00 00 00  (19x8bytes)
+.
+.
+00 00 00 00 00 00 00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+trailer
+
+fe fe   - ? end marker ?
+00 00
+00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+
+
+
+17.3 Tekram NVRAM layout
+
+nvram 64x16 (1024 bit)
+
+Drive settings
+
+Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
+              (addr 0x0yyyy1 = 0x0000)
+
+    x x x x  x x x x  x x x x  x x x x
+               | | |      | |  | | | |
+               | | |      | |  | | |  ----- parity check   0 - off
+               | | |      | |  | | |                       1 - on
+               | | |      | |  | | |
+               | | |      | |  | |  ------- sync neg       0 - off
+               | | |      | |  | |                         1 - on
+               | | |      | |  | |
+               | | |      | |  |  --------- disconnect     0 - off
+               | | |      | |  |                           1 - on
+               | | |      | |  |
+               | | |      | |   ----------- start cmd      0 - off
+               | | |      | |                              1 - on
+               | | |      | |
+               | | |      |  -------------- tagged cmds    0 - off
+               | | |      |                                1 - on
+               | | |      | 
+               | | |       ---------------- wide neg       0 - off
+               | | |                                       1 - on
+               | | |
+                --------------------------- sync rate      0 - 10.0 Mtrans/sec
+                                                           1 -  8.0
+                                                           2 -  6.6
+                                                           3 -  5.7
+                                                           4 -  5.0
+                                                           5 -  4.0
+                                                           6 -  3.0
+                                                           7 -  2.0
+                                                           7 -  2.0
+                                                           8 - 20.0
+                                                           9 - 16.7
+                                                           a - 13.9
+                                                           b - 11.9
+
+Global settings
+
+Host flags 0 (addr 0x100000, 32) 
+
+    x x x x  x x x x  x x x x  x x x x
+    | | | |  | | | |           | | | |
+    | | | |  | | | |            ----------- host ID    0x00 - 0x0f
+    | | | |  | | | |
+    | | | |  | | |  ----------------------- support for    0 - off
+    | | | |  | | |                          > 2 drives     1 - on
+    | | | |  | | | 
+    | | | |  | |  ------------------------- support drives 0 - off
+    | | | |  | |                            > 1Gbytes      1 - on
+    | | | |  | |
+    | | | |  |  --------------------------- bus reset on   0 - off
+    | | | |  |                                power on     1 - on
+    | | | |  |
+    | | | |   ----------------------------- active neg     0 - off
+    | | | |                                                1 - on
+    | | | |
+    | | |  -------------------------------- imm seek       0 - off
+    | | |                                                  1 - on
+    | | |
+    | |  ---------------------------------- scan luns      0 - off
+    | |                                                    1 - on
+    | |
+     -------------------------------------- removable      0 - disable
+                                            as BIOS dev    1 - boot device
+                                                           2 - all
+
+Host flags 1 (addr 0x100001, 33)
+
+    x x x x  x x x x  x x x x  x x x x
+               | | |             | | | 
+               | | |              --------- boot delay     0 -   3 sec
+               | | |                                       1 -   5
+               | | |                                       2 -  10
+               | | |                                       3 -  20
+               | | |                                       4 -  30
+               | | |                                       5 -  60
+               | | |                                       6 - 120
+               | | |
+                --------------------------- max tag cmds   0 -  2
+                                                           1 -  4
+                                                           2 -  8
+                                                           3 - 16
+                                                           4 - 32
+
+Host flags 2 (addr 0x100010, 34)
+
+    x x x x  x x x x  x x x x  x x x x
+                                     |
+                                      ----- F2/F6 enable   0 - off ???
+                                                           1 - on  ???
+
+checksum (addr 0x111111)
+
+checksum = 0x1234 - (sum addr 0-63)
+
+----------------------------------------------------------------------------
+
+default nvram data:
+
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 
+
+0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc
+
+
+18. Support for Big Endian
+
+The PCI local bus has been primarily designed for x86 architecture.
+As a consequence, PCI devices generally expect DWORDS using little endian 
+byte ordering.
+
+18.1 Big Endian CPU
+
+In order to support NCR chips on a Big Endian architecture the driver has to 
+perform byte reordering each time it is needed. This feature has been 
+added to the driver by Cort <cort@cs.nmt.edu> and is available in driver 
+version 2.5 and later ones. For the moment Big Endian support has only 
+been tested on Linux/PPC (PowerPC).
+
+18.2 NCR chip in Big Endian mode of operations
+
+It can be read in SYMBIOS documentation that some chips support a special 
+Big Endian mode, on paper: 53C815, 53C825A, 53C875, 53C875N, 53C895.
+This mode of operations is not software-selectable, but needs pin named 
+BigLit to be pulled-up. Using this mode, most of byte reorderings should 
+be avoided when the driver is running on a Big Endian CPU.
+Driver version 2.5 is also, in theory, ready for this feature.
+
+===============================================================================
+End of NCR53C8XX driver README file
diff -Nru a/Documentation/scsi/osst.txt b/Documentation/scsi/osst.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/osst.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,219 @@
+README file for the osst driver
+===============================
+(w) Kurt Garloff <garloff@suse.de> 12/2000
+
+This file describes the osst driver as of version 0.8.x/0.9.x, the released
+version of the osst driver.
+It is intended to help advanced users to understand the role of osst and to
+get them started using (and maybe debugging) it.
+It won't address issues like "How do I compile a kernel?" or "How do I load
+a module?", as these are too basic.
+Once the OnStream got merged into the official kernel, the distro makers
+will provide the OnStream support for those who are not familiar with
+hacking their kernels.
+
+
+Purpose
+-------
+The osst driver was developed, because the standard SCSI tape driver in
+Linux, st, does not support the OnStream SC-x0 SCSI tape. The st is not to
+blame for that, as the OnStream tape drives do not support the standard SCSI
+command set for Serial Access Storage Devices (SASDs), which basically
+corresponds to the QIC-157 spec.
+Nevertheless, the OnStream tapes are nice pieces of hardware and therefore
+the osst driver has been written to make these tape devs supported by Linux.
+The driver is free software. It's released under the GNU GPL and planned to
+be integrated into the mainstream kernel.
+
+
+Implementation
+--------------
+The osst is a new high-level SCSI driver, just like st, sr, sd and sg. It
+can be compiled into the kernel or loaded as a module.
+As it represents a new device, it got assigned a new device node: /dev/osstX
+are character devices with major no 206 and minor numbers like the /dev/stX
+devices. If those are not present, you may create them by calling
+Makedevs.sh as root (see below).
+The driver started being a copy of st and as such, the osst devices'
+behavior looks very much the same as st to the userspace applications.
+
+
+History
+-------
+In the first place, osst shared it's identity very much with st. That meant
+that it used the same kernel structures and the same device node as st.
+So you could only have either of them being present in the kernel. This has
+been fixed by registering an own device, now.
+st and osst can coexist, each only accessing the devices it can support by
+themselves.
+
+
+Installation
+------------
+osst got integrated into the linux kernel. Select it during kernel
+configuration as module or compile statically into the kernel.
+Compile your kernel and install the modules.
+
+Now, your osst driver is inside the kernel or available as a module,
+depending on your choice during kernel config. You may still need to create
+the device nodes by calling the Makedevs.sh script (see below) manually,
+unless you use a devfs kernel, where this won't be needed.
+
+To load your module, you may use the command 
+modprobe osst
+as root. dmesg should show you, whether your OnStream tapes have been
+recognized.
+
+If you want to have the module autoloaded on access to /dev/osst, you may
+add something like
+alias char-major-206 osst
+to your /etc/modules.conf (old name: conf.modules).
+
+You may find it convenient to create a symbolic link 
+ln -s nosst0 /dev/tape
+to make programs assuming a default name of /dev/tape more convenient to
+use.
+
+The device nodes for osst have to be created. Use the Makedevs.sh script
+attached to this file.
+
+
+Using it
+--------
+You may use the OnStream tape driver with your standard backup software,
+which may be tar, cpio, amanda, arkeia, BRU, Lone Tar, ...
+by specifying /dev/(n)osst0 as the tape device to use or using the above
+symlink trick. The IOCTLs to control tape operation are also mostly
+supported and you may try the mt (or mt_st) program to jump between
+filemarks, eject the tape, ...
+
+There's one limitation: You need to use a block size of 32kB.
+
+(This limitation is worked on and will be fixed in version 0.8.8 of
+ this driver.)
+
+If you just want to get started with standard software, here is an example
+for creating and restoring a full backup:
+# Backup
+tar cvf - / --exclude /proc | buffer -s 32k -m 24M -B -t -o /dev/nosst0
+# Restore
+buffer -s 32k -m 8M -B -t -i /dev/osst0 | tar xvf - -C /
+
+The buffer command has been used to buffer the data before it goes to the
+tape (or the file system) in order to smooth out the data stream and prevent
+the tape from needing to stop and rewind. The OnStream does have an internal
+buffer and a variable speed which help this, but especially on writing, the
+buffering still proves useful in most cases. It also pads the data to
+guarantees the block size of 32k. (Otherwise you may pass the -b64 option to
+tar.)
+Expect something like 1.8MB/s for the SC-x0 drives and 0.9MB/s for the DI-30.
+The USB drive will give you about 0.7MB/s.
+On a fast machine, you may profit from software data compression (z flag for
+tar).
+
+
+USB and IDE
+-----------
+Via the SCSI emulation layers usb-storage and ide-scsi, you can also use the
+osst driver to drive the USB-30 and the DI-30 drives. (Unfortunately, there
+is no such layer for the parallel port, otherwise the DP-30 would work as
+well.) For the USB support, you need the latest 2.4.0-test kernels and the 
+latest usb-storage driver from 
+http://www.linux-usb.org/
+http://sourceforge.net/cvs/?group_id=3581
+
+Note that the ide-tape driver as of 1.16f uses a slightly outdated on-tape
+format and therefore is not completely interoperable with osst tapes.
+
+The ADR-x0 line is fully SCSI-2 compliant and is supported by st, not osst.
+The on-tape format is supposed to be compatible with the one used by osst.
+
+
+Feedback and updates
+--------------------
+The driver development is coordinated through a mailing list
+<osst@linux1.onstream.nl>
+a CVS repository and some web pages. 
+The tester's pages which contain recent news and updated drivers to download
+can be found on
+http://linux1.onstream.nl/test/
+
+If you find any problems, please have a look at the tester's page in order
+to see whether the problem is already known and solved. Otherwise, please
+report it to the mailing list. Your feedback is welcome. (This holds also
+for reports of successful usage, of course.) 
+In case of trouble, please do always provide the following info:
+* driver and kernel version used (see syslog)
+* driver messages (syslog)
+* SCSI config and OnStream Firmware (/proc/scsi/scsi)
+* description of error. Is it reproducible?
+* software and commands used
+
+You may subscribe to the mailing list, BTW, it's a majordomo list.
+
+
+Status
+------
+0.8.0 was the first widespread BETA release. Since then a lot of reports
+have been sent, but mostly reported success or only minor trouble.
+All the issues have been addressed.
+Check the web pages for more info about the current developments.
+0.9.x is the tree for the 2.3/2.4 kernel.
+
+
+Acknowledgments
+----------------
+The driver has been started by making a copy of Kai Makisara's st driver.
+Most of the development has been done by Willem Riede. The presence of the
+userspace program osg (onstreamsg) from Terry Hardie has been rather
+helpful. The same holds for Gadi Oxman's ide-tape support for the DI-30.
+I did add some patches to those drivers as well and coordinated things a
+little bit. 
+Note that most of them did mostly spend their spare time for the creation of
+this driver.
+The people from OnStream, especially Jack Bombeeck did support this project
+and always tried to answer HW or FW related questions. Furthermore, he
+pushed the FW developers to do the right things.
+SuSE did support this project by allowing me to work on it during my working
+time for them and by integrating the driver into their distro.
+
+More people did help by sending useful comments. Sorry to those who have
+been forgotten. Thanks to all the GNU/FSF and Linux developers who made this
+platform such an interesting, nice and stable platform.
+Thanks go to those who tested the drivers and did send useful reports. Your
+help is needed!
+
+
+Makedevs.sh
+-----------
+#!/bin/sh
+# Script to create OnStream SC-x0 device nodes (major 206)
+# Usage: Makedevs.sh [nos [path to dev]]
+# $Id: README.osst.kernel,v 1.4 2000/12/20 14:13:15 garloff Exp $
+major=206
+nrs=4
+dir=/dev
+test -z "$1" || nrs=$1
+test -z "$2" || dir=$2
+declare -i nr
+nr=0
+test -d $dir || mkdir -p $dir
+while test $nr -lt $nrs; do
+  mknod $dir/osst$nr c $major $nr
+  chown 0.disk $dir/osst$nr; chmod 660 $dir/osst$nr;
+  mknod $dir/nosst$nr c $major $[nr+128]
+  chown 0.disk $dir/nosst$nr; chmod 660 $dir/nosst$nr;
+  mknod $dir/osst${nr}l c $major $[nr+32]
+  chown 0.disk $dir/osst${nr}l; chmod 660 $dir/osst${nr}l;
+  mknod $dir/nosst${nr}l c $major $[nr+160]
+  chown 0.disk $dir/nosst${nr}l; chmod 660 $dir/nosst${nr}l;
+  mknod $dir/osst${nr}m c $major $[nr+64]
+  chown 0.disk $dir/osst${nr}m; chmod 660 $dir/osst${nr}m;
+  mknod $dir/nosst${nr}m c $major $[nr+192]
+  chown 0.disk $dir/nosst${nr}m; chmod 660 $dir/nosst${nr}m;
+  mknod $dir/osst${nr}a c $major $[nr+96]
+  chown 0.disk $dir/osst${nr}a; chmod 660 $dir/osst${nr}a;
+  mknod $dir/nosst${nr}a c $major $[nr+224]
+  chown 0.disk $dir/nosst${nr}a; chmod 660 $dir/nosst${nr}a;
+  let nr+=1
+done
diff -Nru a/Documentation/scsi/ppa.txt b/Documentation/scsi/ppa.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/ppa.txt	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,16 @@
+-------- Terse where to get ZIP Drive help info --------
+
+General Iomega ZIP drive page for Linux:
+http://www.torque.net/~campbell/
+
+Driver achive for old drivers:
+http://www.torque.net/~campbell/ppa/
+
+Linux Parport page (parallel port)
+http://www.torque.net/parport/
+
+Email list for Linux Parport
+linux-parport@torque.net
+
+Email for problems with ZIP or ZIP Plus drivers
+campbell@torque.net
diff -Nru a/Documentation/scsi/qlogicfas.txt b/Documentation/scsi/qlogicfas.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/qlogicfas.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,79 @@
+
+This driver supports the Qlogic FASXXX family of chips.  This driver
+only works with the ISA, VLB, and PCMCIA versions of the Qlogic
+FastSCSI!  cards as well as any other card based on the FASXX chip
+(including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards).
+
+This driver does NOT support the PCI version.  Support for these PCI
+Qlogic boards:
+
+	* IQ-PCI
+	* IQ-PCI-10
+	* IQ-PCI-D
+
+is provided by the qlogicisp.c driver.  Check README.qlogicisp for
+details.
+
+Nor does it support the PCI-Basic, which is supported by the
+'am53c974' driver.
+
+PCMCIA SUPPORT
+
+This currently only works if the card is enabled first from DOS.  This
+means you will have to load your socket and card services, and
+QL41DOS.SYS and QL40ENBL.SYS.  These are a minimum, but loading the
+rest of the modules won't interfere with the operation.  The next
+thing to do is load the kernel without resetting the hardware, which
+can be a simple ctrl-alt-delete with a boot floppy, or by using
+loadlin with the kernel image accessible from DOS.  If you are using
+the Linux PCMCIA driver, you will have to adjust it or otherwise stop
+it from configuring the card.
+
+I am working with the PCMCIA group to make it more flexible, but that
+may take a while.
+
+ALL CARDS
+
+The top of the qlogic.c file has a number of defines that controls
+configuration.  As shipped, it provides a balance between speed and
+function.  If there are any problems, try setting SLOW_CABLE to 1, and
+then try changing USE_IRQ and TURBO_PDMA to zero.  If you are familiar
+with SCSI, there are other settings which can tune the bus.
+
+It may be a good idea to enable RESET_AT_START, especially if the
+devices may not have been just powered up, or if you are restarting
+after a crash, since they may be busy trying to complete the last
+command or something.  It comes up faster if this is set to zero, and
+if you have reliable hardware and connections it may be more useful to
+not reset things.
+
+SOME TROUBLESHOOTING TIPS
+
+Make sure it works properly under DOS.  You should also do an initial FDISK
+on a new drive if you want partitions.
+
+Don't enable all the speedups first.  If anything is wrong, they will make
+any problem worse.
+
+IMPORTANT
+
+The best way to test if your cables, termination, etc. are good is to
+copy a very big file (e.g. a doublespace container file, or a very
+large executable or archive).  It should be at least 5 megabytes, but
+you can do multiple tests on smaller files.  Then do a COMP to verify
+that the file copied properly.  (Turn off all caching when doing these
+tests, otherwise you will test your RAM and not the files).  Then do
+10 COMPs, comparing the same file on the SCSI hard drive, i.e. "COMP
+realbig.doc realbig.doc".  Then do it after the computer gets warm.
+
+I noticed my system which seems to work 100% would fail this test if
+the computer was left on for a few hours.  It was worse with longer
+cables, and more devices on the SCSI bus.  What seems to happen is
+that it gets a false ACK causing an extra byte to be inserted into the
+stream (and this is not detected).  This can be caused by bad
+termination (the ACK can be reflected), or by noise when the chips
+work less well because of the heat, or when cables get too long for
+the speed.
+
+Remember, if it doesn't work under DOS, it probably won't work under
+Linux.
diff -Nru a/Documentation/scsi/qlogicisp.txt b/Documentation/scsi/qlogicisp.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/qlogicisp.txt	Sun Nov 17 20:30:12 2002
@@ -0,0 +1,30 @@
+Notes for the QLogic ISP1020 PCI SCSI Driver:
+
+This driver works well in practice, but does not support disconnect/
+reconnect, which makes using it with tape drives impractical.
+
+It should work for most host adaptors with the ISP1020 chip.  The
+QLogic Corporation produces several PCI SCSI adapters which should
+work:
+
+	* IQ-PCI
+	* IQ-PCI-10
+	* IQ-PCI-D
+
+This driver may work with boards containing the ISP1020A or ISP1040A
+chips, but that has not been tested.
+
+This driver will NOT work with:
+
+	* ISA or VL Bus Qlogic cards (they use the 'qlogicfas' driver)
+	* PCI-basic (it uses the 'am53c974' driver)
+
+Much thanks to QLogic's tech support for providing the latest ISP1020
+firmware, and for taking the time to review my code.
+
+Erik Moe
+ehm@cris.com
+
+Revised:
+Michael A. Griffith
+grif@cs.ucr.edu
diff -Nru a/Documentation/scsi/scsi-generic.txt b/Documentation/scsi/scsi-generic.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/scsi-generic.txt	Sun Nov 17 20:30:14 2002
@@ -0,0 +1,101 @@
+            Notes on Linux SCSI Generic (sg) driver
+            ---------------------------------------
+                                                        20020126
+Introduction
+============
+The SCSI Generic driver (sg) is one of the four "high level" SCSI device
+drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg
+is more generalized (but lower level) than its siblings and tends to be
+used on SCSI devices that don't fit into the already serviced categories.
+Thus sg is used for scanners, CD writers and reading audio CDs digitally
+amongst other things.
+
+Rather than document the driver's interface here, version information
+is provided plus pointers (i.e. URLs) where to find documentation
+and examples.
+
+
+Major versions of the sg driver
+===============================
+There are three major versions of sg found in the linux kernel (lk):
+      - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . 
+	It is based in the sg_header interface structure.
+      - sg version 2 from lk 2.2.6 in the 2.2 series. It is based on
+	an extended version of the sg_header interface structure.
+      - sg version 3 found in the lk 2.4 series (and the lk 2.5 series).
+	It adds the sg_io_hdr interface structure.
+
+
+Sg driver documentation
+=======================
+The most recent documentation of the sg driver is kept at the Linux
+Documentation Project's (LDP) site: 
+http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO
+This describes the sg version 3 driver found in the lk 2.4 series.
+The LDP renders documents in single and multiple page HTML, postscript
+and pdf. This document can also be found at:
+http://www.torque.net/sg/p/sg_v3_ho.html
+
+Documentation for the version 2 sg driver found in the lk 2.2 series can
+be found at http://www.torque.net/sg/p/scsi-generic.txt . A larger version
+is at:  http://www.torque.net/sg/p/scsi-generic_long.txt .
+
+The original documentation for the sg driver (prior to lk 2.2.6) can be
+found at http://www.torque.net/sg/p/original/SCSI-Programming-HOWTO.txt
+and in the LDP archives.
+
+A changelog with brief notes can be found in the
+/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy 
+and edit this file (removing its changelog for example) before placing it 
+in /usr/include/scsi/sg.h . Driver debugging information and other notes 
+can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file.
+
+A more general description of the Linux SCSI subsystem of which sg is a 
+part can be found at http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO .
+
+
+Example code and utilities
+==========================
+There are two packages of sg utilities:
+  - sg3_utils   for the sg version 3 driver found in lk 2.4
+  - sg_utils    for the sg version 2 (and original) driver found in lk 2.2
+                and earlier
+Both packages will work in the lk 2.4 series however sg3_utils offers more
+capabilities. They can be found at: http://www.torque.net/sg and 
+freshmeat.net
+
+Another approach is to look at the applications that use the sg driver.
+These include cdrecord, cdparanoia, SANE and cdrdao.
+
+
+Mapping of Linux kernel versions to sg driver versions
+======================================================
+Here is a list of linux kernels in the 2.4 series that had new version
+of the sg driver:
+      lk 2.4.0 : sg version 3.1.17
+      lk 2.4.7 : sg version 3.1.19 
+      lk 2.4.10 : sg version 3.1.20  **
+      lk 2.4.17 : sg version 3.1.22 
+
+** There were 3 changes to sg version 3.1.20 by third parties in the
+   next six linux kernel versions.
+
+For reference here is a list of linux kernels in the 2.2 series that had 
+new version of the sg driver:
+      lk 2.2.0 : original sg version [with no version number]
+      lk 2.2.6 : sg version 2.1.31
+      lk 2.2.8 : sg version 2.1.32
+      lk 2.2.10 : sg version 2.1.34 [SG_GET_VERSION_NUM ioctl first appeared]
+      lk 2.2.14 : sg version 2.1.36
+      lk 2.2.16 : sg version 2.1.38
+      lk 2.2.17 : sg version 2.1.39
+      lk 2.2.20 : sg version 2.1.40
+
+The lk 2.5 development series has recently commenced and it currently
+contains sg version 3.5.23 which is functionally equivalent to sg
+version 3.1.22 found in lk 2.4.17 .
+
+
+Douglas Gilbert
+26th January 2002
+dgilbert@interlog.com
diff -Nru a/Documentation/scsi/scsi.txt b/Documentation/scsi/scsi.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/scsi.txt	Sun Nov 17 20:30:02 2002
@@ -0,0 +1,44 @@
+SCSI subsystem documentation
+============================
+The Linux Documentation Project (LDP) maintains a document describing
+the SCSI subsystem in the Linux kernel (lk) 2.4 series. See:
+http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single
+and multiple page HTML renderings as well as postscript and pdf.
+It can also be found at http://www.torque.net/scsi/SCSI-2.4-HOWTO .
+
+
+Notes on using modules in the SCSI subsystem
+============================================
+The scsi support in the linux kernel can be modularized in a number of 
+different ways depending upon the needs of the end user.  To understand
+your options, we should first define a few terms.
+
+The scsi-core (also known as the "mid level") contains the core of scsi 
+support.  Without it you can do nothing with any of the other scsi drivers.
+The scsi core support can be a module (scsi_mod.o), or it can be built into
+the kernel. If the core is a module, it must be the first scsi module 
+loaded, and if you unload the modules, it will have to be the last one 
+unloaded.  In practice the modprobe and rmmod commands (and "autoclean")
+will enforce the correct ordering of loading and unloading modules in
+the SCSI subsystem.
+
+The individual upper and lower level drivers can be loaded in any order 
+once the scsi core is present in the kernel (either compiled in or loaded
+as a module).  The disk driver (sd_mod.o), cdrom driver (sr_mod.o),
+tape driver ** (st.o) and scsi generics driver (sg.o) represent the upper 
+level drivers to support the various assorted devices which can be 
+controlled.  You can for example load the tape driver to use the tape drive, 
+and then unload it once you have no further need for the driver (and release
+the associated memory).
+
+The lower level drivers are the ones that support the individual cards that
+are supported for the hardware platform that you are running under. Those
+individual cards are often called Host Bus Adapters (HBAs). For example the
+aic7xxx.o driver is used to control all recent SCSI controller cards from 
+Adaptec. Almost all lower level drivers can be built either as modules or 
+built into the kernel.
+
+
+** There is a variant of the st driver for controlling OnStream tape
+   devices. Its module name is osst.o .
+
diff -Nru a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/scsi_mid_low_api.txt	Sun Nov 17 20:30:15 2002
@@ -0,0 +1,977 @@
+                          Linux Kernel 2.5 series
+                 SCSI mid_level - lower_level driver interface
+                 =============================================
+
+Introduction
+============
+This document outlines the interface between the Linux SCSI mid level and
+SCSI lower level drivers. Lower level drivers (LLDs) are variously called 
+host bus adapter (HBA) drivers, host drivers (HD) or pseudo adapter drivers.
+The latter alludes to the fact that a LLD may be a bridge to another IO 
+subsystem (e.g. the "usb-storage" driver). There can be many LLDs in a 
+running system, but only one per hardware type. Most LLDs can control one
+or more SCSI hosts.
+
+For example, the aic7xxx LLD controls Adaptec SCSI parallel interface
+(SPI) controllers based on that company's 7xxx chip series. The aic7xxx
+LLD can be built into the kernel or loaded as a module. There can only be
+one aic7xxx LLD running in a Linux system but it may be controlling many 
+HBAs. These HBAs might be either on PCI daughterboards or built into 
+the motherboard (or both). Like most modern HBAs, each aic7xxx host
+has its own PCI device address. [The one-to-one correspondance between
+a SCSI host and a PCI device is common but not required (e.g. with
+ISA or MCA adapters).]
+
+The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
+refers to this file. With the appropriate DocBook toolset, this permits
+users to generate html, ps and pdf renderings of information within this
+file (e.g. the interface functions).
+
+This version of the document was written in the period when lk 2.5.47
+was current.
+
+Driver structure
+================
+Traditionally a LLD for the SCSI subsystem has been at least two files in
+the drivers/scsi directory. For example, a driver called "xyz" has a header
+file "xyz.h" and a source file "xyz.c". [Actually there is no good reason
+why this couldn't all be in one file.] Some drivers that have been ported
+to several operating systems have more than two files. For example the
+aic7xxx driver has separate files for generic and OS-specific code
+(e.g. FreeBSD and Linux). Such drivers tend to have their own directory
+under the drivers/scsi directory.
+
+When a new LLD is being added to Linux, the following files (found in the
+drivers/scsi directory) will need some attention: Makefile, Config.help and
+Config.in . SCSI documentation is in the process of being moved to the 
+Documentation/scsi directory in the kernel source tree. It is probably best
+to study how existing LLDs are organized.
+
+As the 2.5 series development kernels evolve, changes are being
+introduced into this interface. An example of this is driver
+initialization code where there are now 2 models available. The older
+one, similar to what was found in the lk 2.4 series, is based on hosts
+that are detected at HBA driver load time. This will be referred to
+the "passive" initialization model. The newer model allows HBAs to be
+hotplugged (and unplugged) while the driver is loaded and will be
+referred to as the "hotplug" initialization model. The newer model is
+preferred as it can handle both traditional SCSI equipment that is
+permanently connected as well as modern "SCSI" usb-storage devices
+(e.g. digital cameras) that are hotplugged. Both initialization models
+are discussed in the following sections.
+
+A LLD interfaces to the SCSI subsystem several ways:
+  a) directly invoking functions supplied by the mid level
+  b) passing a set of function pointers to a registration function
+     supplied by the mid level. The mid level will then invoke these
+     functions at some point in the future
+  c) direct access to instances of well known data structures maintained
+     by the mid level
+
+Those functions in group a) are listed in a section entitled "Mid level
+supplied functions" below.
+
+Those functions in group b) are listed in a section entitled "Interface
+functions" below. The function pointers are placed in the members of
+"struct SHT", an instance of which is passed to scsi_register() [or
+scsi_register_host() in the passive initialization model]. Those interface
+functions that are not mandatory and that the LLD does
+not wish to supply should have NULL placed in the corresponding member
+of struct SHT. [Defining an instance of struct SHT at file scope will
+cause NULL to be placed in function pointer members not explicitly
+initialized.]
+
+Those instances in group c) are slowly being removed as they tend to be
+"racy" especially in a hotplug environment.
+
+
+Hotplug initialization model
+============================
+In this model a LLD controls when SCSI hosts are introduced
+and removed from the SCSI subsystem. Hosts can be introduced as early as
+driver initialization and removed as late as driver shutdown. Typically
+a driver will respond to a sysfs probe() callback that indicates a
+HBA is present (e.g. a PCI device). After confirming it is a device that
+it wants to control, it will initialize the HBA and then register a new 
+host with the SCSI mid level.
+
+Hot unplugging a HBA that controls a disk which is processing SCSI
+commands on a mounted file system is an ugly situation. Issues with
+this scenario are still being worked through. The primary concern in
+the stability of the kernel (specifically the block and SCSI subsystems)
+since the effected disk can be "cleaned up" the next time it is seen.
+
+During LLD initialization the driver should register
+itself with the appropriate IO bus that it expects to find HBA(s)
+(e.g. the PCI bus). This can probably be done via sysfs (formerly known
+as driverfs). Any driver parameters (especially those that are writeable
+after the driver is loaded) could also be registered with sysfs at
+this point. At the end of driver initialization the SCSI mid level is
+typically not aware of its presence.
+
+At some later time, the LLD becomes aware of a HBA and what follows
+is a typical sequence of calls (for 3 discovered SCSI devices)
+between the LLD and the mid level.
+
+LLD                   mid level                    LLD
+---                   ---------                    ---
+scsi_register()  -->
+scsi_add_host()  --------+
+                         |
+                    slave_attach()  -->  scsi_adjust_queue_depth()
+                    slave_attach()  -->  scsi_adjust_queue_depth()
+                    slave_attach()  -->  scsi_adjust_queue_depth()
+
+The invocation of scsi_adjust_queue_depth() by the LLD is optional.
+
+Here is the corresponding sequence when a host (HBA) is being
+removed:
+
+LLD                   mid level  
+---                   ---------
+scsi_remove_host()  -----+
+                         |
+                    slave_detach() 
+                    slave_detach()
+                    slave_detach()
+scsi_unregister()  -->
+
+It is practical for a LLD to keep track of struct Scsi_Host instances
+(a pointer is returned by scsi_register() ) and struct scsi_device
+instances (a pointer is passed as the parameter to slave_attach() ).
+Both classes of instances are "owned" by the mid-level. struct scsi_devices 
+instances are freed after slave_detach(). struct Scsi_Host instances
+are freed after scsi_unregister().
+
+
+Passive initialization model
+============================
+LLD initialization (both built-in and module) and shutdown and "wired
+up" by passing function pointers to the module_init() and module_exit()
+macros respectively. In this model the function identified by "module_init"
+must call scsi_register_host() and the function identified by "module_exit"
+must call scsi_unregister_host().
+Most LLDs inherited from the lk 2.4 series include a file called
+"scsi_module.c" [yes the ".c" is a little surprising] in their
+source code. For it to work a declaration like this is needed before
+it is included:
+    static struct SHT driver_template = DRIVER_TEMPLATE;
+    #include "scsi_module.c"
+
+In this case "DRIVER_TEMPLATE" is defined to be a structure initializer
+that is placed in the driver header file by convention. It contains
+pointers to supported interface functions and other values.
+
+Here is an example of an initialization sequence when two hosts are
+detected (so detect() returns 2) and the SCSI bus scan on each host
+finds 3 SCSI devices.
+
+LLD                      mid level                 LLD
+---                      ---------                 ---
+scsi_register_host() -------+
+                            |
+                         detect()  -----------------+
+                            |                       |
+                            |                scsi_register()
+                            |                scsi_register()
+                            |
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+                            |
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+                      slave_attach()  -->  scsi_adjust_queue_depth()
+
+If the LLD does not supply a slave_attach() then the mid level invokes
+scsi_adjust_queue_depth() itself with tagged queuing off and "cmd_per_lun"
+for that host as the third parameter.
+
+Here is a LLD shutdown sequence:
+
+LLD                      mid level                 LLD
+---                      ---------                 ---
+scsi_unregister_host() -----+
+                            |
+                     slave_detach()
+                     slave_detach()
+                     slave_detach()
+                        release()   -->   scsi_unregister()
+                            |
+                     slave_detach()
+                     slave_detach()
+                     slave_detach()
+                        release()   -->   scsi_unregister()
+
+Both slave_detach() and release() are optional. If they are not supplied
+the mid level supplies default actions.
+
+The shortcoming of the "passive initialization model" is that host
+registration and de-registration are (typically) tied to LLD initialization
+and shutdown. Once the LLD is initialized then a new host that appears
+(e.g. via hotplugging) cannot easily be added without a redundant
+driver shutdown and re-initialization.
+
+
+Conventions
+===========
+First there is Linus's thoughts on C coding found in file 
+Documentation/CodingStyle . 
+
+Next there is a movement to "outlaw" typedefs introducing synonyms for 
+struct tags. Both can be still found in the SCSI subsystem, for example: 
+"typedef struct SHT { ...} Scsi_Host_Template;" in hosts.h . In this
+case "struct SHT" is preferred to "Scsi_Host_Template".
+
+Also C99 additions are encouraged to the extent they are supported
+by the relevant gcc compilers. So "//" style comments are encouraged
+were appropriate as are C99 style structure and array initializers.
+
+
+Mid level supplied functions
+============================
+These functions are supplied by the SCSI mid level for use by LLDs.
+The names (i.e. entry points) of these functions are exported
+so a LLD that is a module can access them when the SCSI
+mid level is built into the kernel. The kernel will arrange for the
+SCSI mid level to be loaded and initialized before any LLD
+is initialized. The functions below are listed alphabetically and their
+names all start with "scsi_".
+
+/**
+ * scsi_add_host - perform sysfs registration and SCSI bus scan.
+ * @shost:   pointer to scsi host instance
+ *
+ *      Returns 0 on success, negative errno of failure (e.g. -ENOMEM)
+ *
+ *	Notes: Only required in "hotplug initialization model" after a
+ *	successful call to scsi_register().
+ *	Defined in drivers/scsi/hosts.c
+ **/
+int scsi_add_host(struct Scsi_Host *shost)
+
+
+/**
+ * scsi_adjust_queue_depth - change the queue depth on a SCSI device
+ * @SDpnt:	pointer to SCSI device to change queue depth on
+ * @tagged:	0 - no tagged queueing
+ *		MSG_SIMPLE_TAG - simple (unordered) tagged queueing
+ *		MSG_ORDERED_TAG - ordered tagged queueing
+ * @tags	Number of tags allowed if tagged queueing enabled,
+ *		or number of commands the LLD can queue up
+ *		in non-tagged mode (as per cmd_per_lun).
+ *
+ *	Returns nothing
+ *
+ * 	Notes: Can be invoked any time on a SCSI device controlled by this
+ *	LLD. [Specifically after slave_attach() and prior to slave_detach().]
+ *	Can safely be invoked from interrupt code. Actual queue depth change
+ *	may be delayed until the next command is being processed.
+ *	Defined in drivers/scsi/scsi.c [see source code for more notes]
+ *
+ **/
+void scsi_adjust_queue_depth(struct scsi_device * SDpnt, int tagged, 
+			     int num_tags)
+
+
+/**
+ * scsi_assign_lock - replace default host_lock with given lock
+ * @shost: a pointer to a scsi host instance
+ * @lock: pointer to lock to replace host_lock for this host
+ *
+ *      Returns nothing
+ *
+ *      Notes: Defined in drivers/scsi/hosts.h .
+ **/
+void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
+
+
+/**
+ * scsi_bios_ptable - return copy of block device's partition table
+ * @dev:	pointer to block device
+ *
+ *	Returns pointer to partition table, or NULL or failure
+ *
+ *	Notes: Caller owns memory returned (free with kfree() )
+ *	Defined in drivers/scsi/scsicam.c
+ **/
+unsigned char *scsi_bios_ptable(struct block_device *dev)
+
+
+/**
+ * scsi_block_requests - prevent further commands being queued to given host
+ *
+ * @SHpnt: pointer to host to block commands on
+ *
+ *	Returns nothing
+ *
+ * 	Notes: There is no timer nor any other means by which the requests
+ *	get unblocked other than the LLD calling scsi_unblock_requests().
+ *	Defined in drivers/scsi/scsi_lib.c
+**/
+void scsi_block_requests(struct Scsi_Host * SHpnt)
+
+
+/**
+ * scsi_partsize - parse partition table into cylinders, heads + sectors
+ * @buf: pointer to partition table
+ * @capacity: size of (total) disk in 512 byte sectors
+ * @cyls: outputs number of cylinders calculated via this pointer
+ * @hds: outputs number of heads calculated via this pointer
+ * @secs: outputs number of sectors calculated via this pointer
+ *
+ *	Returns 0 on success, -1 on failure
+ *
+ *	Notes: Caller owns memory returned (free with kfree() )
+ *	Defined in drivers/scsi/scsicam.c
+ **/
+int scsi_partsize(unsigned char *buf, unsigned long capacity,
+               unsigned int *cyls, unsigned int *hds, unsigned int *secs)
+
+
+/**
+ * scsi_register - create and register a scsi host adapter instance.
+ * @shost_tp:   pointer to scsi host template
+ * @xtr_bytes:  extra bytes to allocate in hostdata array (which is the
+ *		last member of the returned Scsi_Host instance)
+ *
+ *      Returns pointer to new Scsi_Host instance or NULL on failure
+ *
+ *	Notes: When this call returns to the LLDD, the SCSI bus scan on
+ *	this host has _not_ yet been done.
+ *	The hostdata array (by default zero length) is a per host scratch 
+ *	area for the LLD.
+ *	Defined in drivers/scsi/hosts.c .
+ **/
+struct Scsi_Host * scsi_register(struct SHT *, int xtr_bytes)
+
+
+/**
+ * scsi_register_host - register a low level host driver
+ * @shost_tp:   pointer to a scsi host driver template
+ *
+ *      Returns 0 on Success, 1 on failure
+ *
+ *      Notes: Should only be invoked if the "passive initialization
+ *	model" is being used. Notice this is a _driver_ rather than 
+ *	HBA registration function. Most older drivers call this
+ *	function by including the scsi_module.c file.
+ *	This function is deprecated, use the "hotplug initialization
+ *	model" instead.
+ *	Defined in drivers/scsi/hosts.c .
+ **/
+int scsi_register_host(Scsi_Host_Template *shost_tp)
+
+
+/**
+ * scsi_remove_host - detach and remove all SCSI devices owned by host
+ * @shost:      a pointer to a scsi host instance
+ *
+ *	Returns value: 0 on success, 1 on failure (e.g. LLD busy ??)
+ *
+ *      Notes: Should only be invoked if the "hotplug initialization
+ *	model" is being used. It should be called _prior_ to  
+ *	scsi_unregister().
+ *	Defined in drivers/scsi/hosts.c .
+ **/
+int scsi_remove_host(struct Scsi_Host *shost)
+
+
+/**
+ * scsi_report_bus_reset - report scsi _bus_ reset observed
+ * @shost: a pointer to a scsi host involved
+ * @channel: channel (within) host on which scsi bus reset occurred
+ *
+ *	Returns nothing
+ *
+ *      Notes: This only needs to be called if the reset is one which
+ *	originates from an unknown location.  Resets originated by the 
+ *	mid level itself don't need to call this, but there should be 
+ *	no harm.  The main purpose of this is to make sure that a
+ *	CHECK_CONDITION is properly treated.
+ *	Defined in drivers/scsi/scsi_lib.c .
+ **/
+void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
+
+
+/**
+ * scsi_set_pci_device - place PCI device reference in host structure
+ * @shost: a pointer to a scsi host instance
+ * @pdev: pointer to PCI device instance to assign
+ *
+ *	Returns nothing
+ *
+ *      Notes: Defined in drivers/scsi/hosts.h .
+ **/
+void scsi_set_pci_device(struct Scsi_Host * shost, struct pci_dev * pdev)
+
+
+/**
+ * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI
+ * @scsi_data_direction: SCSI subsystem direction flag
+ *
+ *	Returns PCI_DMA_TODEVICE given SCSI_DATA_WRITE,
+ *		PCI_DMA_FROMDEVICE given SCSI_DATA_READ
+ *		PCI_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
+ *		else returns PCI_DMA_NONE
+ *
+ *      Notes: Defined in drivers/scsi/scsi.h .
+ **/
+int scsi_to_pci_dma_dir(unsigned char scsi_data_direction)
+
+
+/**
+ * scsi_unblock_requests - allow further commands to be queued to given host
+ *
+ * @SHpnt: pointer to host to unblock commands on
+ *
+ *	Returns nothing
+ *
+ * 	Notes: Defined in drivers/scsi/scsi_lib.c .
+**/
+void scsi_unblock_requests(struct Scsi_Host * SHpnt)
+
+
+/**
+ * scsi_unregister - unregister and free host
+ * @shp:	pointer to scsi host instance to unregister.
+ *		N.B. shp points to freed memory on return
+ *
+ *	Returns nothing
+ *
+ *      Notes: Should only be invoked if the "hotplug initialization
+ *	model" is being used. It should be called _after_  
+ *	scsi_remove_host().
+ *	Defined in drivers/scsi/hosts.c .
+ **/
+void scsi_unregister(struct Scsi_Host * shp)
+
+
+/**
+ * scsi_unregister_host - unregister a low level host adapter driver
+ * @shost_tp:   scsi host template to unregister.
+ *
+ *	Returns 0 on Success, 1 on Failure
+ *
+ *      Notes: Should only be invoked if the "passive initialization
+ *	model" is being used. Notice this is a _driver_ rather than 
+ *	HBA deregistration function. Most older drivers call this
+ *	function by including the scsi_module.c file.
+ *	This function is deprecated, use the "hotplug initialization
+ *	model" instead.
+ *	Defined in drivers/scsi/hosts.c .
+ **/
+int scsi_unregister_host(Scsi_Host_Template *shost_tp)
+
+
+
+Interface Functions
+===================
+Interface functions are supplied (defined) by LLDs and
+their function pointers are placed in an instance of struct SHT which
+is passed to scsi_register() [or scsi_register_host()]. Some
+are mandatory. Interface functions should be declared static. The 
+accepted convention is that driver "xyz" will declare its slave_attach() 
+function as:
+    static int xyz_slave_attach(struct scsi_device * sdev);
+
+A pointer to this function should be placed in the 'slave_attach' member
+of a "struct SHT" instance. A pointer to such an instance should
+passed to the mid level's scsi_register() [or scsi_register_host()].
+
+The interface functions are also described in the hosts.h file immediately
+above their definition point in "struct SHT". In some cases more detail
+is given in hosts.h than below.
+
+Those interface functions marked "Required: yes" must be implemented
+by the LLD and a pointer to that function must be placed in the driver's
+"struct SHT" instance. Interface functions marked "Required: no" need not
+be implemented.
+
+The interface functions are listed below in alphabetical order.
+
+
+/**
+ *      bios_param - fetch head, sector, cylinder info for a disk
+ *      @sdev: pointer to scsi device context (defined in scsi.h)
+ *      @bdev: pointer to block device context (defined in fs.h)
+ *	@capacity:  device size (in 512 byte sectors)
+ *      @params: three element array to place output:
+ *              params[0] number of heads (max 255)
+ *              params[1] number of sectors (max 63)
+ *              params[2] number of cylinders 
+ *
+ *      Return value is ignored
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: an arbitrary geometry (based on READ CAPACITY) is used
+ *      if this function is not provided. The params array is
+ *      pre-initialized with made up values just in case this function 
+ *      doesn't output anything.
+ **/
+    int bios_param(struct scsi_device * sdev, struct block_device *bdev,
+    		   sector_t capacity, int params[3]);
+
+
+/**
+ *      command - send scsi command to device, wait for reply
+ *      @scp: pointer to scsi command object
+ *
+ *      Returns an int with four component bytes: scsi_byte, msg_byte, 
+ *      host_byte, driver_byte (status_byte is in the lsb). A value of
+ *      0 is an unqualified success.
+ *
+ *      Required: if struct Scsi_Host::can_queue can ever by cleared (zero)
+ *                then this function is required.
+ *
+ *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
+ *             and is expected to be held on return.
+ *
+ *      Notes: Drivers tend to be dropping support for this function and
+ *      supporting queuecommand() instead.
+ **/
+    int command(struct scsi_cmnd * scp);
+
+
+/**
+ *      detect - detects HBAs this driver wants to control
+ *      @shtp: host template for this driver.
+ *
+ *      Returns number of hosts this driver wants to control. 0 means no
+ *      suitable hosts found.
+ *
+ *      Required: yes, if "passive initialization mode" is used
+ *		  [in "hotplug initialization mode" it is not invoked]
+ *
+ *      Locks: none held
+ *
+ *      Notes: First function called from the SCSI mid level on this
+ *      driver. Upper level drivers (e.g. sd) may not (yet) be present.
+ *      For each host found, this method should call scsi_register() 
+ *      [see hosts.c].
+ **/
+    int detect(struct SHT * shtp);
+
+
+/**
+ *      eh_abort_handler - abort command associated with scp
+ *      @scp: identifies command to be aborted
+ *
+ *      Returns SUCCESS if command aborted else FAILED
+ *
+ *      Required: no
+ *
+ *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry 
+ *	and assumed to be held on return.
+ *
+ *      Notes: Invoked from scsi_eh thread. No other commands will be
+ *      queued on current host during eh.
+ **/
+     int eh_abort_handler(struct scsi_cmnd * scp);
+
+
+/**
+ *      eh_device_reset_handler - issue SCSI device reset
+ *      @scp: identifies SCSI device to be reset
+ *
+ *      Returns SUCCESS if command aborted else FAILED
+ *
+ *      Required: no
+ *
+ *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
+ *	and assumed to be held on return.
+ *
+ *      Notes: Invoked from scsi_eh thread. No other commands will be
+ *      queued on current host during eh.
+ **/
+     int eh_device_reset_handler(struct scsi_cmnd * scp);
+
+
+/**
+ *      eh_bus_reset_handler - issue SCSI bus reset
+ *      @scp: SCSI bus that contains this device should be reset
+ *
+ *      Returns SUCCESS if command aborted else FAILED
+ *
+ *      Required: no
+ *
+ *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry 
+ *	and assumed to be held on return.
+ *
+ *      Notes: Invoked from scsi_eh thread. No other commands will be
+ *      queued on current host during eh.
+ **/
+     int eh_bus_reset_handler(struct scsi_cmnd * scp);
+
+
+/**
+ *      eh_host_reset_handler - reset host (host bus adapter)
+ *      @scp: SCSI host that contains this device should be reset
+ *
+ *      Returns SUCCESS if command aborted else FAILED
+ *
+ *      Required: no
+ *
+ *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
+ *	and assumed to be held on return.
+ *
+ *      Notes: Invoked from scsi_eh thread. No other commands will be
+ *      queued on current host during eh. 
+ *      With the default eh_strategy in place, if none of the _abort_, 
+ *      _device_reset_, _bus_reset_ or this eh handler function are 
+ *      defined (or they all return FAILED) then the device in question 
+ *      will be set offline whenever eh is invoked.
+ **/
+     int eh_host_reset_handler(struct scsi_cmnd * scp);
+
+
+/**
+ *      eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
+ *      @shp: host on which error has occurred
+ *
+ *      Returns TRUE if host unjammed, else FALSE.
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: Invoked from scsi_eh thread. Driver supplied alternate to 
+ *      scsi_unjam_host() found in scsi_error.c
+ **/
+     int eh_strategy_handler(struct Scsi_Host * shp);
+
+
+/**
+ *      info - supply information about given host: driver name plus data
+ *             to distinguish given host
+ *      @shp: host to supply information about
+ *
+ *      Return ASCII null terminated string. [This driver is assumed to
+ *      manage the memory pointed to and maintain it, typically for the
+ *      lifetime of this host.]
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: Often supplies PCI or ISA information such as IO addresses
+ *      and interrupt numbers. If not supplied struct Scsi_Host::name used
+ *      instead. It is assumed the returned information fits on one line 
+ *      (i.e. does not included embedded newlines).
+ *      The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this
+ *      function (or struct Scsi_Host::name if this function is not
+ *	available).
+ *      In a similar manner, scsi_register_host() outputs to the console
+ *      each host's "info" (or name) for the driver it is registering.
+ *      Also if proc_info() is not supplied, the output of this function
+ *      is used instead.
+ **/
+    const char * info(struct Scsi_Host * shp);
+
+
+/**
+ *      ioctl - driver can respond to ioctls
+ *      @sdp: device that ioctl was issued for
+ *      @cmd: ioctl number
+ *      @arg: pointer to read or write data from. Since it points to
+ *            user space, should use appropriate kernel functions
+ *            (e.g. copy_from_user() ). In the Unix style this argument
+ *            can also be viewed as an unsigned long.
+ *
+ *      Returns negative "errno" value when there is a problem. 0 or a
+ *      positive value indicates success and is returned to the user space.
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: The SCSI subsystem uses a "trickle down" ioctl model.
+ *      The user issues an ioctl() against an upper level driver
+ *      (e.g. /dev/sdc) and if the upper level driver doesn't recognize
+ *      the 'cmd' then it is passed to the SCSI mid level. If the SCSI
+ *      mid level does not recognize it, then the LLD that controls
+ *      the device receives the ioctl. According to recent Unix standards
+ *      unsupported ioctl() 'cmd' numbers should return -ENOTTY.
+ *      However the mid level returns -EINVAL for unrecognized 'cmd'
+ *      numbers when this function is not supplied by the driver.
+ *      Unfortunately some applications expect -EINVAL and react badly
+ *	when -ENOTTY is returned; stick with -EINVAL.
+ **/
+    int ioctl(struct scsi_device *sdp, int cmd, void *arg);
+
+
+/**
+ *      proc_info - supports /proc/scsi/{driver_name}/{host_no}
+ *      @buffer: anchor point to output to (0==writeto1_read0) or fetch from
+ *               (1==writeto1_read0).
+ *      @start: where "interesting" data is written to. Ignored when
+ *              1==writeto1_read0.
+ *      @offset: offset within buffer 0==writeto1_read0 is actually
+ *               interested in. Ignored when 1==writeto1_read0 .
+ *      @length: maximum (or actual) extent of buffer
+ *      @host_no: host number of interest (struct Scsi_Host::host_no)
+ *      @writeto1_read0: 1 -> data coming from user space towards driver
+ *                            (e.g. "echo some_string > /proc/scsi/xyz/2")
+ *                       0 -> user what data from this driver
+ *                            (e.g. "cat /proc/scsi/xyz/2")
+ *
+ *      Returns length when 1==writeto1_read0. Otherwise number of chars
+ *      output to buffer past offset.
+ *
+ *      Required: no
+ *
+ *      Locks: none held
+ *
+ *      Notes: Driven from scsi_proc.c which interfaces to proc_fs
+ **/
+int proc_info(char * buffer, char ** start, off_t offset, 
+              int length, int hostno, int writeto1_read0);
+
+
+/**
+ *      queuecommand - queue scsi command, invoke 'done' on completion
+ *      @scp: pointer to scsi command object
+ *      @done: function pointer to be invoked on completion
+ *
+ *      Returns 1 if the adapter (host) is busy, else returns 0. One
+ *		reason for an adapter to be busy is that the number
+ *		of outstanding queued commands is already equal to
+ *		struct Scsi_Host::can_queue .
+ *
+ *      Required: if struct Scsi_Host::can_queue is ever non-zero
+ *                then this function is required.
+ *
+ *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
+ *             and is expected to be held on return.
+ *
+ *      Notes: This function should be relatively fast. Normally it will
+ *      not wait for IO to complete. Hence the 'done' callback is invoked 
+ *      (often directly from an interrupt service routine) sometime after
+ *      this command has returned. In some cases (e.g. pseudo adapter 
+ *      drivers that manufacture the response to a SCSI INQUIRY)
+ *      the 'done' callback may be invoked before this function returns.
+ *      If the 'done' callback is not invoked within a certain period
+ *      the SCSI mid level will commence error processing.
+ *      The integer with 4 component bytes that command() uses as its
+ *      return value should be generated by this function. However, in
+ *      this case, it should be placed in scp->result before this function 
+ *      returns.
+ *      If a status of CHECK CONDITION is placed in "result" when the
+ *	'done' callback is invoked, then the LLD driver should 
+ *	perform autosense and fill in the struct scsi_cmnd::sense_buffer
+ *	array.
+ **/
+    int queuecommand(struct scsi_cmnd * scp, 
+		     void (*done)(struct scsi_cmnd *));
+
+
+/**
+ *      release - release all resources associated with given host
+ *      @shp: host to be released.
+ *
+ *      Return value ignored.
+ *
+ *      Required: no
+ *
+ *      Locks: lock_kernel() active on entry and expected to be active
+ *      on return.
+ *
+ *      Notes: Invoked from mid level's scsi_unregister_host().
+ *      This function should call scsi_unregister(shp) [found in hosts.c]
+ *      prior to returning.
+ **/
+    int release(struct Scsi_Host * shp);
+
+
+/**
+ *      slave_attach - driver fine tuning for give device just after it
+ *		       has been first scan (i.e. it responded to an
+ *		       INQUIRY)
+ *      @sdp: device that has just been attached
+ *
+ *      Returns 0 if ok. Any other return is assumed to be an error and
+ *	the device is taken offline.
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: Allows the driver to inspect the response to the initial
+ *	INQUIRY done by the scanning code and take appropriate action.
+ *	For more details see the hosts.h file.
+ *	If this function is not supplied, the mid level will call
+ *	scsi_adjust_queue_depth() with the struct Scsi_Host::cmd_per_lun
+ *	value on behalf of the given device. If this function is
+ *	supplied then its implementation is expected to call
+ *	scsi_adjust_queue_depth(). 	
+ **/
+    int slave_attach(struct scsi_device *sdp);
+
+
+/**
+ *      slave_detach - given device is about to be shut down. No further
+ *		       commands will be sent.
+ *      @sdp: device that is about to be detached
+ *
+ *      Returns nothing
+ *
+ *      Required: no
+ *
+ *      Locks: none
+ *
+ *      Notes: Mid level structures for given device are still in place
+ *	but are about to be torn down. Any per device resources allocated
+ *	by this driver for given device should be freed now. No further
+ *	commands will be sent for this sdp instance. [However the device
+ *	could be re-attached in the future in which case a new instance
+ *	of struct scsi_device would be supplied by a future slave_attach()
+ *	call.]
+ **/
+    void slave_detach(struct scsi_device *sdp);
+
+
+
+Data Structures
+===============
+struct SHT
+----------
+There is one "struct SHT" instance per LLD ***. It is
+typically initialized as a file scope static in a driver's header file. That
+way members that are not explicitly initialized will be set to 0 or NULL.
+Member of interest:
+    name         - name of driver (should only use characters that are
+                   permitted in a unix file name)
+    proc_name    - name used in "/proc/scsi/<proc_name>/<host_no>"
+The structure is defined and commented in hosts.h
+
+*** In extreme situations a single driver may have several instances
+    if it controls several different classes of hardware (e.g. the
+    advansys driver handles both ISA and PCI cards).
+
+struct Scsi_Host
+----------------
+There is one struct Scsi_Host instance per host (HBA) that a LLD
+controls. The struct Scsi_Host structure has many members in common
+with "struct SHT". When a new struct Scsi_Host instance is created (in
+scsi_register() in hosts.c) those common members are initialized from
+the driver's struct SHT instance. Members of interest:
+    host_no      - system wide unique number that is used for identifying
+                   this host. Issued in ascending order from 0 (and the
+                   positioning can be influenced by the scsihosts
+                   kernel boot (or module) parameter)
+    can_queue    - 0->use command(), greater than 0->use queuecommand() and
+                   do not send more than can_queue commands to the adapter.
+    this_id      - scsi id of host (scsi initiator) or -1 if not known
+    sg_tablesize - maximum scatter gather elements allowed by host.
+                   0 implies scatter gather not supported by host
+    max_sectors  - maximum number of sectors (usually 512 bytes) allowed
+                   in a single SCSI command. 0 implies no maximum.
+    cmd_per_lun  - maximum number of command that can be queued on devices
+                   controlled by the host. Overridden by LLD calls to
+		   scsi_adjust_queue_depth().
+    unchecked_isa_dma - 1->only use bottom 16 MB of ram (ISA DMA addressing
+                   restriction), 0->can use full 32 bit (or better) DMA
+                   address space
+    use_clustering - 1->SCSI commands in mid level's queue can be merged,
+                     0->disallow SCSI command merging
+    highmem_io   - 1->can DMA in to or out of high memory,
+                   0->use bounce buffers if data is in high memory
+    hostt        - pointer to driver's struct SHT from which this
+                   struct Scsi_Host instance was spawned
+    host_queue   - deceptively named pointer to the start of a double linked
+                   list of struct scsi_device instances that belong to this
+		   host.
+The structure is defined in hosts.h
+
+struct scsi_device
+------------------
+Generally, there is one instance of this structure for each SCSI logical unit
+on a host. Scsi devices are uniquely identified within a host by bus number,
+target id and logical unit number (lun).
+The structure is defined in scsi.h
+
+struct scsi_cmnd
+----------------
+Instances of this structure convey SCSI commands to the LLD.
+Each SCSI device has a pool of struct scsi_cmnd instances whose size
+is determined by scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun).
+There will be at least one instance of struct scsi_cmnd for each SCSI device.
+The structure is defined in scsi.h
+
+
+Locks
+=====
+Each struct Scsi_Host instance has a spin_lock called struct 
+Scsi_Host::default_lock which is initialized in scsi_register() [found in 
+hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer
+is initialized to point at default_lock with the scsi_assign_lock() function.
+Thereafter lock and unlock operations performed by the mid level use the
+struct Scsi_Host::host_lock pointer.
+
+LLDs can override the use of struct Scsi_Host::default_lock by
+using scsi_assign_lock(). The earliest opportunity to do this would
+be in the detect() function after it has invoked scsi_register(). It
+could be replaced by a coarser grain lock (e.g. per driver) or a
+lock of equal granularity (i.e. per host). Using finer grain locks 
+(e.g. per SCSI device) may be possible by juggling locks in
+queuecommand().
+
+Autosense
+=========
+Autosense (or auto-sense) is defined in the SAM-2 document as "the
+automatic return of sense data to the application client coincident
+with the completion of a SCSI command" when a status of CHECK CONDITION
+occurs. LLDs should perform autosense. This should be done when the LLD
+detects a CHECK CONDITION status by either: 
+    a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI))
+       to perform an extra data in phase on such responses
+    b) or, the LLD issuing a REQUEST SENSE command itself
+
+Either way, the mid level decides whether the LLD has 
+performed autosense by checking struct scsi_cmnd::sense_buffer[0] . If this
+byte has an upper nibble of 7 then autosense is assumed to have taken 
+place. If it has another value (and this byte is initialized to 0 before
+each command) then the mid level will issue a REQUEST SENSE command.
+
+In the presence of queued commands the "nexus" that maintains sense
+buffer data from the command that failed until a following REQUEST SENSE
+may get out of synchronization. This is why it is best for the LLD
+to perform autosense.
+
+
+Changes since lk 2.4 series
+===========================
+io_request_lock has been replaced by several finer grained locks. The lock 
+relevant to LLDs is struct Scsi_Host::host_lock and there is
+one per SCSI host.
+
+The older error handling mechanism has been removed. This means the
+LLD interface functions abort() and reset() have been removed.
+The struct SHT::use_new_eh_code flag has been removed.
+
+In the 2.4 series the SCSI subsystem configuration descriptions were 
+aggregated with the configuration descriptions from all other Linux 
+subsystems in the Documentation/Configure.help file. In the 2.5 series, 
+the SCSI subsystem now has its own (much smaller) drivers/scsi/Config.help
+file.
+
+Addition of slave_attach() and slave_detach().
+
+Addition of the "hotplug initialization model".
+
+
+Credits
+=======
+The following people have contributed to this document:
+        Mike Anderson <andmike@us.ibm.com>
+        James Bottomley <James.Bottomley@steeleye.com> 
+        Patrick Mansfield <patmans@us.ibm.com> 
+	Christoph Hellwig <hch@infradead.org>
+
+
+Douglas Gilbert
+dgilbert@interlog.com
+17th November 2002
diff -Nru a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/st.txt	Sun Nov 17 20:30:04 2002
@@ -0,0 +1,447 @@
+This file contains brief information about the SCSI tape driver.
+The driver is currently maintained by Kai M{kisara (email
+Kai.Makisara@metla.fi)
+
+Last modified: Fri Jul 26 16:01:39 2002 by makisara
+
+
+BASICS
+
+The driver is generic, i.e., it does not contain any code tailored
+to any specific tape drive. The tape parameters can be specified with
+one of the following three methods:
+
+1. Each user can specify the tape parameters he/she wants to use
+directly with ioctls. This is administratively a very simple and
+flexible method and applicable to single-user workstations. However,
+in a multiuser environment the next user finds the tape parameters in
+state the previous user left them.
+
+2. The system manager (root) can define default values for some tape
+parameters, like block size and density using the MTSETDRVBUFFER ioctl.
+These parameters can be programmed to come into effect either when a
+new tape is loaded into the drive or if writing begins at the
+beginning of the tape. The second method is applicable if the tape
+drive performs auto-detection of the tape format well (like some
+QIC-drives). The result is that any tape can be read, writing can be
+continued using existing format, and the default format is used if
+the tape is rewritten from the beginning (or a new tape is written
+for the first time). The first method is applicable if the drive
+does not perform auto-detection well enough and there is a single
+"sensible" mode for the device. An example is a DAT drive that is
+used only in variable block mode (I don't know if this is sensible
+or not :-).
+
+The user can override the parameters defined by the system
+manager. The changes persist until the defaults again come into
+effect.
+
+3. Up to four modes can be defined and selected using the minor number
+(bits 5 and 6). Mode 0 corresponds to the defaults discussed
+above. Additional modes are dormant until they are defined by the
+system manager (root). When specification of a new mode is started,
+the configuration of mode 0 is used to provide a starting point for
+definition of the new mode.
+
+Using the modes allows the system manager to give the users choices
+over some of the buffering parameters not directly accessible to the
+users (buffered and asynchronous writes). The modes also allow choices
+between formats in multi-tape operations (the explicitly overridden
+parameters are reset when a new tape is loaded).
+
+If more than one mode is used, all modes should contain definitions
+for the same set of parameters.
+
+Many Unices contain internal tables that associate different modes to
+supported devices. The Linux SCSI tape driver does not contain such
+tables (and will not do that in future). Instead of that, a utility
+program can be made that fetches the inquiry data sent by the device,
+scans its database, and sets up the modes using the ioctls. Another
+alternative is to make a small script that uses mt to set the defaults
+tailored to the system.
+
+The driver supports fixed and variable block size (within buffer
+limits). Both the auto-rewind (minor equals device number) and
+non-rewind devices (minor is 128 + device number) are implemented.
+
+In variable block mode, the byte count in write() determines the size
+of the physical block on tape. When reading, the drive reads the next
+tape block and returns to the user the data if the read() byte count
+is at least the block size. Otherwise, error ENOMEM is returned.
+
+In fixed block mode, the data transfer between the drive and the
+driver is in multiples of the block size. The write() byte count must
+be a multiple of the block size. This is not required when reading but
+may be advisable for portability.
+
+Support is provided for changing the tape partition and partitioning
+of the tape with one or two partitions. By default support for
+partitioned tape is disabled for each driver and it can be enabled
+with the ioctl MTSETDRVBUFFER.
+
+By default the driver writes one filemark when the device is closed after
+writing and the last operation has been a write. Two filemarks can be
+optionally written. In both cases end of data is signified by
+returning zero bytes for two consecutive reads.
+
+The compile options are defined in the file linux/drivers/scsi/st_options.h.
+
+4. If the open option O_NONBLOCK is used, open succeeds even if the
+drive is not ready. If O_NONBLOCK is not used, the driver waits for
+the drive to become ready. If this does not happen in ST_BLOCK_SECONDS
+seconds, open fails with the errno value EIO.
+
+
+BSD AND SYS V SEMANTICS
+
+The user can choose between these two behaviours of the tape driver by
+defining the value of the symbol ST_SYSV. The semantics differ when a
+file being read is closed. The BSD semantics leaves the tape where it
+currently is whereas the SYS V semantics moves the tape past the next
+filemark unless the filemark has just been crossed.
+
+The default is BSD semantics.
+
+
+BUFFERING
+
+The driver tries to do tranfers directly to/from user space. If this
+is not possible, a driver buffer allocated at run-time is used. If
+direct i/o is not possible for the whole transfer, the driver buffer
+is used (i.e., bounce buffers for individual pages are not
+used). Direct i/o can be impossible because of several reasons, e.g.:
+- one or more pages are at addresses not reachable by the HBA
+- the number of pages in the transfer exceeds the number of
+  scatter/gather segments permitted by the HBA
+- one or more pages can't be locked into memory (should not happen in
+  any reasonable situation)
+
+The size of the driver buffers is always at least one tape block. In fixed
+block mode, the minimum buffer size is defined (in 1024 byte units) by
+ST_FIXED_BUFFER_BLOCKS. With small block size this allows buffering of
+several blocks and using one SCSI read or write to transfer all of the
+blocks. Buffering of data across write calls in fixed block mode is
+allowed if ST_BUFFER_WRITES is non-zero and direct i/o is not used.
+Buffer allocation uses chunks of memory having sizes 2^n * (page
+size). Because of this the actual buffer size may be larger than the
+minimum allowable buffer size.
+
+Asynchronous writing. Writing the buffer contents to the tape is
+started and the write call returns immediately. The status is checked
+at the next tape operation. Asynchronous writes are not done with
+direct i/o.
+
+Buffered writes and asynchronous writes may in some rare cases cause
+problems in multivolume operations if there is not enough space on the
+tape after the early-warning mark to flush the driver buffer.
+
+Read ahead for fixed block mode (ST_READ_AHEAD). Filling the buffer is
+attempted even if the user does not want to get all of the data at
+this read command. Should be disabled for those drives that don't like
+a filemark to truncate a read request or that don't like backspacing.
+
+The threshold for triggering asynchronous write in fixed block mode
+is defined by ST_WRITE_THRESHOLD. This may be optimized for each
+use pattern. The default triggers asynchronous write after three
+default sized writes (10 kB) from tar.
+
+Scatter/gather buffers (buffers that consist of chunks non-contiguous
+in the physical memory) are used if contiguous buffers can't be
+allocated. To support all SCSI adapters (including those not
+supporting scatter/gather), buffer allocation is using the following
+three kinds of chunks:
+1. The initial segment that is used for all SCSI adapters including
+those not supporting scatter/gather. The size of this buffer will be
+(PAGE_SIZE << ST_FIRST_ORDER) bytes if the system can give a chunk of
+this size (and it is not larger than the buffer size specified by
+ST_BUFFER_BLOCKS). If this size is not available, the driver halves
+the size and tries again until the size of one page. The default
+settings in st_options.h make the driver to try to allocate all of the
+buffer as one chunk.
+2. The scatter/gather segments to fill the specified buffer size are
+allocated so that as many segments as possible are used but the number
+of segments does not exceed ST_FIRST_SG.
+3. The remaining segments between ST_MAX_SG (or the module parameter
+max_sg_segs) and the number of segments used in phases 1 and 2
+are used to extend the buffer at run-time if this is necessary. The
+number of scatter/gather segments allowed for the SCSI adapter is not
+exceeded if it is smaller than the maximum number of scatter/gather
+segments specified. If the maximum number allowed for the SCSI adapter
+is smaller than the number of segments used in phases 1 and 2,
+extending the buffer will always fail.
+
+
+EOM BEHAVIOUR WHEN WRITING
+
+When the end of medium early warning is encountered, the current write
+is finished and the number of bytes is returned. The next write
+returns -1 and errno is set to ENOSPC. To enable writing a trailer,
+the next write is allowed to proceed and, if successful, the number of
+bytes is returned. After this, -1 and the number of bytes are
+alternately returned until the physical end of medium (or some other
+error) is encountered.
+
+
+MODULE PARAMETERS
+
+The buffer size, write threshold, and the maximum number of allocated buffers
+are configurable when the driver is loaded as a module. The keywords are:
+
+buffer_kbs=xxx             the buffer size for fixed block mode is set
+			   to xxx kilobytes
+write_threshold_kbs=xxx    the write threshold in kilobytes set to xxx
+max_sg_segs=xxx		   the maximum number of scatter/gather
+			   segments
+try_direct_io=x		   try direct transfer between user buffer and
+			   tape drive if this is non-zero
+
+Note that if the buffer size is changed but the write threshold is not
+set, the write threshold is set to the new buffer size - 2 kB.
+
+
+BOOT TIME CONFIGURATION
+
+If the driver is compiled into the kernel, the same parameters can be
+also set using, e.g., the LILO command line. The preferred syntax is
+to use the same keywords as when loading the driver as module. If
+several parameters are set, the keyword-value pairs are separated with
+a comma (no spaces allowed). A colon can be used instead of the equal
+mark. The definition is prepended by the string st=. Here is an
+example:
+
+	st=buffer_kbs:64,write_threhold_kbs:60
+
+The following syntax used by the old kernel versions is also supported:
+
+           st=aa[,bb[,dd]]
+
+where
+  aa is the buffer size for fixed block mode in 1024 byte units
+  bb is the write threshold in 1024 byte units
+  dd is the maximum number of scatter/gather segments
+
+
+IOCTLS
+
+The tape is positioned and the drive parameters are set with ioctls
+defined in mtio.h The tape control program 'mt' uses these ioctls. Try
+to find an mt that supports all of the Linux SCSI tape ioctls and
+opens the device for writing if the tape contents will be modified
+(look for a package mt-st* from the Linux ftp sites; the GNU mt does
+not open for writing for, e.g., erase).
+
+The supported ioctls are:
+
+The following use the structure mtop:
+
+MTFSF   Space forward over count filemarks. Tape positioned after filemark.
+MTFSFM  As above but tape positioned before filemark.
+MTBSF	Space backward over count filemarks. Tape positioned before
+        filemark.
+MTBSFM  As above but ape positioned after filemark.
+MTFSR   Space forward over count records.
+MTBSR   Space backward over count records.
+MTFSS   Space forward over count setmarks.
+MTBSS   Space backward over count setmarks.
+MTWEOF  Write count filemarks.
+MTWSM   Write count setmarks.
+MTREW   Rewind tape.
+MTOFFL  Set device off line (often rewind plus eject).
+MTNOP   Do nothing except flush the buffers.
+MTRETEN Re-tension tape.
+MTEOM   Space to end of recorded data.
+MTERASE Erase tape. If the argument is zero, the short erase command
+	is used. The long erase command is used with all other values
+	of the argument.
+MTSEEK	Seek to tape block count. Uses Tandberg-compatible seek (QFA)
+        for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and
+	block numbers in the status are not valid after a seek.
+MTSETBLK Set the drive block size. Setting to zero sets the drive into
+        variable block mode (if applicable).
+MTSETDENSITY Sets the drive density code to arg. See drive
+        documentation for available codes.
+MTLOCK and MTUNLOCK Explicitly lock/unlock the tape drive door.
+MTLOAD and MTUNLOAD Explicitly load and unload the tape. If the
+	command argument x is between MT_ST_HPLOADER_OFFSET + 1 and
+	MT_ST_HPLOADER_OFFSET + 6, the number x is used sent to the
+	drive with the command and it selects the tape slot to use of
+	HP C1553A changer.
+MTCOMPRESSION Sets compressing or uncompressing drive mode using the
+	SCSI mode page 15. Note that some drives other methods for
+	control of compression. Some drives (like the Exabytes) use
+	density codes for compression control. Some drives use another
+	mode page but this page has not been implemented in the
+	driver. Some drives without compression capability will accept
+	any compression mode without error.
+MTSETPART Moves the tape to the partition given by the argument at the
+	next tape operation. The block at which the tape is positioned
+	is the block where the tape was previously positioned in the
+	new active partition unless the next tape operation is
+	MTSEEK. In this case the tape is moved directly to the block
+	specified by MTSEEK. MTSETPART is inactive unless
+	MT_ST_CAN_PARTITIONS set.
+MTMKPART Formats the tape with one partition (argument zero) or two
+	partitions (the argument gives in megabytes the size of
+	partition 1 that is physically the first partition of the
+	tape). The drive has to support partitions with size specified
+	by the initiator. Inactive unless MT_ST_CAN_PARTITIONS set.
+MTSETDRVBUFFER
+	Is used for several purposes. The command is obtained from count
+        with mask MT_SET_OPTIONS, the low order bits are used as argument.
+	This command is only allowed for the superuser (root). The
+	subcommands are:
+	0
+           The drive buffer option is set to the argument. Zero means
+           no buffering.
+        MT_ST_BOOLEANS
+           Sets the buffering options. The bits are the new states
+           (enabled/disabled) the following options (in the
+	   parenthesis is specified whether the option is global or
+	   can be specified differently for each mode):
+	     MT_ST_BUFFER_WRITES write buffering (mode)
+	     MT_ST_ASYNC_WRITES asynchronous writes (mode)
+             MT_ST_READ_AHEAD  read ahead (mode)
+             MT_ST_TWO_FM writing of two filemarks (global)
+	     MT_ST_FAST_EOM using the SCSI spacing to EOD (global)
+	     MT_ST_AUTO_LOCK automatic locking of the drive door (global)
+             MT_ST_DEF_WRITES the defaults are meant only for writes (mode)
+	     MT_ST_CAN_BSR backspacing over more than one records can
+		be used for repositioning the tape (global)
+	     MT_ST_NO_BLKLIMS the driver does not ask the block limits
+		from the drive (block size can be changed only to
+		variable) (global)
+	     MT_ST_CAN_PARTITIONS enables support for partitioned
+		tapes (global)
+	     MT_ST_SCSI2LOGICAL the logical block number is used in
+		the MTSEEK and MTIOCPOS for SCSI-2 drives instead of
+		the device dependent address. It is recommended to set
+		this flag unless there are tapes using the device
+		dependent (from the old times) (global)
+	     MT_ST_SYSV sets the SYSV sematics (mode)
+	     MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
+	        the command to finish) for some commands (e.g., rewind)
+	     MT_ST_DEBUGGING debugging (global; debugging must be
+		compiled into the driver)
+	MT_ST_SETBOOLEANS
+	MT_ST_CLEARBOOLEANS
+	   Sets or clears the option bits.
+        MT_ST_WRITE_THRESHOLD
+           Sets the write threshold for this device to kilobytes
+           specified by the lowest bits.
+	MT_ST_DEF_BLKSIZE
+	   Defines the default block size set automatically. Value
+	   0xffffff means that the default is not used any more.
+	MT_ST_DEF_DENSITY
+	MT_ST_DEF_DRVBUFFER
+	   Used to set or clear the density (8 bits), and drive buffer
+	   state (3 bits). If the value is MT_ST_CLEAR_DEFAULT
+	   (0xfffff) the default will not be used any more. Otherwise
+	   the lowermost bits of the value contain the new value of
+	   the parameter.
+	MT_ST_DEF_COMPRESSION
+	   The compression default will not be used if the value of
+	   the lowermost byte is 0xff. Otherwise the lowermost bit
+	   contains the new default. If the bits 8-15 are set to a
+	   non-zero number, and this number is not 0xff, the number is
+	   used as the compression algorithm. The value
+	   MT_ST_CLEAR_DEFAULT can be used to clear the compression
+	   default.
+	MT_ST_SET_TIMEOUT
+	   Set the normal timeout in seconds for this device. The
+	   default is 900 seconds (15 minutes). The timeout should be
+	   long enough for the retries done by the device while
+	   reading/writing.
+	MT_ST_SET_LONG_TIMEOUT
+	   Set the long timeout that is used for operations that are
+	   known to take a long time. The default is 14000 seconds
+	   (3.9 hours). For erase this value is further multiplied by
+	   eight.
+	MT_ST_SET_CLN
+	   Set the cleaning request interpretation parameters using
+	   the lowest 24 bits of the argument. The driver can set the
+	   generic status bit GMT_CLN if a cleaning request bit pattern
+	   is found from the extended sense data. Many drives set one or
+	   more bits in the extended sense data when the drive needs
+	   cleaning. The bits are device-dependent. The driver is
+	   given the number of the sense data byte (the lowest eight
+	   bits of the argument; must be >= 18 (values 1 - 17
+	   reserved) and <= the maximum requested sense data sixe), 
+	   a mask to select the relevant bits (the bits 9-16), and the
+	   bit pattern (bits 17-23). If the bit pattern is zero, one
+	   or more bits under the mask indicate cleaning request. If
+	   the pattern is non-zero, the pattern must match the masked
+	   sense data byte.
+
+	   (The cleaning bit is set if the additional sense code and
+	   qualifier 00h 17h are seen regardless of the setting of
+	   MT_ST_SET_CLN.)
+
+The following ioctl uses the structure mtpos:
+MTIOCPOS Reads the current position from the drive. Uses
+        Tandberg-compatible QFA for SCSI-1 drives and the SCSI-2
+        command for the SCSI-2 drives.
+
+The following ioctl uses the structure mtget to return the status:
+MTIOCGET Returns some status information.
+        The file number and block number within file are returned. The
+        block is -1 when it can't be determined (e.g., after MTBSF).
+        The drive type is either MTISSCSI1 or MTISSCSI2.
+        The number of recovered errors since the previous status call
+        is stored in the lower word of the field mt_erreg.
+        The current block size and the density code are stored in the field
+        mt_dsreg (shifts for the subfields are MT_ST_BLKSIZE_SHIFT and
+        MT_ST_DENSITY_SHIFT).
+	The GMT_xxx status bits reflect the drive status. GMT_DR_OPEN
+	is set if there is no tape in the drive. GMT_EOD means either
+	end of recorded data or end of tape. GMT_EOT means end of tape.
+
+
+MISCELLANEOUS COMPILE OPTIONS
+
+The recovered write errors are considered fatal if ST_RECOVERED_WRITE_FATAL
+is defined.
+
+The maximum number of tape devices is determined by the define
+ST_MAX_TAPES. If more tapes are detected at driver initialization, the
+maximum is adjusted accordingly.
+
+Immediate return from tape positioning SCSI commands can be enabled by
+defining ST_NOWAIT. If this is defined, the user should take care that
+the next tape operation is not started before the previous one has
+finished. The drives and SCSI adapters should handle this condition
+gracefully, but some drive/adapter combinations are known to hang the
+SCSI bus in this case.
+
+The MTEOM command is by default implemented as spacing over 32767
+filemarks. With this method the file number in the status is
+correct. The user can request using direct spacing to EOD by setting
+ST_FAST_EOM 1 (or using the MT_ST_OPTIONS ioctl). In this case the file
+number will be invalid.
+
+When using read ahead or buffered writes the position within the file
+may not be correct after the file is closed (correct position may
+require backspacing over more than one record). The correct position
+within file can be obtained if ST_IN_FILE_POS is defined at compile
+time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl.
+(The driver always backs over a filemark crossed by read ahead if the
+user does not request data that far.)
+
+
+DEBUGGING HINTS
+
+To enable debugging messages, edit st.c and #define DEBUG 1. As seen
+above, debugging can be switched off with an ioctl if debugging is
+compiled into the driver. The debugging output is not voluminuous.
+
+If the tape seems to hang, I would be very interested to hear where
+the driver is waiting. With the command 'ps -l' you can see the state
+of the process using the tape. If the state is D, the process is
+waiting for something. The field WCHAN tells where the driver is
+waiting. If you have the current System.map in the correct place (in
+/boot for the procps I use) or have updated /etc/psdatabase (for kmem
+ps), ps writes the function name in the WCHAN field. If not, you have
+to look up the function from System.map.
+
+Note also that the timeouts are very long compared to most other
+drivers. This means that the Linux driver may appear hung although the
+real reason is that the tape firmware has got confused.
diff -Nru a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/sym53c8xx_2.txt	Sun Nov 17 20:30:03 2002
@@ -0,0 +1,1149 @@
+The Linux SYM-2 driver documentation file
+
+Written by Gerard Roudier <groudier@free.fr>
+21 Rue Carnot
+95170 DEUIL LA BARRE - FRANCE
+
+Decembre 28 2000
+===============================================================================
+
+1.  Introduction
+2.  Supported chips and SCSI features
+3.  Advantages of this driver for newer chips.
+      3.1 Optimized SCSI SCRIPTS
+      3.2 New features appeared with the SYM53C896
+4.  Memory mapped I/O versus normal I/O
+5.  Tagged command queueing
+6.  Parity checking
+7.  Profiling information
+8.  Control commands
+      8.1  Set minimum synchronous period
+      8.2  Set wide size
+      8.3  Set maximum number of concurrent tagged commands
+      8.4  Set debug mode
+      8.5  Set flag (no_disc)
+      8.6  Set verbose level
+      8.7  Reset all logical units of a target
+      8.8  Abort all tasks of all logical units of a target
+9.  Configuration parameters
+10. Boot setup commands
+      10.1 Syntax
+      10.2 Available arguments
+             10.2.1  Master parity checking
+             10.2.2  Scsi parity checking
+             10.2.3  Default number of tagged commands
+             10.2.4  Default synchronous period factor
+             10.2.5  Verbosity level
+             10.2.6  Debug mode
+             10.2.7  Burst max
+             10.2.8  LED support
+             10.2.9  Max wide
+             10.2.10 Differential mode
+             10.2.11 IRQ mode
+             10.2.12 Reverse probe
+             10.2.13 Fix up PCI configuration space
+             10.2.14 Serial NVRAM
+             10.2.15 Check SCSI BUS 
+             10.2.16 Exclude a host from being attached
+             10.2.17 Suggest a default SCSI id for hosts
+      10.3 PCI configuration fix-up boot option
+      10.4 Serial NVRAM support boot option
+      10.5 SCSI BUS checking boot option
+11. SCSI problem troubleshooting
+      15.1 Problem tracking
+      15.2 Understanding hardware error reports
+12. Serial NVRAM support (by Richard Waltham)
+      17.1 Features
+      17.2 Symbios NVRAM layout
+      17.3 Tekram  NVRAM layout
+
+===============================================================================
+
+1. Introduction
+
+This driver supports the whole SYM53C8XX family of PCI-SCSI controllers.
+It also support the subset of LSI53C10XX PCI-SCSI controllers that are based 
+on the SYM53C8XX SCRIPTS language.
+
+It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code 
+with the FreeBSD SYM-2 driver. The `glue' that allows this driver to work 
+under Linux is contained in 2 files named sym_glue.h and sym_glue.c.
+Other drivers files are intended not to depend on the Operating System 
+on which the driver is used.
+
+The history of this driver can be summerized as follows:
+
+1993: ncr driver written for 386bsd and FreeBSD by:
+          Wolfgang Stanglmeier        <wolf@cologne.de>
+          Stefan Esser                <se@mi.Uni-Koeln.de>
+
+1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx.
+          Gerard Roudier
+
+1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that 
+      adds full support for the 896 but drops support for early NCR devices.
+          Gerard Roudier
+
+1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010 
+      33 MHz and 66MHz Ultra-3 controllers. The new driver is named `sym'.
+          Gerard Roudier
+
+2000: Add support for early NCR devices to FreeBSD `sym' driver.
+      Break the driver into several sources and separate the OS glue 
+      code from the core code that can be shared among different O/Ses.
+      Write a glue code for Linux.
+          Gerard Roudier
+
+This README file addresses the Linux version of the driver. Under FreeBSD, 
+the driver documentation is the sym.8 man page.
+
+Information about new chips is available at LSILOGIC web server:
+
+          http://www.lsilogic.com/
+
+SCSI standard documentations are available at T10 site:
+
+          http://www.t10.org/
+
+Useful SCSI tools written by Eric Youngdale are part of most Linux 
+distributions:
+   scsiinfo:    command line tool
+   scsi-config: TCL/Tk tool using scsiinfo
+
+2. Supported chips and SCSI features
+
+The following features are supported for all chips:
+
+	Synchronous negotiation
+	Disconnection
+	Tagged command queuing
+	SCSI parity checking
+	PCI Master parity checking
+
+Other features depends on chip capabilities.
+The driver notably uses optimized SCRIPTS for devices that support 
+LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that 
+support the corresponding feature.
+
+The following table shows some characteristics of the chip family.
+
+       On board                                   LOAD/STORE   HARDWARE
+Chip   SDMS BIOS   Wide   SCSI std.   Max. sync   SCRIPTS      PHASE MISMATCH
+----   ---------   ----   ---------   ----------  ----------   --------------
+810        N         N      FAST10    10 MB/s        N             N
+810A       N         N      FAST10    10 MB/s        Y             N
+815        Y         N      FAST10    10 MB/s        N             N
+825        Y         Y      FAST10    20 MB/s        N             N
+825A       Y         Y      FAST10    20 MB/s        Y             N
+860        N         N      FAST20    20 MB/s        Y             N
+875        Y         Y      FAST20    40 MB/s        Y             N
+875A       Y         Y      FAST20    40 MB/s        Y             Y
+876        Y         Y      FAST20    40 MB/s        Y             N
+895        Y         Y      FAST40    80 MB/s        Y             N
+895A       Y         Y      FAST40    80 MB/s        Y             Y
+896        Y         Y      FAST40    80 MB/s        Y             Y
+897        Y         Y      FAST40    80 MB/s        Y             Y
+1510D      Y         Y      FAST40    80 MB/s        Y             Y
+1010       Y         Y      FAST80   160 MB/s        Y             Y
+1010_66*   Y         Y      FAST80   160 MB/s        Y             Y
+
+* Chip supports 33MHz and 66MHz PCI bus clock.
+
+
+Summary of other supported features:
+
+Module:                allow to load the driver
+Memory mapped I/O:     increases performance
+Control commands:      write operations to the proc SCSI file system
+Debugging information: written to syslog (expert only)
+Scatter / gather
+Shared interrupt
+Boot setup commands
+Serial NVRAM:          Symbios and Tekram formats
+
+
+3. Advantages of this driver for newer chips.
+
+3.1 Optimized SCSI SCRIPTS.
+
+All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions 
+named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register 
+to/from memory much faster that the MOVE MEMORY instruction that is supported 
+by the 53c7xx and 53c8xx family.
+
+The LOAD/STORE instructions support absolute and DSA relative addressing 
+modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead 
+of MOVE MEMORY instructions.
+
+Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this 
+driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in 
+order to provide support for the entire SYM53C8XX chips family.
+
+3.2 New features appeared with the SYM53C896
+
+Newer chips (see above) allows handling of the phase mismatch context from 
+SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor 
+until the C code has saved the context of the transfer).
+
+The 896 and 1010 chips support 64 bit PCI transactions and addressing, 
+while the 895A supports 32 bit PCI transactions and 64 bit addressing.
+The SCRIPTS processor of these chips is not true 64 bit, but uses segment 
+registers for bit 32-63. Another interesting feature is that LOAD/STORE 
+instructions that address the on-chip RAM (8k) remain internal to the chip.
+
+4. Memory mapped I/O versus normal I/O
+
+Memory mapped I/O has less latency than normal I/O and is the recommended 
+way for doing IO with PCI devices. Memory mapped I/O seems to work fine on 
+most hardware configurations, but some poorly designed chipsets may break 
+this feature. A configuration option is provided for normal I/O to be 
+used but the driver defaults to MMIO.
+
+5. Tagged command queueing
+
+Queuing more than 1 command at a time to a device allows it to perform 
+optimizations based on actual head positions and its mechanical 
+characteristics. This feature may also reduce average command latency.
+In order to really gain advantage of this feature, devices must have 
+a reasonnable cache size (No miracle is to be expected for a low-end 
+hard disk with 128 KB or less).
+Some kown old SCSI devices do not properly support tagged command queuing.
+Generally, firmware revisions that fix this kind of problems are available 
+at respective vendor web/ftp sites.
+All I can say is that I never have had problem with tagged queuing using 
+this driver and its predecessors. Hard disks that behaved correctly for 
+me using tagged commands are the following:
+
+- IBM S12 0662
+- Conner 1080S
+- Quantum Atlas I
+- Quantum Atlas II
+- Seagate Cheetah I
+- Quantum Viking II
+- IBM DRVS
+- Quantum Atlas IV
+- Seagate Cheetah II
+
+If your controller has NVRAM, you can configure this feature per target 
+from the user setup tool. The Tekram Setup program allows to tune the 
+maximum number of queued commands up to 32. The Symbios Setup only allows 
+to enable or disable this feature.
+
+The maximum number of simultaneous tagged commands queued to a device
+is currently set to 16 by default.  This value is suitable for most SCSI
+disks.  With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
+<= 10 ms), using a larger value may give better performances.
+
+This driver supports up to 255 commands per device, and but using more than 
+64 is generally not worth-while, unless you are using a very large disk or 
+disk arrays. It is noticeable that most of recent hard disks seem not to 
+accept more than 64 simultaneous commands. So, using more than 64 queued 
+commands is probably just resource wasting.
+
+If your controller does not have NVRAM or if it is managed by the SDMS 
+BIOS/SETUP, you can configure tagged queueing feature and device queue 
+depths from the boot command-line. For example:
+
+  sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32
+
+will set tagged commands queue depths as follow:
+
+- target 2  all luns  on controller 0 --> 15
+- target 3  all luns  on controller 0 --> 15
+- target 4  all luns  on controller 0 -->  7
+- target 1  lun 0     on controller 1 --> 32
+- all other target/lun                -->  4
+
+In some special conditions, some SCSI disk firmwares may return a
+QUEUE FULL status for a SCSI command. This behaviour is managed by the
+driver using the following heuristic:
+
+- Each time a QUEUE FULL status is returned, tagged queue depth is reduced 
+  to the actual number of disconnected commands. 
+
+- Every 200 successfully completed SCSI commands, if allowed by the
+  current limit, the maximum number of queueable commands is incremented.
+
+Since QUEUE FULL status reception and handling is resource wasting, the 
+driver notifies by default this problem to user by indicating the actual 
+number of commands used and their status, as well as its decision on the 
+device queue depth change.
+The heuristic used by the driver in handling QUEUE FULL ensures that the 
+impact on performances is not too bad. You can get rid of the messages by 
+setting verbose level to zero, as follow:
+
+1st method: boot your system using 'sym53c8xx=verb:0' option.
+2nd method: apply "setverbose 0" control command to the proc fs entry 
+            corresponding to your controller after boot-up.
+
+6. Parity checking
+
+The driver supports SCSI parity checking and PCI bus master parity
+checking. These features must be enabled in order to ensure safe data
+transfers. However, some flawed devices or mother boards will have
+problems with parity. You can disable either PCI parity or SCSI parity 
+checking by entering appropriate options from the boot command line.
+(See 10: Boot setup commands).
+
+7. Profiling information
+
+This driver does not provide profiling informations as did its predecessors.
+This feature was not this useful and added complexity to the code. 
+As the driver code got more complex, I have decided to remove everything 
+that didn't seem actually useful.
+
+8. Control commands
+
+Control commands can be sent to the driver with write operations to
+the proc SCSI file system. The generic command syntax is the
+following:
+
+      echo "<verb> <parameters>" >/proc/scsi/sym53c8xx/0
+      (assumes controller number is 0)
+
+Using "all" for "<target>" parameter with the commands below will
+apply to all targets of the SCSI chain (except the controller).
+
+Available commands:
+
+8.1 Set minimum synchronous period factor
+
+    setsync <target> <period factor>
+
+    target:    target number
+    period:    minimum synchronous period.
+               Maximum speed = 1000/(4*period factor) except for special
+               cases below.
+
+    Specify a period of 0, to force asynchronous transfer mode.
+
+       9 means 12.5 nano-seconds synchronous period
+      10 means 25 nano-seconds synchronous period
+      11 means 30 nano-seconds synchronous period
+      12 means 50 nano-seconds synchronous period
+
+8.2 Set wide size
+
+    setwide <target> <size>
+
+    target:    target number
+    size:      0=8 bits, 1=16bits
+
+8.3 Set maximum number of concurrent tagged commands
+ 
+    settags <target> <tags>
+
+    target:    target number
+    tags:      number of concurrent tagged commands
+               must not be greater than configured (default: 16)
+
+8.4 Set debug mode
+
+    setdebug <list of debug flags>
+
+    Available debug flags:
+        alloc:   print info about memory allocations (ccb, lcb)
+        queue:   print info about insertions into the command start queue
+        result:  print sense data on CHECK CONDITION status
+        scatter: print info about the scatter process
+        scripts: print info about the script binding process
+	tiny:    print minimal debugging information
+	timing:  print timing information of the NCR chip
+	nego:    print information about SCSI negotiations
+	phase:   print information on script interruptions
+
+    Use "setdebug" with no argument to reset debug flags.
+
+
+8.5 Set flag (no_disc)
+ 
+    setflag <target> <flag>
+
+    target:    target number
+
+    For the moment, only one flag is available:
+
+        no_disc:   not allow target to disconnect.
+
+    Do not specify any flag in order to reset the flag. For example:
+    - setflag 4
+      will reset no_disc flag for target 4, so will allow it disconnections.
+    - setflag all
+      will allow disconnection for all devices on the SCSI bus.
+
+
+8.6 Set verbose level
+
+    setverbose #level
+
+    The driver default verbose level is 1. This command allows to change 
+    th driver verbose level after boot-up.
+
+8.7 Reset all logical units of a target
+
+    resetdev <target>
+
+    target:    target number
+    The driver will try to send a BUS DEVICE RESET message to the target.
+
+8.8 Abort all tasks of all logical units of a target
+
+    cleardev <target>
+
+    target:    target number
+    The driver will try to send a ABORT message to all the logical units 
+    of the target.
+
+
+9. Configuration parameters
+
+Under kernel configuration tools (make menuconfig, for example), it is 
+possible to change some default driver configuration parameters.
+If the firmware of all your devices is perfect enough, all the
+features supported by the driver can be enabled at start-up. However,
+if only one has a flaw for some SCSI feature, you can disable the
+support by the driver of this feature at linux start-up and enable
+this feature after boot-up only for devices that support it safely.
+
+Configuration parameters:
+
+Use normal IO                         (default answer: n)
+    Answer "y" if you suspect your mother board to not allow memory mapped I/O.
+    May slow down performance a little.
+
+Default tagged command queue depth    (default answer: 16)
+    Entering 0 defaults to tagged commands not being used.
+    This parameter can be specified from the boot command line.
+
+Maximum number of queued commands     (default answer: 32)
+    This option allows you to specify the maximum number of tagged commands 
+    that can be queued to a device. The maximum supported value is 255.
+
+Synchronous transfers frequency       (default answer: 80)
+    This option allows you to specify the frequency in MHz the driver 
+    will use at boot time for synchronous data transfer negotiations.
+    0 means "asynchronous data transfers".
+
+10. Boot setup commands
+
+10.1 Syntax
+
+Setup commands can be passed to the driver either at boot time or as a 
+string variable using 'insmod'.
+
+A boot setup command for this driver begins with the driver name "sym53c8xx=".
+The kernel syntax parser then expects an optionnal list of integers separated 
+with comma followed by an optional list of  comma-separated strings.
+
+Example of boot setup command under lilo prompt:
+
+lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
+
+- enable tagged commands, up to 4 tagged commands queued.
+- set synchronous negotiation speed to 10 Mega-transfers / second.
+- set DEBUG_NEGO flag.
+
+Since comma seems not to be allowed when defining a string variable using  
+'insmod', the driver also accepts <space> as option separator. 
+The following command will install driver module with the same options as 
+above.
+
+    insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200"
+
+The integer list of arguments is discarded by the driver. 
+
+Each string argument must be specified as "keyword:value". Only lower-case 
+characters and digits are allowed.
+
+10.2 Available arguments
+
+10.2.1  Master parity checking
+        mpar:y     enabled
+        mpar:n     disabled
+
+10.2.2  Scsi parity checking
+        spar:y     enabled
+        spar:n     disabled
+
+10.2.3  Default number of tagged commands
+        tags:0     (or tags:1 ) tagged command queuing disabled
+        tags:#tags (#tags  > 1) tagged command queuing enabled
+  #tags will be truncated to the max queued commands configuration parameter.
+  This option also allows to specify a command queue depth for each device 
+  that support tagged command queueing.
+  Example:
+      sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
+               will set devices queue depth as follow:
+      - controller #0 target #2 and target #3                  -> 16 commands,
+      - controller #0 target #5                                -> 24 commands,
+      - controller #1 target #1 logical unit #2                -> 32 commands,
+      - all other logical units (all targets, all controllers) -> 10 commands.
+
+10.2.4  Default synchronous period factor
+        sync:255     disabled (asynchronous transfer mode)
+        sync:#factor
+  #factor =  9     Ultra-3 SCSI 80 Mega-transfers / second (Wide only)
+  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
+  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
+  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
+  #factor < 50     Fast    SCSI-2
+
+  In all cases, the driver will use the minimum transfer period supported by 
+  controllers according to SYM53C8XX chip type.
+
+10.2.5  Verbosity level
+        verb:0     minimal
+        verb:1     normal
+        verb:2     too much
+
+10.2.6 Debug mode
+        debug:0	 clear debug flags
+        debug:#x   set debug flags
+  #x is an integer value combining the following power-of-2 values:
+  DEBUG_ALLOC       0x1
+  DEBUG_PHASE       0x2
+  DEBUG_POLL        0x4
+  DEBUG_QUEUE       0x8
+  DEBUG_RESULT     0x10
+  DEBUG_SCATTER    0x20
+  DEBUG_SCRIPT     0x40
+  DEBUG_TINY       0x80
+  DEBUG_TIMING    0x100
+  DEBUG_NEGO      0x200
+  DEBUG_TAGS      0x400
+  DEBUG_FREEZE    0x800
+  DEBUG_RESTART  0x1000
+
+  You can play safely with DEBUG_NEGO. However, some of these flags may 
+  generate bunches of syslog messages. 
+
+10.2.7 Burst max
+        burst:0    burst disabled
+        burst:255  get burst length from initial IO register settings.
+        burst:#x   burst enabled (1<<#x burst transfers max)
+  #x is an integer value which is log base 2 of the burst transfers max.
+  By default the driver uses the maximum value supported by the chip.
+
+10.2.8 LED support
+        led:1      enable  LED support
+        led:0      disable LED support
+  Donnot enable LED support if your scsi board does not use SDMS BIOS.
+  (See 'Configuration parameters')
+
+10.2.9 Max wide
+        wide:1      wide scsi enabled
+        wide:0      wide scsi disabled
+  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
+  If you have connected a wide device with a 50 pins to 68 pins cable 
+  converter, any accepted wide negotiation will break further data transfers.
+  In such a case, using "wide:0" in the bootup command will be helpfull. 
+
+10.2.10 Differential mode
+        diff:0	never set up diff mode
+        diff:1	set up diff mode if BIOS set it
+        diff:2	always set up diff mode
+        diff:3	set diff mode if GPIO3 is not set
+
+10.2.11 IRQ mode
+        irqm:0     always open drain
+        irqm:1     same as initial settings (assumed BIOS settings)
+        irqm:2     always totem pole
+
+10.2.12 Reverse probe
+        revprob:n   probe chip ids from the PCI configuration in this order:
+                    810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A,
+                    1510D, 1010-33, 1010-66.
+        revprob:y   probe chip ids in the reverse order.
+
+10.2.13 Fix up PCI configuration space
+        pcifix:<option bits>
+
+    Available option bits:
+        0x0:   No attempt to fix PCI configuration space registers values.
+        0x1:   Set PCI cache-line size register if not set.
+        0x2:   Set write and invalidate bit in PCI command register.
+
+10.2.14 Serial NVRAM
+        nvram:n     do not look for serial NVRAM
+        nvram:y     test controllers for onboard serial NVRAM
+        (alternate binary form)
+        mvram=<bits options>
+        0x01   look for NVRAM  (equivalent to nvram=y)
+        0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
+        0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
+        0x08   ignore NVRAM "Scan at boot time" parameter for all devices
+        0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+10.2.15 Check SCSI BUS 
+        buschk:<option bits>
+
+    Available option bits:
+        0x0:   No check.
+        0x1:   Check and donnot attach the controller on error.  
+        0x2:   Check and just warn on error.
+
+10.2.16 Exclude a host from being attached
+        excl=<io_address>
+
+    Prevent host at a given io address from being attached.
+    For example 'sym53c8xx=excl:0xb400,excl:0xc000' indicate to the 
+    driver not to attach hosts at address 0xb400 and 0xc000.
+
+10.2.17 Suggest a default SCSI id for hosts
+        hostid:255	no id suggested.
+        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
+
+    If a host SCSI id is available from the NVRAM, the driver will ignore 
+    any value suggested as boot option. Otherwise, if a suggested value 
+    different from 255 has been supplied, it will use it. Otherwise, it will 
+    try to deduce the value previously set in the hardware and use value 
+    7 if the hardware value is zero.
+
+10.3 PCI configuration fix-up boot option
+
+pcifix:<option bits>
+
+Available option bits:
+    0x1:     Set PCI cache-line size register if not set.
+    0x2:     Set write and invalidate bit in PCI command register.
+
+Use 'pcifix:3' in order to allow the driver to fix both PCI features.
+
+Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
+and PCI write and invalidate commands. These features require the 
+cache line size register to be properly set in the PCI configuration 
+space of the chips. On the other hand, chips will use PCI write and 
+invalidate commands only if the corresponding bit is set to 1 in the 
+PCI command register.
+
+Not all PCI bioses set the PCI cache line register and the PCI write and 
+invalidate bit in the PCI configuration space of 53C8XX chips.
+Optimized PCI accesses may be broken for some PCI/memory controllers or 
+make problems with some PCI boards.
+
+10.4 Serial NVRAM support boot option
+
+nvram:n     do not look for serial NVRAM
+nvram:y     test controllers for onboard serial NVRAM
+
+This option can also been entered as an hexadecimal value that allows 
+to control what information the driver will get from the NVRAM and what 
+information it will ignore.
+For details see '17. Serial NVRAM support'.
+
+When this option is enabled, the driver tries to detect all boards using 
+a Serial NVRAM. This memory is used to hold user set up parameters.
+
+The parameters the driver is able to get from the NVRAM depend on the 
+data format used, as follow:
+
+                                 Tekram format      Symbios format
+General and host parameters
+    Boot order                         N                   Y
+    Host SCSI ID                       Y                   Y
+    SCSI parity checking               Y                   Y
+    Verbose boot messages              N                   Y
+SCSI devices parameters
+    Synchronous transfer speed         Y                   Y
+    Wide 16 / Narrow                   Y                   Y
+    Tagged Command Queuing enabled     Y                   Y
+    Disconnections enabled             Y                   Y
+    Scan at boot time                  N                   Y
+
+In order to speed up the system boot, for each device configured without 
+the "scan at boot time" option, the driver forces an error on the 
+first TEST UNIT READY command received for this device.
+
+Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
+hard disks. In such a situation you cannot configure the NVRAM with 
+optimized parameters value.
+
+The 'nvram' boot option can be entered in hexadecimal form in order 
+to ignore some options configured in the NVRAM, as follow:
+
+mvram=<bits options>
+      0x01   look for NVRAM  (equivalent to nvram=y)
+      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
+      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
+      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
+      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
+
+Option 0x80 is disabled by default.
+Result is that, by default (option not set), the sym53c8xx driver will not 
+attach controllers set to OFF in the NVRAM.
+
+10.5 SCSI BUS checking boot option.
+
+When this option is set to a non-zero value, the driver checks SCSI lines 
+logic state, 100 micro-seconds after having asserted the SCSI RESET line.
+The driver just reads SCSI lines and checks all lines read FALSE except RESET.
+Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI 
+RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
+Unfortunately, the following common SCSI BUS problems are not detected:
+- Only 1 terminator installed.
+- Misplaced terminators.
+- Bad quality terminators.
+On the other hand, either bad cabling, broken devices, not conformant 
+devices, ... may cause a SCSI signal to be wrong when te driver reads it.
+
+15. SCSI problem troubleshooting
+
+15.1 Problem tracking
+
+Most SCSI problems are due to a non conformant SCSI bus or too buggy
+devices.  If infortunately you have SCSI problems, you can check the
+following things:
+
+- SCSI bus cables
+- terminations at both end of the SCSI chain
+- linux syslog messages (some of them may help you)
+
+If you donnot find the source of problems, you can configure the
+driver or devices in the NVRAM with minimal features.
+
+- only asynchronous data transfers
+- tagged commands disabled
+- disconnections not allowed
+
+Now, if your SCSI bus is ok, your system has every chance to work
+with this safe configuration but performances will not be optimal.
+
+If it still fails, then you can send your problem description to
+appropriate mailing lists or news-groups.  Send me a copy in order to
+be sure I will receive it.  Obviously, a bug in the driver code is
+possible.
+
+  My cyrrent email address: Gerard Roudier <groudier@free.fr>
+
+Allowing disconnections is important if you use several devices on
+your SCSI bus but often causes problems with buggy devices.
+Synchronous data transfers increases throughput of fast devices like
+hard disks.  Good SCSI hard disks with a large cache gain advantage of
+tagged commands queuing.
+
+15.2 Understanding hardware error reports
+
+When the driver detects an unexpected error condition, it may display a 
+message of the following pattern.
+
+sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
+sym0: script cmd = 19000000
+sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.
+
+Some fields in such a message may help you understand the cause of the 
+problem, as follows:
+
+sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
+.....A.........B.C....D.E..F....G.H..I.......J.....K...L.......
+
+Field A : target number.
+  SCSI ID of the device the controller was talking with at the moment the 
+  error occurs.
+
+Field B : DSTAT io register (DMA STATUS)
+  Bit 0x40 : MDPE Master Data Parity Error
+             Data parity error detected on the PCI BUS.
+  Bit 0x20 : BF   Bus Fault
+             PCI bus fault condition detected
+  Bit 0x01 : IID  Illegal Instruction Detected
+             Set by the chip when it detects an Illegal Instruction format 
+             on some condition that makes an instruction illegal.
+  Bit 0x80 : DFE Dma Fifo Empty
+             Pure status bit that does not indicate an error.
+  If the reported DSTAT value contains a combination of MDPE (0x40), 
+  BF (0x20), then the cause may be likely due to a PCI BUS problem.
+
+Field C : SIST io register (SCSI Interrupt Status)
+  Bit 0x08 : SGE  SCSI GROSS ERROR
+             Indicates that the chip detected a severe error condition 
+             on the SCSI BUS that prevents the SCSI protocol from functionning
+             properly.
+  Bit 0x04 : UDC  Undexpected Disconnection
+             Indicates that the device released the SCSI BUS when the chip 
+             was not expecting this to happen. A device may behave so to 
+             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occured.
+  Bit 0x02 : RST  SCSI BUS Reset
+             Generally SCSI targets donnot reset the SCSI BUS, although any 
+             device on the BUS can reset it at any time.
+  Bit 0x01 : PAR  Parity
+             SCSI parity error detected.
+  On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and 
+  PAR (0x01) may be detected by the chip. If your SCSI system sometimes 
+  encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI 
+  BUS problem is likely the cause of these errors.
+
+For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file 
+that contains some minimal comments on IO register bits.
+Field D : SOCL  Scsi Output Control Latch
+          This register reflects the state of the SCSI control lines the 
+          chip want to drive or compare against.
+Field E : SBCL  Scsi Bus Control Lines
+          Actual value of control lines on the SCSI BUS.
+Field F : SBDL  Scsi Bus Data Lines
+          Actual value of data lines on the SCSI BUS.
+Field G : SXFER  SCSI Transfer
+          Contains the setting of the Synchronous Period for output and 
+          the current Synchronous offset (offset 0 means asynchronous).
+Field H : SCNTL3 Scsi Control Register 3
+          Contains the setting of timing values for both asynchronous and 
+          synchronous data transfers. 
+Field I : SCNTL4 Scsi Control Register 4
+          Only meaninful for 53C1010 Ultra3 controllers.
+
+Understanding Fields J, K, L and dumps requires to have good knowledge of 
+SCSI standards, chip cores functionnals and internal driver data structures.
+You are not required to decode and understand them, unless you want to help 
+maintain the driver code.
+
+17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk)
+
+17.1 Features
+
+Enabling serial NVRAM support enables detection of the serial NVRAM included
+on Symbios and some Symbios compatible host adaptors, and Tekram boards. The 
+serial NVRAM is used by Symbios and Tekram to hold set up parameters for the 
+host adaptor and it's attached drives.
+
+The Symbios NVRAM also holds data on the boot order of host adaptors in a
+system with more than one host adaptor. This enables the order of scanning
+the cards for drives to be changed from the default used during host adaptor
+detection.
+
+This can be done to a limited extent at the moment using "reverse probe" but
+this only changes the order of detection of different types of cards. The
+NVRAM boot order settings can do this as well as change the order the same
+types of cards are scanned in, something "reverse probe" cannot do.
+
+Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
+and this is used to distinguish between Symbios compatible and Tekram host 
+adaptors. This is used to disable the Symbios compatible "diff" setting
+incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT 
+configuration parameter is set enabling both Symbios and Tekram boards to be 
+used together with the Symbios cards using all their features, including
+"diff" support. ("led pin" support for Symbios compatible cards can remain
+enabled when using Tekram cards. It does nothing useful for Tekram host
+adaptors but does not cause problems either.)
+
+
+17.2 Symbios NVRAM layout
+
+typical data at NVRAM address 0x100 (53c810a NVRAM)
+-----------------------------------------------------------
+00 00
+64 01
+8e 0b
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62 
+04 00 03 00 00 10 00 58 00 00 01 00 00 63 
+04 00 01 00 00 10 00 48 00 00 01 00 00 61 
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+
+0f 00 08 08 64 00 0a 00
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 
+
+fe fe
+00 00
+00 00
+-----------------------------------------------------------
+NVRAM layout details
+
+NVRAM Address 0x000-0x0ff not used
+              0x100-0x26f initialised data
+              0x270-0x7ff not used
+
+general layout
+
+        header  -   6 bytes,
+        data    - 356 bytes (checksum is byte sum of this data)
+        trailer -   6 bytes
+                  ---
+        total     368 bytes
+
+data area layout
+
+        controller set up  -  20 bytes
+        boot configuration -  56 bytes (4x14 bytes)
+        device set up      - 128 bytes (16x8 bytes)
+        unused (spare?)    - 152 bytes (19x8 bytes)
+                             ---
+        total                356 bytes
+
+-----------------------------------------------------------
+header
+
+00 00   - ?? start marker
+64 01   - byte count (lsb/msb excludes header/trailer)
+8e 0b   - checksum (lsb/msb excludes header/trailer)
+-----------------------------------------------------------
+controller set up
+
+00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
+                   |     |           |     |
+                   |     |           |      -- host ID
+                   |     |           |
+                   |     |            --Removable Media Support
+                   |     |               0x00 = none
+                   |     |               0x01 = Bootable Device
+                   |     |               0x02 = All with Media
+                   |     |
+                   |      --flag bits 2
+                   |        0x00000001= scan order hi->low
+                   |            (default 0x00 - scan low->hi)
+                    --flag bits 1
+                       0x00000001 scam enable
+                       0x00000010 parity enable
+                       0x00000100 verbose boot msgs
+
+remaining bytes unknown - they do not appear to change in my
+current set up for any of the controllers.
+
+default set up is identical for 53c810a and 53c875 NVRAM
+(Removable Media added Symbios BIOS version 4.09)
+-----------------------------------------------------------
+boot configuration
+
+boot order set by order of the devices in this table
+
+04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
+04 00 03 00 00 10 00 58 00 00 01 00 00 63    2nd controller
+04 00 01 00 00 10 00 48 00 00 01 00 00 61    3rd controller
+00 00 00 00 00 00 00 00 00 00 00 00 00 00    4th controller
+       |  |  |  |     |        |     |  |
+       |  |  |  |     |        |      ---- PCI io port adr
+       |  |  |  |     |         --0x01 init/scan at boot time
+       |  |  |  |      --PCI device/function number (0xdddddfff)
+       |  |   ----- ?? PCI vendor ID (lsb/msb)
+        ----PCI device ID (lsb/msb)
+
+?? use of this data is a guess but seems reasonable
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+device set up (up to 16 devices - includes controller)
+
+0f 00 08 08 64 00 0a 00 - id 0
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 
+0f 00 08 08 64 00 0a 00 - id 15
+ |     |  |  |     |  |
+ |     |  |  |      ----timeout (lsb/msb)
+ |     |  |   --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
+ |     |  |                  (0x30 20 Mtrans/sec- fast 20)
+ |     |  |                  (0x64 10 Mtrans/sec- fast )
+ |     |  |                  (0xc8  5 Mtrans/sec)
+ |     |  |                  (0x00  asynchronous)
+ |     |   -- ?? max sync offset (0x08 in NVRAM on 53c810a) 
+ |     |                         (0x10 in NVRAM on 53c875)
+ |      --device bus width (0x08 narrow)
+ |                         (0x10 16 bit wide)
+  --flag bits
+    0x00000001 - disconnect enabled
+    0x00000010 - scan at boot time
+    0x00000100 - scan luns
+    0x00001000 - queue tags enabled
+
+remaining bytes unknown - they do not appear to change in my
+current set up
+
+?? use of this data is a guess but seems reasonable 
+(but it could be max bus width)
+
+default set up for 53c810a NVRAM
+default set up for 53c875 NVRAM - bus width     - 0x10
+                                - sync offset ? - 0x10
+                                - sync period   - 0x30
+-----------------------------------------------------------
+?? spare device space (32 bit bus ??)
+
+00 00 00 00 00 00 00 00  (19x8bytes)
+.
+.
+00 00 00 00 00 00 00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+trailer
+
+fe fe   - ? end marker ?
+00 00
+00 00
+
+default set up is identical for 53c810a and 53c875 NVRAM
+-----------------------------------------------------------
+
+
+
+17.3 Tekram NVRAM layout
+
+nvram 64x16 (1024 bit)
+
+Drive settings
+
+Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
+              (addr 0x0yyyy1 = 0x0000)
+
+    x x x x  x x x x  x x x x  x x x x
+               | | |      | |  | | | |
+               | | |      | |  | | |  ----- parity check   0 - off
+               | | |      | |  | | |                       1 - on
+               | | |      | |  | | |
+               | | |      | |  | |  ------- sync neg       0 - off
+               | | |      | |  | |                         1 - on
+               | | |      | |  | |
+               | | |      | |  |  --------- disconnect     0 - off
+               | | |      | |  |                           1 - on
+               | | |      | |  |
+               | | |      | |   ----------- start cmd      0 - off
+               | | |      | |                              1 - on
+               | | |      | |
+               | | |      |  -------------- tagged cmds    0 - off
+               | | |      |                                1 - on
+               | | |      | 
+               | | |       ---------------- wide neg       0 - off
+               | | |                                       1 - on
+               | | |
+                --------------------------- sync rate      0 - 10.0 Mtrans/sec
+                                                           1 -  8.0
+                                                           2 -  6.6
+                                                           3 -  5.7
+                                                           4 -  5.0
+                                                           5 -  4.0
+                                                           6 -  3.0
+                                                           7 -  2.0
+                                                           7 -  2.0
+                                                           8 - 20.0
+                                                           9 - 16.7
+                                                           a - 13.9
+                                                           b - 11.9
+
+Global settings
+
+Host flags 0 (addr 0x100000, 32) 
+
+    x x x x  x x x x  x x x x  x x x x
+    | | | |  | | | |           | | | |
+    | | | |  | | | |            ----------- host ID    0x00 - 0x0f
+    | | | |  | | | |
+    | | | |  | | |  ----------------------- support for    0 - off
+    | | | |  | | |                          > 2 drives     1 - on
+    | | | |  | | | 
+    | | | |  | |  ------------------------- support drives 0 - off
+    | | | |  | |                            > 1Gbytes      1 - on
+    | | | |  | |
+    | | | |  |  --------------------------- bus reset on   0 - off
+    | | | |  |                                power on     1 - on
+    | | | |  |
+    | | | |   ----------------------------- active neg     0 - off
+    | | | |                                                1 - on
+    | | | |
+    | | |  -------------------------------- imm seek       0 - off
+    | | |                                                  1 - on
+    | | |
+    | |  ---------------------------------- scan luns      0 - off
+    | |                                                    1 - on
+    | |
+     -------------------------------------- removable      0 - disable
+                                            as BIOS dev    1 - boot device
+                                                           2 - all
+
+Host flags 1 (addr 0x100001, 33)
+
+    x x x x  x x x x  x x x x  x x x x
+               | | |             | | | 
+               | | |              --------- boot delay     0 -   3 sec
+               | | |                                       1 -   5
+               | | |                                       2 -  10
+               | | |                                       3 -  20
+               | | |                                       4 -  30
+               | | |                                       5 -  60
+               | | |                                       6 - 120
+               | | |
+                --------------------------- max tag cmds   0 -  2
+                                                           1 -  4
+                                                           2 -  8
+                                                           3 - 16
+                                                           4 - 32
+
+Host flags 2 (addr 0x100010, 34)
+
+    x x x x  x x x x  x x x x  x x x x
+                                     |
+                                      ----- F2/F6 enable   0 - off ???
+                                                           1 - on  ???
+
+checksum (addr 0x111111)
+
+checksum = 0x1234 - (sum addr 0-63)
+
+----------------------------------------------------------------------------
+
+default nvram data:
+
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
+0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 
+
+0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc
+
+
+===============================================================================
+End of Linux SYM-2 driver documentation file
diff -Nru a/Documentation/scsi/tmscsim.txt b/Documentation/scsi/tmscsim.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/scsi/tmscsim.txt	Sun Nov 17 20:30:14 2002
@@ -0,0 +1,449 @@
+The tmscsim driver
+==================
+
+1. Purpose and history
+2. Installation
+3. Features
+4. Configuration via /proc/scsi/tmscsim/?
+5. Configuration via boot/module params
+6. Potential improvements
+7. Bug reports, debugging and updates
+8. Acknowledgements
+9. Copyright
+
+
+1. Purpose and history
+----------------------
+The tmscsim driver supports PCI SCSI Host Adapters based on the AM53C974
+chip. AM53C974 based SCSI adapters include: 
+ Tekram DC390, DC390T
+ Dawicontrol 2974
+ QLogic Fast! PCI Basic
+ some on-board adapters
+(This is most probably not a complete list)
+
+It has originally written by C.L. Huang from the Tekram corp. to support the
+Tekram DC390(T) adapter. This is where the name comes from: tm = Tekram
+scsi = SCSI driver, m = AMD (?) as opposed to w for the DC390W/U/F
+(NCR53c8X5, X=2/7) driver. Yes, there was also a driver for the latter,
+tmscsiw, which supported DC390W/U/F adapters. It's not maintained any more,
+as the ncr53c8xx is perfectly supporting these adpaters since some time.
+
+The driver first appeared in April 1996, exclusively supported the DC390 
+and has been enhanced since then in various steps. In May 1998 support for 
+general AM53C974 based adapters and some possibilities to configure it were
+added. The non-DC390 support works by assuming some values for the data
+normally taken from the DC390 EEPROM. See below (chapter 5) for details.
+
+When using the DC390, the configuration is still be done using the DC390
+BIOS setup. The DC390 EEPROM is read and used by the driver, any boot or
+module parameters (chapter 5) are ignored! However, you can change settings
+dynamically, as described in chapter 4. 
+
+For a more detailed description of the driver's history, see the first lines
+of tmscsim.c.
+The numbering scheme isn't consistent. The first versions went from 1.00 to
+1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So
+the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental),
+2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send
+fixes to people for testing, I create intermediate versions with a digit 
+appended, e.g. 2.0c3.
+
+
+2. Installation
+---------------
+If you got any recent kernel with this driver and document included in
+linux/drivers/scsi, you basically have to do nothing special to use this
+driver. Of course you have to choose to compile SCSI support and DC390(T)
+support into your kernel or as module when configuring your kernel for
+compiling.
+NEW: You may as well compile this module outside your kernel, using the
+supplied Makefile.
+
+ If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of
+ this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from
+ my web page and apply the patch. Apply further patches to upgrade to the 
+ latest version of the driver.
+
+ If you want to do it manually, you should copy the files (dc390.h,
+ tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to
+ linux/drivers/scsi. You have to recompile your kernel/module of course.
+
+ You should apply the three patches included in dc390-120-kernel.diff
+ (Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff)
+ The patches are against 2.1.125, so you might have to manually resolve
+ rejections when applying to another kernel version.
+
+ The patches will update the kernel startup code to allow boot parameters to
+ be passed to the driver, update the Documentation and finally offer you the
+ possibility to omit the non-DC390 parts of the driver.
+ (By selecting "Omit support for non DC390" you basically disable the
+ emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes
+ of memory.)
+
+If you got a very old kernel without the tmscsim driver (pre 2.0.31)
+I recommend upgrading your kernel. However, if you don't want to, please
+contact me to get the appropriate patches.
+
+
+Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has
+proven stable on many systems, but it's still a good idea to take some
+precautions. In an ideal world you would have a full backup of your disks.
+The world isn't ideal and most people don't have full backups (me neither).
+So take at least the following measures:
+* make your kernel remount the FS read-only on detecting an error:
+  tune2fs -e remount-ro /dev/sd??
+* have copies of your SCSI disk's partition tables on some safe location:
+  dd if=/dev/sda of=/mnt/floppy/sda bs=512 count=1
+  or just print it with:
+  fdisk -l | lpr
+* make sure you are able to boot Linux (e.g. from floppy disk using InitRD)
+  if your SCSI disk gets corrupted. You can use 
+  ftp://student.physik.uni-dortmund.de/pub/linux/kernel/bootdisk.gz
+
+One more warning: I used to overclock my PCI bus to 41.67 MHz. My Tekram
+DC390F (Sym53c875) accepted this as well as my Millenium. But the Am53C974
+produced errors and started to corrupt my disks. So don't do that! A 37.50
+MHz PCI bus works for me, though, but I don't recommend using higher clocks
+than the 33.33 MHz being in the PCI spec.
+
+If you want to share the IRQ with another device and the driver refuses to
+do so, you might succeed with changing the DC390_IRQ type in tmscsim.c to 
+SA_SHIRQ | SA_INTERRUPT.
+
+
+3.Features
+----------
+- SCSI
+ * Tagged command queueing
+ * Sync speed up to 10 MHz
+ * Disconnection
+ * Multiple LUNs
+
+- General / Linux interface
+ * Support for up to 4 AM53C974 adapters.
+ * DC390 EEPROM usage or boot/module params
+ * Information via cat /proc/scsi/tmscsim/?
+ * Dynamically configurable by writing to /proc/scsi/tmscsim/?
+ * Dynamic allocation of resources
+ * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter 
+    specific locks (Linux 2.5?)
+ * Uniform source code for Linux-2.x.y
+ * Support for dyn. addition/removal of devices via add/remove-single-device
+   (Try: echo "scsi add-single-device C B T U" >/proc/scsi/scsi 
+    C = Controller, B = Bus, T = Target SCSI ID, U = Unit SCSI LUN.) 
+    Use with care!
+ * Try to use the partition table for the determination of the mapping
+
+
+4. Configuration via /proc/scsi/tmscsim/?
+-----------------------------------------
+First of all look at the output of /proc/scsi/tmscsim/? by typing
+ cat /proc/scsi/tmscsim/?
+The "?" should be replaced by the SCSI host number. (The shell might do this
+for you.)
+You will see some info regarding the adapter and, at the end, a listing of
+the attached devices and their settings.
+
+Here's an example:
+garloff@kurt:/home/garloff > cat /proc/scsi/tmscsim/0
+Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0e7 2000-11-28
+SCSI Host Nr 1, AM53C974 Adapter Nr 0
+IOPortBase 0xb000, IRQ 10
+MaxID 8, MaxLUN 8, AdapterID 6, SelTimeout 250 ms, DelayReset 1 s
+TagMaxNum 16, Status 0x00, ACBFlag 0x00, GlitchEater 24 ns
+Statistics: Cmnds 1470165, Cmnds not sent directly 0, Out of SRB conds 0
+            Lost arbitrations 587,  Sel. connected 0, Connected: No
+Nr of attached devices: 4, Nr of DCBs: 4
+Map of attached LUNs: 01 00 00 03 01 00 00 00
+Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd
+00  00  00  Yes  Yes  Yes  Yes  Yes   100 ns    10.0 M      15      16
+01  03  00  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
+02  03  01  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
+03  04  00  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
+
+Note that the settings MaxID and MaxLUN are not zero- but one-based, which
+means that a setting MaxLUN=4, will result in the support of LUNs 0..3. This
+is somehow inconvenient, but the way the mid-level SCSI code expects it to be.
+
+ACB and DCB are acronyms for Adapter Control Block and Device Control Block.
+These are data structures of the driver containing information about the
+adapter and the connected SCSI devices respectively.
+
+Idx is the device index (just a consecutive number for the driver), ID and
+LUN are the SCSI ID and LUN, Prty means Parity checking, Sync synchronous
+negotiation, DsCn Disconnection, SndS Send Start command on startup (not
+used by the driver) and TagQ Tagged Command Queueing. NegoPeriod and
+SyncSpeed are somehow redundant, because they are reciprocal values 
+(1 / 112 ns = 8.9 MHz). At least in theory. The driver is able to adjust the
+NegoPeriod more accurate (4ns) than the SyncSpeed (1 / 25ns). I don't know
+if certain devices will have problems with this discrepancy. Max. speed is
+10 MHz corresp. to a min. NegoPeriod of 100 ns. 
+(The driver allows slightly higher speeds if the devices (Ultra SCSI) accept
+it, but that's out of adapter spec, on your own risk and unlikely to improve
+performance. You're likely to crash your disks.) 
+SyncOffs is the offset used for synchronous negotiations; max. is 15. 
+The last values are only shown, if Sync is enabled. (NegoPeriod is still
+displayed in brackets to show the values which will be used after enabling
+Sync.)
+MaxCmd ist the number of commands (=tags) which can be processed at the same
+time by the device.
+
+If you want to change a setting, you can do that by writing to
+/proc/scsi/tmscsim/?. Basically you have to imitate the output of driver.
+(Don't use the brackets for NegoPeriod on Sync disabled devices.)
+You don't have to care about capitalisation. The driver will accept space,
+tab, comma, = and : as separators.
+
+There are three kinds of changes: 
+
+(1) Change driver settings: 
+    You type the names of the parameters and the params following it.
+    Example:
+     echo "MaxLUN=8 seltimeout 200" >/proc/scsi/tmscsim/0
+
+    Note that you can only change MaxID, MaxLUN, AdapterID, SelTimeOut,
+    TagMaxNum, ACBFlag, GlitchEater and DelayReset. Don't change ACBFlag
+    unless you want to see what happens, if the driver hangs.
+
+(2) Change device settings: You write a config line to the driver. The Nr
+    must match the ID and LUN given. If you give "-" as parameter, it is
+    ignored and the corresponding setting won't be changed. 
+    You can use "y" or "n" instead of "Yes" and "No" if you want to.
+    You don't need to specify a full line. The driver automatically performs
+    an INQUIRY on the device if necessary to check if it is capable to operate
+    with the given settings (Sync, TagQ).
+    Examples:
+     echo "0 0 0 y y y - y - 10 " >/proc/scsi/tmscsim/0
+     echo "3 5 0 y n y " >/proc/scsi/tmscsim/0
+
+    To give a short explanation of the first example: 
+    The first three numbers, "0 0 0" (Device index 0, SCSI ID 0, SCSI LUN 0),
+    select the device to which the following parameters apply. Note that it
+    would be sufficient to use the index or both SCSI ID and LUN, but I chose
+    to require all three to have a syntax similar to the output.
+    The following "y y y - y" enables Parity checking, enables Synchronous
+    transfers, Disconnection, leaves Send Start (not used) untouched and
+    enables Tagged Command Queueing for the selected device. The "-" skips
+    the Negotiation Period setting but the "10" sets the max sync. speed to
+    10 MHz. It's useless to specify both NegoPeriod and SyncSpeed as
+    discussed above. The values used in this example will result in maximum
+    performance.
+
+(3) Special commands: You can force a SCSI bus reset, an INQUIRY command, the
+    removal or the addition of a device's DCB and a SCSI register dump.
+    This is only used for debugging when you meet problems. The parameter of
+    the INQUIRY and REMOVE commands is the device index as shown by the
+    output of /proc/scsi/tmscsim/? in the device listing in the first column
+    (Idx). ADD takes the SCSI ID and LUN.
+    Examples:
+     echo "reset" >/proc/scsi/tmscsim/0
+     echo "inquiry 1" >/proc/scsi/tmscsim/0
+     echo "remove 2" >/proc/scsi/tmscsim/1
+     echo "add 2 3" >/proc/scsi/tmscsim/?
+     echo "dump" >/proc/scsi/tmscsim/0
+
+    Note that you will meet problems when you REMOVE a device's DCB with the
+    remove command if it contains partitions which are mounted. Only use it
+    after unmounting its partitions, telling the SCSI mid-level code to
+    remove it (scsi remove-single-device) and you really need a few bytes of
+    memory.
+    The ADD command allows you to configure a device before you tell the
+    mid-level code to try detection.
+
+
+I'd suggest reviewing the output of /proc/scsi/tmscsim/? after changing
+settings to see if everything changed as requested.
+
+
+5. Configuration via boot/module parameters
+-------------------------------------------
+With the DC390, the driver reads its EEPROM settings and tries to use them.
+But you may want to override the settings prior to being able to change the
+driver configuration via /proc/scsi/tmscsim/?.
+If you do have another AM53C974 based adapter, that's even the only
+possibility to adjust settings before you are able to write to the
+/proc/scsi/tmscsim/? pseudo-file, e.g. if you want to use another 
+adapter ID than 7.  
+(BTW, the log message "DC390: No EEPROM found!" is normal without a DC390.)
+For this purpose, you can pass options to the driver before it is initialised
+by using kernel or module parameters. See lilo(8) or modprobe(1) manual
+pages on how to pass params to the kernel or a module.
+[NOTE: Formerly, it was not possible to override the EEPROM supplied
+ settings of the DC390 with cmd line parameters. This has changed since
+ 2.0e7]
+
+The syntax of the params is much shorter than the syntax of the /proc/...
+interface. This makes it a little bit more difficult to use. However, long
+parameter lines have the risk to be misinterpreted and the length of kernel
+parameters is limited.
+
+As the support for non-DC390 adapters works by simulating the values of the
+DC390 EEPROM, the settings are given in a DC390 BIOS' way.
+
+Here's the syntax:
+tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds,DelayReset
+
+Each of the parameters is a number, containing the described information:
+
+* AdaptID: The SCSI ID of the host adapter. Must be in the range 0..7
+  Default is 7.
+
+* SpdIdx: The index of the maximum speed as in the DC390 BIOS. The values
+  0..7 mean 10, 8.0, 6.7, 5.7, 5.0, 4.0, 3.1 and 2 MHz resp. Default is
+  0 (10.0 MHz).
+
+* DevMode is a bit mapped value describing the per-device features. It
+  applies to all devices. (Sync, Disc and TagQ will only apply, if the
+  device supports it.) The meaning of the bits (* = default):
+
+   Bit Val(hex) Val(dec)  Meaning
+   *0	 0x01	    1	  Parity check
+   *1	 0x02	    2	  Synchronous Negotiation
+   *2	 0x04	    4	  Disconnection
+   *3	 0x08	    8	  Send Start command on startup. (Not used)
+   *4	 0x10	   16	  Tagged Command Queueing
+
+  As usual, the desired value is obtained by adding the wanted values. If
+  you want to enable all values, e.g., you would use 31(0x1f). Default is 31.
+
+* AdaptMode is a bit mapped value describing the enabled adapter features.
+
+   Bit Val(hex) Val(dec)  Meaning
+   *0	 0x01	    1	  Support more than two drives. (Not used)
+   *1	 0x02	    2	  Use DOS compatible mapping for HDs greater than 1GB.
+   *2	 0x04	    4	  Reset SCSI Bus on startup.
+   *3	 0x08	    8	  Active Negation: Improves SCSI Bus noise immunity.
+    4	 0x10	   16	  Immediate return on BIOS seek command. (Not used)
+ (*)5	 0x20	   32	  Check for LUNs >= 1.
+  
+  The default for LUN Check depends on CONFIG_SCSI_MULTI_LUN.
+
+* TaggedCmnds is a number indicating the maximum number of Tagged Commands.
+  It is the binary logarithm - 1 of the actual number. Max is 4 (32).
+   Value  Number of Tagged Commands
+     0		 2
+     1		 4
+     2		 8
+    *3		16
+     4		32
+
+* DelayReset is the time in seconds (minus 0.5s), the adapter waits, after a
+  bus reset. Default is 1 (corresp. to 1.5s).
+
+Example:
+ modprobe tmscsim tmscsim=6,2,31
+would set the adapter ID to 6, max. speed to 6.7 MHz, enable all device
+features and leave the adapter features, the number of Tagged Commands
+and the Delay after a reset to the defaults.
+
+As you can see, you don't need to specify all of the six params.
+If you want values to be ignored (i.e. the EEprom settings or the defaults
+will be used), you may pass -2 (not 0!) at the corresponding position.
+
+The defaults (7,0,31,15,3,1) are aggressive to allow good performance. You
+can use tmscsim=7,0,31,63,4,0 for maximum performance, if your SCSI chain
+allows it. If you meet problems, you can use tmscsim=-1 which is a shortcut
+for tmscsim=7,4,9,15,2,10.
+
+
+6. Potential improvements
+-------------------------
+Most of the intended work on the driver has been done. Here are a few ideas
+to further improve its usability:
+
+* Cleanly separate per-Target and per-LUN properties (DCB)
+* More intelligent abort() routine
+* Use new_eh code (Linux-2.1+)
+* Have the mid-level (ML) code (and not the driver) handle more of the
+  various conditions.
+* Command queueing in the driver: Eliminate Query list and use ML instead.
+* More user friendly boot/module param syntax
+
+Further investigation on these problems:
+
+* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error)
+
+Known problems: 
+Please see http://www.garloff.de/kurt/linux/dc390/problems.html
+
+* Changing the parameters of multi-lun by the tmscsim/? interface will
+  cause problems, cause these settings are mostly per Target and not per LUN
+  and should be updated accordingly. To be fixed for 2.0d24.
+* CDRs (eg Yam CRW4416) not recognized, because some buggy devices don't 
+  recover from a SCSI reset in time. Use a higher delay or don't issue
+  a SCSI bus reset on driver initialization. See problems page.
+  For the CRW4416S, this seems to be solved with firmware 1.0g (reported by 
+  Jean-Yves Barbier).
+* TEAC CD-532S not being recognized. (Works with 1.11).
+* Scanners (eg. Astra UMAX 1220S) don't work: Disable Sync Negotiation.
+  If this does not help, try echo "INQUIRY t" >/proc/scsi/tmscsim/? (t
+  replaced by the dev index of your scanner). You may try to reset your SCSI
+  bus afterwards (echo "RESET" >/proc/scsi/tmscsim/?).
+  The problem seems to be solved as of 2.0d18, thanks to Andreas Rick.
+* If there is a valid partition table, the driver will use it for determing
+  the mapping. If there's none, a reasonable mapping (Symbios-like) will be
+  assumed. Other operating systems may not like this mapping, though
+  it's consistent with the BIOS' behaviour. Old DC390 drivers ignored the
+  partition table and used a H/S = 64/32 or 255/63 translation. So if you
+  want to be compatible to those, use this old mapping when creating
+  partition tables. Even worse, on bootup the DC390 might complain if other
+  mappings are found, so auto rebooting may fail.
+* In some situations, the driver will get stuck in an abort loop. This is a
+  bad interaction between the Mid-Layer of Linux' SCSI code and the driver.
+  Try to disable DsCn, if you meet this problem. Please contact me for
+  further debugging.
+
+
+7. Bug reports, debugging and updates
+-------------------------------------
+Whenever you have problems with the driver, you are invited to ask the
+author for help. However, I'd suggest reading the docs and trying to solve
+the problem yourself, first. 
+If you find something, which you believe to be a bug, please report it to me. 
+Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and
+maybe the DC390 log messages to the report. 
+
+Bug reports should be send to me (Kurt Garloff <dc390@garloff.de>) as well
+as to the linux-scsi list (<linux-scsi@vger.kernel.org>), as sometimes bugs
+are caused by the SCSI mid-level code.
+
+I will ask you for some more details and probably I will also ask you to
+enable some of the DEBUG options in the driver (tmscsim.c:DC390_DEBUGXXX
+defines). The driver will produce some data for the syslog facility then.
+Beware: If your syslog gets written to a SCSI disk connected to your
+AM53C974, the logging might produce log output again, and you might end
+having your box spending most of its time doing the logging.
+
+The latest version of the driver can be found at:
+ http://www.garloff.de/kurt/linux/dc390/
+ ftp://ftp.suse.com/pub/people/garloff/linux/dc390/
+
+
+8. Acknowledgements
+-------------------
+Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and 
+all the others for the wonderful OS and software.
+Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver
+release and support.
+Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding.
+Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert 
+Tonneau) for intensively testing the driver (and even risking data loss
+doing this during early revisions).
+Recently, SuSE GmbH, Nuernberg, FRG, has been paying me for the driver
+development and maintenance. Special thanks!
+
+
+9. Copyright
+------------
+ This driver 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; version 2 of the License.
+ If you want to use any later version of the GNU GPL, you will probably
+ be allowed to, but you have to ask me and Tekram <erich@tekram.com.tw>
+ before.
+
+-------------------------------------------------------------------------
+Written by Kurt Garloff <kurt@garloff.de> 1998/06/11
+Last updated 2000/11/28, driver revision 2.0e7
+$Id: README.tmscsim,v 2.25.2.7 2000/12/20 01:07:12 garloff Exp $
diff -Nru a/Documentation/scsi-generic.txt b/Documentation/scsi-generic.txt
--- a/Documentation/scsi-generic.txt	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,101 +0,0 @@
-            Notes on Linux SCSI Generic (sg) driver
-            ---------------------------------------
-                                                        20020126
-Introduction
-============
-The SCSI Generic driver (sg) is one of the four "high level" SCSI device
-drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg
-is more generalized (but lower level) than its siblings and tends to be
-used on SCSI devices that don't fit into the already serviced categories.
-Thus sg is used for scanners, CD writers and reading audio CDs digitally
-amongst other things.
-
-Rather than document the driver's interface here, version information
-is provided plus pointers (i.e. URLs) where to find documentation
-and examples.
-
-
-Major versions of the sg driver
-===============================
-There are three major versions of sg found in the linux kernel (lk):
-      - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . 
-	It is based in the sg_header interface structure.
-      - sg version 2 from lk 2.2.6 in the 2.2 series. It is based on
-	an extended version of the sg_header interface structure.
-      - sg version 3 found in the lk 2.4 series (and the lk 2.5 series).
-	It adds the sg_io_hdr interface structure.
-
-
-Sg driver documentation
-=======================
-The most recent documentation of the sg driver is kept at the Linux
-Documentation Project's (LDP) site: 
-http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO
-This describes the sg version 3 driver found in the lk 2.4 series.
-The LDP renders documents in single and multiple page HTML, postscript
-and pdf. This document can also be found at:
-http://www.torque.net/sg/p/sg_v3_ho.html
-
-Documentation for the version 2 sg driver found in the lk 2.2 series can
-be found at http://www.torque.net/sg/p/scsi-generic.txt . A larger version
-is at:  http://www.torque.net/sg/p/scsi-generic_long.txt .
-
-The original documentation for the sg driver (prior to lk 2.2.6) can be
-found at http://www.torque.net/sg/p/original/SCSI-Programming-HOWTO.txt
-and in the LDP archives.
-
-A changelog with brief notes can be found in the
-/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy 
-and edit this file (removing its changelog for example) before placing it 
-in /usr/include/scsi/sg.h . Driver debugging information and other notes 
-can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file.
-
-A more general description of the Linux SCSI subsystem of which sg is a 
-part can be found at http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO .
-
-
-Example code and utilities
-==========================
-There are two packages of sg utilities:
-  - sg3_utils   for the sg version 3 driver found in lk 2.4
-  - sg_utils    for the sg version 2 (and original) driver found in lk 2.2
-                and earlier
-Both packages will work in the lk 2.4 series however sg3_utils offers more
-capabilities. They can be found at: http://www.torque.net/sg and 
-freshmeat.net
-
-Another approach is to look at the applications that use the sg driver.
-These include cdrecord, cdparanoia, SANE and cdrdao.
-
-
-Mapping of Linux kernel versions to sg driver versions
-======================================================
-Here is a list of linux kernels in the 2.4 series that had new version
-of the sg driver:
-      lk 2.4.0 : sg version 3.1.17
-      lk 2.4.7 : sg version 3.1.19 
-      lk 2.4.10 : sg version 3.1.20  **
-      lk 2.4.17 : sg version 3.1.22 
-
-** There were 3 changes to sg version 3.1.20 by third parties in the
-   next six linux kernel versions.
-
-For reference here is a list of linux kernels in the 2.2 series that had 
-new version of the sg driver:
-      lk 2.2.0 : original sg version [with no version number]
-      lk 2.2.6 : sg version 2.1.31
-      lk 2.2.8 : sg version 2.1.32
-      lk 2.2.10 : sg version 2.1.34 [SG_GET_VERSION_NUM ioctl first appeared]
-      lk 2.2.14 : sg version 2.1.36
-      lk 2.2.16 : sg version 2.1.38
-      lk 2.2.17 : sg version 2.1.39
-      lk 2.2.20 : sg version 2.1.40
-
-The lk 2.5 development series has recently commenced and it currently
-contains sg version 3.5.23 which is functionally equivalent to sg
-version 3.1.22 found in lk 2.4.17 .
-
-
-Douglas Gilbert
-26th January 2002
-dgilbert@interlog.com
diff -Nru a/Documentation/scsi.txt b/Documentation/scsi.txt
--- a/Documentation/scsi.txt	Sun Nov 17 20:30:02 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
-SCSI subsystem documentation
-============================
-The Linux Documentation Project (LDP) maintains a document describing
-the SCSI subsystem in the Linux kernel (lk) 2.4 series. See:
-http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single
-and multiple page HTML renderings as well as postscript and pdf.
-It can also be found at http://www.torque.net/scsi/SCSI-2.4-HOWTO .
-
-
-Notes on using modules in the SCSI subsystem
-============================================
-The scsi support in the linux kernel can be modularized in a number of 
-different ways depending upon the needs of the end user.  To understand
-your options, we should first define a few terms.
-
-The scsi-core (also known as the "mid level") contains the core of scsi 
-support.  Without it you can do nothing with any of the other scsi drivers.
-The scsi core support can be a module (scsi_mod.o), or it can be built into
-the kernel. If the core is a module, it must be the first scsi module 
-loaded, and if you unload the modules, it will have to be the last one 
-unloaded.  In practice the modprobe and rmmod commands (and "autoclean")
-will enforce the correct ordering of loading and unloading modules in
-the SCSI subsystem.
-
-The individual upper and lower level drivers can be loaded in any order 
-once the scsi core is present in the kernel (either compiled in or loaded
-as a module).  The disk driver (sd_mod.o), cdrom driver (sr_mod.o),
-tape driver ** (st.o) and scsi generics driver (sg.o) represent the upper 
-level drivers to support the various assorted devices which can be 
-controlled.  You can for example load the tape driver to use the tape drive, 
-and then unload it once you have no further need for the driver (and release
-the associated memory).
-
-The lower level drivers are the ones that support the individual cards that
-are supported for the hardware platform that you are running under. Those
-individual cards are often called Host Bus Adapters (HBAs). For example the
-aic7xxx.o driver is used to control all recent SCSI controller cards from 
-Adaptec. Almost all lower level drivers can be built either as modules or 
-built into the kernel.
-
-
-** There is a variant of the st driver for controlling OnStream tape
-   devices. Its module name is osst.o .
-
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sun Nov 17 20:30:03 2002
+++ b/Makefile	Sun Nov 17 20:30:03 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 47
+SUBLEVEL = 48
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -157,7 +157,6 @@
 OBJDUMP		= $(CROSS_COMPILE)objdump
 AWK		= awk
 GENKSYMS	= /sbin/genksyms
-DEPMOD		= /sbin/depmod
 KALLSYMS	= /sbin/kallsyms
 PERL		= perl
 MODFLAGS	= -DMODULE
@@ -516,7 +515,7 @@
 #	Install modules
 
 .PHONY: modules_install
-modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post
+modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS))
 
 .PHONY: _modinst_
 _modinst_:
@@ -524,20 +523,6 @@
 	@rm -f $(MODLIB)/build
 	@mkdir -p $(MODLIB)/kernel
 	@ln -s $(TOPDIR) $(MODLIB)/build
-
-# If System.map exists, run depmod.  This deliberately does not have a
-# dependency on System.map since that would run the dependency tree on
-# vmlinux.  This depmod is only for convenience to give the initial
-# boot a modules.dep even before / is mounted read-write.  However the
-# boot script depmod is the master version.
-ifeq "$(strip $(INSTALL_MOD_PATH))" ""
-depmod_opts	:=
-else
-depmod_opts	:= -b $(INSTALL_MOD_PATH) -r
-endif
-.PHONY: _modinst_post
-_modinst_post:
-	if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
 
 .PHONY: $(patsubst %, _modinst_%, $(SUBDIRS))
 $(patsubst %, _modinst_%, $(SUBDIRS)) :
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/alpha/Kconfig	Sun Nov 17 20:30:15 2002
@@ -794,7 +794,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
--- a/arch/alpha/kernel/srm_env.c	Sun Nov 17 20:30:03 2002
+++ b/arch/alpha/kernel/srm_env.c	Sun Nov 17 20:30:03 2002
@@ -116,12 +116,8 @@
 	unsigned long	ret;
 	srm_env_t	*entry;
 
-	MOD_INC_USE_COUNT;
-
-	if(off != 0) {
-		MOD_DEC_USE_COUNT;
+	if(off != 0)
 		return -EFAULT;
-	}
 
 	entry	= (srm_env_t *) data;
 	ret	= callback_getenv(entry->id, page, count);
@@ -131,8 +127,6 @@
 	else
 		nbytes = -EFAULT;
 
-	MOD_DEC_USE_COUNT;
-
 	return nbytes;
 }
 
@@ -141,44 +135,37 @@
 srm_env_write(struct file *file, const char *buffer, unsigned long count,
 		void *data)
 {
-#define BUFLEN	512
-	int		nbytes;
+	int res;
 	srm_env_t	*entry;
-	char		buf[BUFLEN];
+	char		*buf = (char *) __get_free_page(GFP_USER);
 	unsigned long	ret1, ret2;
 
-	MOD_INC_USE_COUNT;
-
 	entry = (srm_env_t *) data;
 
-	nbytes = strlen(buffer) + 1;
-	if(nbytes > BUFLEN) {
-		MOD_DEC_USE_COUNT;
+	if (!buf)
 		return -ENOMEM;
-	}
-
-	/* memcpy(aligned_buffer, buffer, nbytes) */
 
-	if(copy_from_user(buf, buffer, count)) {
-		MOD_DEC_USE_COUNT;
-		return -EFAULT;
-	}
-	buf[count] = 0x00;
+	res = -EINVAL;
+	if (count >= PAGE_SIZE)
+		goto out;
+
+	res = -EFAULT;
+	if (copy_from_user(buf, buffer, count))
+		goto out;
+	buf[count] = '\0';
 
 	ret1 = callback_setenv(entry->id, buf, count);
-	if((ret1 >> 61) == 0) {
+	if ((ret1 >> 61) == 0) {
 		do 
 			ret2 = callback_save_env();
 		while((ret2 >> 61) == 1);
-		nbytes = (int) ret1;
-	} else
-		nbytes = -EFAULT;
+		res = (int) ret1;
+	}
 
-	MOD_DEC_USE_COUNT;
+	free_page((unsigned long)buf);
 
-	return nbytes;
+	return res;
 }
-
 
 static void
 srm_env_cleanup(void)
diff -Nru a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
--- a/arch/alpha/kernel/sys_jensen.c	Sun Nov 17 20:30:14 2002
+++ b/arch/alpha/kernel/sys_jensen.c	Sun Nov 17 20:30:14 2002
@@ -220,7 +220,7 @@
 {
 	struct pci_controller *hose;
 #ifdef CONFIG_PCI
-	static struct pci_dev fake_isa_bridge = { dma_mask: 0xffffffffUL, };
+	static struct pci_dev fake_isa_bridge = { .dma_mask = 0xffffffffUL, };
 
 	isa_bridge = &fake_isa_bridge;
 #endif
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c	Sun Nov 17 20:30:13 2002
+++ b/arch/alpha/kernel/sys_nautilus.c	Sun Nov 17 20:30:13 2002
@@ -107,7 +107,6 @@
 naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
 		       struct pt_regs *regs)
 {
-	printk("xtime %lx\n", CURRENT_TIME);
 	printk("PC %lx RA %lx\n", regs->pc, regs->r26);
 	irongate_pci_clr_err();
 }
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/Kconfig	Sun Nov 17 20:30:14 2002
@@ -222,7 +222,7 @@
 
 config FORCE_MAX_ZONEORDER
 	int
-	depends on ASSABET_NEPONSET || SA1100_ADSBITSY || SA1100_BADGE4 || SA1100_CONSUS || SA1100_GRAPHICSMASTER || SA1100_JORNADA720 || ARCH_LUBBOCK || SA1100_PFS168 || SA1100_PT_SYSTEM3 || SA1100_XP860
+	depends on SA1111
 	default "9"
 
 comment "Processor Type"
@@ -1014,7 +1014,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -1041,11 +1041,6 @@
 config KBDMOUSE
 	bool
 	depends on ARCH_ACORN && BUSMOUSE=y && !ARCH_RPC
-	default y
-
-config RPCMOUSE
-	bool
-	depends on ARCH_ACORN && BUSMOUSE=y && ARCH_RPC
 	default y
 
 source "drivers/media/Kconfig"
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/Makefile	Sun Nov 17 20:30:12 2002
@@ -34,14 +34,12 @@
 # Note that GCC is lame - it doesn't numerically define an
 # architecture version macro, but instead defines a whole
 # series of macros.
-arch-y				:=
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5
 arch-$(CONFIG_CPU_XSCALE)	:=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mxscale #-march=armv5te
 
 # This selects how we optimise for the processor.
-tune-y				:=
 tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
 tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
 tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
@@ -58,123 +56,67 @@
 CFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu
 AFLAGS		+=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu
 
+#Default value
+DATAADDR	:= .
+
 ifeq ($(CONFIG_CPU_26),y)
 PROCESSOR	:= armo
 HEAD		:= arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o
 LDFLAGS_BLOB	+= --oformat elf26-littlearm
   ifeq ($(CONFIG_ROM_KERNEL),y)
-    DATAADDR	 = 0x02080000
-    TEXTADDR	 = 0x03800000
+    DATAADDR	 := 0x02080000
+    textaddr-y	 := 0x03800000
   else
-    TEXTADDR	 = 0x02080000
+    textaddr-y	 := 0x02080000
   endif
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
-PROCESSOR	 = armv
+PROCESSOR	:= armv
 HEAD		:= arch/arm/kernel/head.o arch/arm/kernel/init_task.o
-TEXTADDR	 = 0xC0008000
 LDFLAGS_BLOB	+= --oformat elf32-littlearm
+textaddr-y	:= 0xC0008000
 endif
 
-ifeq ($(CONFIG_ARCH_ARCA5K),y)
-MACHINE		 = arc
-endif
-
-ifeq ($(CONFIG_ARCH_RPC),y)
-MACHINE		 = rpc
-endif
-
-ifeq ($(CONFIG_ARCH_EBSA110),y)
-MACHINE		 = ebsa110
-endif
-
-ifeq ($(CONFIG_ARCH_CLPS7500),y)
-MACHINE		 = clps7500
-INCDIR		 = cl7500
-endif
-
-ifeq ($(CONFIG_FOOTBRIDGE),y)
-MACHINE		 = footbridge
-INCDIR		 = ebsa285
-endif
-
-ifeq ($(CONFIG_ARCH_CO285),y)
-TEXTADDR	 = 0x60008000
-MACHINE		 = footbridge
-INCDIR		 = ebsa285
-endif
-
-ifeq ($(CONFIG_ARCH_FTVPCI),y)
-MACHINE		 = ftvpci
-INCDIR		 = nexuspci
-endif
-
-ifeq ($(CONFIG_ARCH_TBOX),y)
-MACHINE		 = tbox
-endif
-
-ifeq ($(CONFIG_ARCH_SHARK),y)
-MACHINE		 = shark
-endif
-
+ machine-$(CONFIG_ARCH_ARCA5K)	   := arc
+ machine-$(CONFIG_ARCH_RPC)	   := rpc
+ machine-$(CONFIG_ARCH_EBSA110)	   := ebsa110
+ machine-$(CONFIG_ARCH_CLPS7500)   := clps7500
+  incdir-$(CONFIG_ARCH_CLPS7500)   := cl7500
+ machine-$(CONFIG_FOOTBRIDGE)	   := footbridge
+  incdir-$(CONFIG_FOOTBRIDGE)	   := ebsa285
+textaddr-$(CONFIG_ARCH_CO285)	   := 0x60008000
+ machine-$(CONFIG_ARCH_CO285)	   := footbridge
+  incdir-$(CONFIG_ARCH_CO285)	   := ebsa285
+ machine-$(CONFIG_ARCH_FTVPCI)	   := ftvpci
+  incdir-$(CONFIG_ARCH_FTVPCI)	   := nexuspci
+ machine-$(CONFIG_ARCH_TBOX)	   := tbox
+ machine-$(CONFIG_ARCH_SHARK)	   := shark
+ machine-$(CONFIG_ARCH_SA1100)	   := sa1100
 ifeq ($(CONFIG_ARCH_SA1100),y)
-ifeq ($(CONFIG_SA1111),y)
 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
-TEXTADDR	 = 0xc0208000
-endif
-MACHINE		 = sa1100
+textaddr-$(CONFIG_SA1111)	   := 0xc0208000
 endif
-
-ifeq ($(CONFIG_ARCH_PXA),y)
-MACHINE		 = pxa
-endif
-
-ifeq ($(CONFIG_ARCH_L7200),y)
-MACHINE		 = l7200
+ machine-$(CONFIG_ARCH_PXA)	   := pxa
+ machine-$(CONFIG_ARCH_L7200)	   := l7200
+ machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
+ machine-$(CONFIG_ARCH_CAMELOT)	   := epxa10db
+textaddr-$(CONFIG_ARCH_CLPS711X)   := 0xc0028000
+ machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
+textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
+ machine-$(CONFIG_ARCH_ANAKIN)	   := anakin
+ machine-$(CONFIG_ARCH_IOP310)	   := iop310
+ machine-$(CONFIG_ARCH_ADIFCC)	   := adifcc
+
+MACHINE  := $(machine-y)
+TEXTADDR := $(textaddr-y)
+ifeq ($(incdir-y),)
+incdir-y := $(MACHINE)
 endif
-
-ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
-MACHINE		 = integrator
-endif
-
-ifeq ($(CONFIG_ARCH_CAMELOT),y)
-MACHINE          = epxa10db
-endif
-
-ifeq ($(CONFIG_ARCH_CLPS711X),y)
-TEXTADDR	 = 0xc0028000
-MACHINE		 = clps711x
-endif
-
-ifeq ($(CONFIG_ARCH_FORTUNET),y)
-TEXTADDR	 = 0xc0008000
-endif
-
-ifeq ($(CONFIG_ARCH_ANAKIN),y)
-MACHINE		 = anakin
-endif
-
-ifeq ($(CONFIG_ARCH_IOP310),y)
-MACHINE		 = iop310
-endif
-
-ifeq ($(CONFIG_ARCH_ADIFCC),y)
-MACHINE		= adifcc
-endif
-
+INCDIR   := $(incdir-y)
+  
 export	MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT
 
-# Only set INCDIR if its not already defined above
-# Grr, ?= doesn't work as all the other assignment operators do.  Make bug?
-ifeq ($(origin INCDIR), undefined)
-INCDIR		:=$(MACHINE)
-endif
-
-ifeq ($(origin DATAADDR), undefined)
-DATAADDR	:= .
-endif
-
 # Do we have FASTFPE?
 FASTFPE		:=arch/arm/fastfpe
 ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
@@ -194,7 +136,10 @@
 
 libs-y				+= arch/arm/lib/
 
-makeboot = $(call descend,arch/arm/boot,$(1))
+# Default target when executing plain make
+all: zImage
+
+makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/arm/boot $(1)
 
 #	Update machine arch and proc symlinks if something which affects
 #	them changed.  We use .arch and .proc to indicate when they were
@@ -217,13 +162,17 @@
 .PHONY: maketools FORCE
 maketools: include/asm-arm/.arch include/asm-arm/.proc \
 	   include/asm-arm/constants.h include/linux/version.h FORCE
-	+@$(call descend,arch/arm/tools, include/asm-arm/mach-types.h)
+	$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/arm/tools include/asm-arm/mach-types.h
+
+# Convert bzImage to zImage
+bzImage: vmlinux
+	$(call makeboot,arch/arm/boot/zImage)
 
 zImage Image bootpImage: vmlinux
-	+@$(call makeboot,arch/arm/boot/$@)
+	$(call makeboot,arch/arm/boot/$@)
 
-bzImage zinstall install: vmlinux
-	+@$(call makeboot,$@)
+zinstall install: vmlinux
+	$(call makeboot,$@)
 
 MRPROPER_FILES	+= \
 	include/asm-arm/arch include/asm-arm/.arch \
@@ -233,15 +182,15 @@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archmrproper:
-archclean: FORCE
-	+@$(call makeboot,clean)
+archclean:
+	$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/arm/boot
 
 # My testing targets (that short circuit a few dependencies)
-zImg:;	+@$(call makeboot, zImage)
-Img:;	+@$(call makeboot, Image)
-i:;	+@$(call makeboot, install)
-zi:;	+@$(call makeboot, zinstall)
-bp:;	+@$(call makeboot, bootpImage)
+zImg:;	$(call makeboot, arch/arm/boot/zImage)
+Img:;	$(call makeboot, arch/arm/boot/Image)
+bp:;	$(call makeboot, arch/arm/boot/bootpImage)
+i:;	$(call makeboot, install)
+zi:;	$(call makeboot, zinstall)
 
 #
 # Configuration targets.  Use these to select a
@@ -261,10 +210,9 @@
 
 arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
 				   include/config/MARKER
+	@:
 
-include/asm-$(ARCH)/constants.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
-	@$(generate-asm-offsets.h) < $< > $@
-
-include/asm-$(ARCH)/constants.h: include/asm-$(ARCH)/constants.h.tmp
+include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
 	@echo -n '  Generating $@'
+	@$(generate-asm-offsets.h) < $< > $@.tmp
 	@$(update-if-changed)
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/boot/Makefile	Sun Nov 17 20:30:03 2002
@@ -13,132 +13,81 @@
 #   PARAMS_PHYS must be with 4MB of ZRELADDR
 #   INITRD_PHYS must be in RAM
 
-ifeq ($(CONFIG_CPU_26),y)
-ZRELADDR	 = 0x02080000
-PARAMS_PHYS	 = 0x0207c000
-INITRD_PHYS	 = 0x02180000
-endif
-
-ifeq ($(CONFIG_ARCH_RPC),y)
-ZRELADDR	 = 0x10008000
-PARAMS_PHYS	 = 0x10000100
-INITRD_PHYS	 = 0x18000000
-endif
-
-ifeq ($(CONFIG_ARCH_CLPS7500),y)
-ZRELADDR	 = 0x10008000
-endif
-
-ifeq ($(CONFIG_ARCH_EBSA110),y)
-ZRELADDR	 = 0x00008000
-PARAMS_PHYS	 = 0x00000400
-INITRD_PHYS	 = 0x00800000
-endif
-
-ifeq ($(CONFIG_ARCH_SHARK),y)
-ZTEXTADDR	 = 0x08508000
-ZRELADDR	 = 0x08008000
-endif
-
-ifeq ($(CONFIG_FOOTBRIDGE),y)
-ZRELADDR	 = 0x00008000
-PARAMS_PHYS	 = 0x00000100
-INITRD_PHYS	 = 0x00800000
-endif
-
-ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
-ZRELADDR	 = 0x00008000
-PARAMS_PHYS	 = 0x00000100
-INITRD_PHYS	 = 0x00800000
-endif
-
-ifeq ($(CONFIG_ARCH_CAMELOT),y)
-ZRELADDR	 = 0x00008000
-endif
-
-ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
-ZRELADDR	 = 0x40008000
-endif
-
-ifeq ($(CONFIG_ARCH_L7200),y)
-ZRELADDR	 = 0xf0008000
-endif
-
+   zreladdr-$(CONFIG_CPU_26)		:= 0x02080000 
+params_phys-$(CONFIG_CPU_26)		:= 0x0207c000
+initrd_phys-$(CONFIG_CPU_26)		:= 0x02180000
+   zreladdr-$(CONFIG_ARCH_RPC)		:= 0x10008000
+params_phys-$(CONFIG_ARCH_RPC)		:= 0x10000100
+initrd_phys-$(CONFIG_ARCH_RPC)		:= 0x18000000
+   zreladdr-$(CONFIG_ARCH_CLPS7500)	:= 0x10008000
+   zreladdr-$(CONFIG_ARCH_CLPS7500)	:= 0x10008000
+   zreladdr-$(CONFIG_ARCH_EBSA110)	:= 0x00008000
+params_phys-$(CONFIG_ARCH_EBSA110)	:= 0x00000400
+initrd_phys-$(CONFIG_ARCH_EBSA110)	:= 0x00800000
+  ztextaddr-$(CONFIG_ARCH_SHARK)	:= 0x08508000
+   zreladdr-$(CONFIG_ARCH_SHARK)	:= 0x08008000
+   zreladdr-$(CONFIG_FOOTBRIDGE)	:= 0x00008000
+params_phys-$(CONFIG_FOOTBRIDGE)	:= 0x00000100
+initrd_phys-$(CONFIG_FOOTBRIDGE)	:= 0x00800000
+   zreladdr-$(CONFIG_ARCH_INTEGRATOR)	:= 0x00008000
+params_phys-$(CONFIG_ARCH_INTEGRATOR)	:= 0x00000100
+initrd_phys-$(CONFIG_ARCH_INTEGRATOR)	:= 0x00800000
+   zreladdr-$(CONFIG_ARCH_CAMELOT)	:= 0x00008000
+   zreladdr-$(CONFIG_ARCH_NEXUSPCI)	:= 0x40008000
+   zreladdr-$(CONFIG_ARCH_L7200)	:= 0xf0008000
 # The standard locations for stuff on CLPS711x type processors
-ifeq ($(CONFIG_ARCH_CLPS711X),y)
-ZRELADDR	 = 0xc0028000
-PARAMS_PHYS	 = 0xc0000100
-endif
-
+   zreladdr-$(CONFIG_ARCH_CLPS711X)	:= 0xc0028000 
+params_phys-$(CONFIG_ARCH_CLPS711X)	:= 0xc0000100
 # Should probably have some agreement on these...
-ifeq ($(CONFIG_ARCH_P720T),y)
-INITRD_PHYS	 = 0xc0400000
-endif
-ifeq ($(CONFIG_ARCH_CDB89712),y)
-INITRD_PHYS	 = 0x00700000
-endif
-
+initrd_phys-$(CONFIG_ARCH_P720T)	:= 0xc0400000
+initrd_phys-$(CONFIG_ARCH_CDB89712)	:= 0x00700000
+   zreladdr-$(CONFIG_ARCH_SA1100)	:= 0xc0008000
 ifeq ($(CONFIG_ARCH_SA1100),y)
-ZRELADDR	 = 0xc0008000
-# No defconfig file to move this into...
-#ifeq ($(CONFIG_SA1100_YOPY),y)
-#  ZTEXTADDR      = 0x00080000
-#  ZBSSADDR       = 0xc0200000
-#endif
-ifeq ($(CONFIG_SA1111),y)
-  ZRELADDR	 = 0xc0208000
-endif
-endif
-
-ifeq ($(CONFIG_ARCH_PXA),y)
-ZRELADDR	 = 0xa0008000
-endif
-
-ifeq ($(CONFIG_ARCH_ANAKIN),y)
-ZRELADDR	 = 0x20008000
+   zreladdr-$(CONFIG_SA1111)		:= 0xc0208000
 endif
-
-ifeq ($(CONFIG_ARCH_IQ80310),y)
-ZRELADDR	 = 0xa0008000
-endif
-
-ifeq ($(CONFIG_ARCH_ADIFCC),y)
-ZRELADDR	 = 0xc0008000
-endif
-
+  zreladdr-$(CONFIG_ARCH_PXA)		:= 0xa0008000
+  zreladdr-$(CONFIG_ARCH_ANAKIN)	:= 0x20008000
+  zreladdr-$(CONFIG_ARCH_IQ80310)	:= 0xa0008000
+  zreladdr-$(CONFIG_ARCH_ADIFCC)	:= 0xc0008000
+
+ZRELADDR    := $(zreladdr-y)
+ZTEXTADDR   := $(ztextaddr-y)
+PARAMS_PHYS := $(params_phys-y)
+INITRD_PHYS := $(initrd_phys-y)
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
 # from ROM or Flash must define ZTEXTADDR (preferably via the config)
-#
+# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK
 ifeq ($(CONFIG_ZBOOT_ROM),y)
-ZTEXTADDR	=$(CONFIG_ZBOOT_ROM_TEXT)
-ZBSSADDR	=$(CONFIG_ZBOOT_ROM_BSS)
+ZTEXTADDR	:= $(CONFIG_ZBOOT_ROM_TEXT)
+ZBSSADDR	:= $(CONFIG_ZBOOT_ROM_BSS)
 else
-ZTEXTADDR	=0
-ZBSSADDR	=ALIGN(4)
+ZTEXTADDR	:= 0
+ZBSSADDR	:= ALIGN(4)
 endif
 
 export	ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS
 
-include $(TOPDIR)/Rules.make
+EXTRA_TARGETS := Image zImage bootpImage
 
 $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
-
-bzImage: $(obj)/zImage
+	@echo '  Kernel: $@ is ready'
 
 $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
 	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: vmlinux FORCE
-	+@$(call descend,arch/arm/boot/compressed, $(obj)/compressed/vmlinux)
+	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed $@
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
-	+@$(call descend,arch/arm/boot/bootp, $(obj)/bootp/bootp)
+	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed $@
 
 .PHONY: initrd
 initrd:
@@ -157,19 +106,16 @@
 	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
-clean:
-	$(RM) $(addprefix $(obj)/,Image zImage bootpImage)
-	+@$(call descend,arch/arm/boot/bootp, clean)
-	+@$(call descend,arch/arm/boot/compressed, clean)
+clean-files := $(addprefix $(obj)/,Image zImage bootpImage)
+subdir-	    := bootp compressed
 
 archhelp:
-	@echo  '* bzImage/zImage- Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+	@echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
 	@echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
 	@echo  '  bootpImage    - Combined zImage and initial RAM disk' 
+	@echo  '  initrd        - Create an initial image'
 	@echo  '  install       - Install uncompressed kernel'
 	@echo  '  zinstall      - Install compressed kernel'
 	@echo  '                  Install using (your) ~/bin/installkernel or'
 	@echo  '                  (distribution) /sbin/installkernel or'
 	@echo  '                  install to $$(INSTALL_PATH) and run lilo'
-
-
diff -Nru a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
--- a/arch/arm/boot/bootp/Makefile	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/boot/bootp/Makefile	Sun Nov 17 20:30:15 2002
@@ -9,8 +9,6 @@
 
 EXTRA_TARGETS := bootp
 
-include $(TOPDIR)/Rules.make
-
 # Note that bootp.lds picks up kernel.o and initrd.o
 $(obj)/bootp:	$(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds)
 		$(LD) $(ZLDFLAGS) -o $@ $(obj)/init.o
@@ -22,5 +20,3 @@
 		$(LD) -r -s -o $@ -b binary $(INITRD)
 
 .PHONY:		$(INITRD) $(ZSYSTEM)
-
-clean:;		$(RM) $(obj)/bootp
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/boot/compressed/Makefile	Sun Nov 17 20:30:03 2002
@@ -63,28 +63,30 @@
 OBJS		+= head-xscale.o
 endif
 
-SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;\
-s/BSS_START/$(ZBSSADDR)/;s#OBJ#$(obj)#
+SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-EXTRA_TARGETS := vmlinux piggy.o font.o head.o $(OBJS)
+EXTRA_TARGETS := vmlinux vmlinux.lds piggy piggy.gz\
+                 piggy.o font.o head.o $(OBJS)
 EXTRA_CFLAGS  := $(CFLAGS_BOOT) -fpic
 EXTRA_AFLAGS  := -traditional
 
-include $(TOPDIR)/Rules.make
-
 LDFLAGS_vmlinux := -p -X \
 	$(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T
 
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
-	 	$(addprefix $(obj)/, $(OBJS))
+	 	$(addprefix $(obj)/, $(OBJS)) FORCE
 	$(call if_changed,ld)
+	@:
+
 
+$(obj)/piggy: vmlinux FORCE
+	$(call if_changed,objcopy)
 
-$(obj)/piggy:    vmlinux;	$(call if_changed,objcopy)
-$(obj)/piggy.gz: $(obj)/piggy;	$(call if_changed,gzip)
+$(obj)/piggy.gz: $(obj)/piggy FORCE
+	$(call if_changed,gzip)
 
 LDFLAGS_piggy.o := -r -b binary
-$(obj)/piggy.o:  $(obj)/piggy.gz
+$(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 	$(call if_changed,ld)
 
 CFLAGS_font.o := -Dstatic=
@@ -93,9 +95,7 @@
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
 
-.PHONY:	clean
-clean:
-	rm -f $(addprefix $(obj)/,vmlinux core piggy* vmlinux.lds)
+clean-files := $(addprefix $(obj)/,vmlinux piggy* vmlinux.lds)
 
 $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c
 
diff -Nru a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
--- a/arch/arm/kernel/dma-isa.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/kernel/dma-isa.c	Sun Nov 17 20:30:16 2002
@@ -16,7 +16,6 @@
  *   arch/arm/kernel/dma-ebsa285.c
  *   Copyright (C) 1998 Phil Blundell
  */
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
diff -Nru a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
--- a/arch/arm/kernel/dma.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/kernel/dma.c	Sun Nov 17 20:30:15 2002
@@ -13,7 +13,6 @@
  */
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/mman.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/kernel/ecard.c	Sun Nov 17 20:30:15 2002
@@ -989,42 +989,6 @@
 	return rc;
 }
 
-static ecard_t *finding_pos;
-
-void ecard_startfind(void)
-{
-	finding_pos = NULL;
-}
-
-ecard_t *ecard_find(int cid, const card_ids *cids)
-{
-	if (!finding_pos)
-		finding_pos = cards;
-	else
-		finding_pos = finding_pos->next;
-
-	for (; finding_pos; finding_pos = finding_pos->next) {
-		if (finding_pos->claimed)
-			continue;
-
-		if (finding_pos->dev.driver)
-			continue;
-
-		if (!cids) {
-			if ((finding_pos->cid.id ^ cid) == 0)
-				break;
-		} else {
-			const struct ecard_id *id;
-
-			id = ecard_match_device(cids, finding_pos);
-			if (id)
-				break;
-		}
-	}
-
-	return finding_pos;
-}
-
 /*
  * Initialise the expansion card system.
  * Locate all hardware - interrupt management and
@@ -1087,10 +1051,15 @@
 	struct expansion_card *ec = ECARD_DEV(dev);
 	struct ecard_driver *drv = ECARD_DRV(dev->driver);
 	const struct ecard_id *id;
+	int ret;
 
 	id = ecard_match_device(drv->id_table, ec);
 
-	return drv->probe(ec, id);
+	ecard_claim(ec);
+	ret = drv->probe(ec, id);
+	if (ret)
+		ecard_release(ec);
+	return ret;
 }
 
 static int ecard_drv_remove(struct device *dev)
@@ -1099,6 +1068,7 @@
 	struct ecard_driver *drv = ECARD_DRV(dev->driver);
 
 	drv->remove(ec);
+	ecard_release(ec);
 
 	return 0;
 }
@@ -1144,12 +1114,8 @@
 
 postcore_initcall(ecard_bus_init);
 
-EXPORT_SYMBOL(ecard_startfind);
-EXPORT_SYMBOL(ecard_find);
 EXPORT_SYMBOL(ecard_readchunk);
 EXPORT_SYMBOL(ecard_address);
-
 EXPORT_SYMBOL(ecard_register_driver);
 EXPORT_SYMBOL(ecard_remove_driver);
-
 EXPORT_SYMBOL(ecard_bus_type);
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/kernel/irq.c	Sun Nov 17 20:30:02 2002
@@ -20,7 +20,6 @@
 #include <linux/config.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
@@ -661,7 +660,7 @@
 	unsigned int mask = 0, i;
 
 	spin_lock_irq(&irq_controller_lock);
-	for(i = 0; i < 16 && i < NR_IRQS; i++)
+	for (i = 0; i < 16 && i < NR_IRQS; i++)
 		if (irq_desc[i].probing && irq_desc[i].triggered)
 			mask |= 1 << i;
 	spin_unlock_irq(&irq_controller_lock);
diff -Nru a/arch/arm/kernel/plx90x0.c b/arch/arm/kernel/plx90x0.c
--- a/arch/arm/kernel/plx90x0.c	Sun Nov 17 20:30:04 2002
+++ b/arch/arm/kernel/plx90x0.c	Sun Nov 17 20:30:04 2002
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/kernel/setup.c	Sun Nov 17 20:30:14 2002
@@ -503,12 +503,12 @@
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = {
- orig_video_lines:	30,
- orig_video_cols:	80,
- orig_video_mode:	0,
- orig_video_ega_bx:	0,
- orig_video_isVGA:	1,
- orig_video_points:	8
+ .orig_video_lines	= 30,
+ .orig_video_cols	= 80,
+ .orig_video_mode	= 0,
+ .orig_video_ega_bx	= 0,
+ .orig_video_isVGA	= 1,
+ .orig_video_points	= 8
 };
 
 static int __init parse_tag_videotext(const struct tag *tag)
diff -Nru a/arch/arm/kernel/time-acorn.c b/arch/arm/kernel/time-acorn.c
--- a/arch/arm/kernel/time-acorn.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/kernel/time-acorn.c	Sun Nov 17 20:30:16 2002
@@ -12,7 +12,6 @@
  *   10-Oct-1996	RMK	Brought up to date with arch-sa110eval
  *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
  */
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/kernel/time.c	Sun Nov 17 20:30:15 2002
@@ -18,7 +18,6 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
diff -Nru a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c
--- a/arch/arm/kernel/via82c505.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/kernel/via82c505.c	Sun Nov 17 20:30:02 2002
@@ -1,5 +1,4 @@
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c
--- a/arch/arm/mach-adifcc/arch.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-adifcc/arch.c	Sun Nov 17 20:30:15 2002
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/major.h>
 #include <linux/fs.h>
-#include <asm/types.h>
+
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c
--- a/arch/arm/mach-adifcc/irq.c	Sun Nov 17 20:30:13 2002
+++ b/arch/arm/mach-adifcc/irq.c	Sun Nov 17 20:30:13 2002
@@ -13,7 +13,6 @@
  * support for PCI though.
  */
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-anakin/irq.c b/arch/arm/mach-anakin/irq.c
--- a/arch/arm/mach-anakin/irq.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-anakin/irq.c	Sun Nov 17 20:30:14 2002
@@ -12,7 +12,6 @@
  */
 
 #include <linux/ptrace.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/mach-arc/dma.c b/arch/arm/mach-arc/dma.c
--- a/arch/arm/mach-arc/dma.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-arc/dma.c	Sun Nov 17 20:30:15 2002
@@ -10,7 +10,6 @@
  *  DMA functions specific to Archimedes and A5000 architecture
  */
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
diff -Nru a/arch/arm/mach-arc/oldlatches.c b/arch/arm/mach-arc/oldlatches.c
--- a/arch/arm/mach-arc/oldlatches.c	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/mach-arc/oldlatches.c	Sun Nov 17 20:30:03 2002
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
--- a/arch/arm/mach-clps711x/autcpu12.c	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mach-clps711x/autcpu12.c	Sun Nov 17 20:30:12 2002
@@ -22,7 +22,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/blk.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
--- a/arch/arm/mach-clps711x/cdb89712.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-clps711x/cdb89712.c	Sun Nov 17 20:30:02 2002
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-clps711x/dma.c b/arch/arm/mach-clps711x/dma.c
--- a/arch/arm/mach-clps711x/dma.c	Sun Nov 17 20:30:13 2002
+++ b/arch/arm/mach-clps711x/dma.c	Sun Nov 17 20:30:13 2002
@@ -17,17 +17,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/mman.h>
 #include <linux/init.h>
 
-#include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-
 #include <asm/mach/dma.h>
 
 void __init arch_dma_init(dma_t *dma)
diff -Nru a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
--- a/arch/arm/mach-clps711x/fortunet.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-clps711x/fortunet.c	Sun Nov 17 20:30:14 2002
@@ -21,8 +21,6 @@
  */
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/blk.h>
 
@@ -32,7 +30,6 @@
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
-#include <asm/mach/amba_kmi.h>
 
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
diff -Nru a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c
--- a/arch/arm/mach-clps711x/mm.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-clps711x/mm.c	Sun Nov 17 20:30:15 2002
@@ -20,7 +20,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/config.h>
diff -Nru a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
--- a/arch/arm/mach-clps711x/p720t.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-clps711x/p720t.c	Sun Nov 17 20:30:14 2002
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
--- a/arch/arm/mach-clps711x/time.c	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/mach-clps711x/time.c	Sun Nov 17 20:30:03 2002
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/sched.h>
+#include <linux/timex.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-ebsa110/time.c b/arch/arm/mach-ebsa110/time.c
--- a/arch/arm/mach-ebsa110/time.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-ebsa110/time.c	Sun Nov 17 20:30:14 2002
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
diff -Nru a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c
--- a/arch/arm/mach-epxa10db/arch.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-epxa10db/arch.c	Sun Nov 17 20:30:14 2002
@@ -19,12 +19,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
diff -Nru a/arch/arm/mach-epxa10db/dma.c b/arch/arm/mach-epxa10db/dma.c
--- a/arch/arm/mach-epxa10db/dma.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-epxa10db/dma.c	Sun Nov 17 20:30:15 2002
@@ -18,17 +18,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/mman.h>
 #include <linux/init.h>
 
-#include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-
 #include <asm/mach/dma.h>
 
 void __init arch_dma_init(dma_t *dma)
diff -Nru a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c
--- a/arch/arm/mach-epxa10db/time.c	Sun Nov 17 20:30:04 2002
+++ b/arch/arm/mach-epxa10db/time.c	Sun Nov 17 20:30:04 2002
@@ -9,11 +9,9 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
-
 
 
 extern int (*set_rtc)(void);
diff -Nru a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
--- a/arch/arm/mach-footbridge/cats-hw.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-footbridge/cats-hw.c	Sun Nov 17 20:30:14 2002
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 1998, 1999 Russell King, Phil Blundell
  */
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
--- a/arch/arm/mach-footbridge/dc21285.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-footbridge/dc21285.c	Sun Nov 17 20:30:14 2002
@@ -8,7 +8,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
--- a/arch/arm/mach-footbridge/dma.c	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mach-footbridge/dma.c	Sun Nov 17 20:30:12 2002
@@ -11,7 +11,6 @@
  *			ISA DMA controllers.
  */
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
diff -Nru a/arch/arm/mach-footbridge/irq.c b/arch/arm/mach-footbridge/irq.c
--- a/arch/arm/mach-footbridge/irq.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/mach-footbridge/irq.c	Sun Nov 17 20:30:16 2002
@@ -14,9 +14,7 @@
  *   26-Jan-1999 PJB	Don't use IACK on CATS
  *   16-Mar-1999 RMK	Added autodetect of ISA PICs
  */
-#include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
--- a/arch/arm/mach-footbridge/isa-irq.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-footbridge/isa-irq.c	Sun Nov 17 20:30:15 2002
@@ -14,7 +14,6 @@
  *   26-Jan-1999 PJB	Don't use IACK on CATS
  *   16-Mar-1999 RMK	Added autodetect of ISA PICs
  */
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -102,7 +101,7 @@
 	desc->handle(isa_irq, desc, regs);
 }
 
-static struct irqaction irq_cascade = { handler: no_action, name: "cascade", };
+static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
 static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
 static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
 
diff -Nru a/arch/arm/mach-footbridge/mm.c b/arch/arm/mach-footbridge/mm.c
--- a/arch/arm/mach-footbridge/mm.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-footbridge/mm.c	Sun Nov 17 20:30:15 2002
@@ -11,7 +11,6 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
  
diff -Nru a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
--- a/arch/arm/mach-footbridge/netwinder-hw.c	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/mach-footbridge/netwinder-hw.c	Sun Nov 17 20:30:03 2002
@@ -7,7 +7,6 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
diff -Nru a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c
--- a/arch/arm/mach-ftvpci/core.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-ftvpci/core.c	Sun Nov 17 20:30:15 2002
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/mach-integrator/arch.c b/arch/arm/mach-integrator/arch.c
--- a/arch/arm/mach-integrator/arch.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-integrator/arch.c	Sun Nov 17 20:30:15 2002
@@ -19,8 +19,6 @@
  */
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-integrator/dma.c b/arch/arm/mach-integrator/dma.c
--- a/arch/arm/mach-integrator/dma.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-integrator/dma.c	Sun Nov 17 20:30:02 2002
@@ -18,7 +18,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c
--- a/arch/arm/mach-integrator/pci.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/mach-integrator/pci.c	Sun Nov 17 20:30:16 2002
@@ -21,7 +21,6 @@
  *
  *  PCI functions for Integrator
  */
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
--- a/arch/arm/mach-integrator/pci_v3.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-integrator/pci_v3.c	Sun Nov 17 20:30:15 2002
@@ -21,7 +21,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
--- a/arch/arm/mach-integrator/time.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-integrator/time.c	Sun Nov 17 20:30:14 2002
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-iop310/arch.c b/arch/arm/mach-iop310/arch.c
--- a/arch/arm/mach-iop310/arch.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-iop310/arch.c	Sun Nov 17 20:30:14 2002
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/major.h>
 #include <linux/fs.h>
-#include <asm/types.h>
+
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/memory.h>
diff -Nru a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c
--- a/arch/arm/mach-iop310/iop310-irq.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-iop310/iop310-irq.c	Sun Nov 17 20:30:15 2002
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c
--- a/arch/arm/mach-iop310/iop310-pci.c	Sun Nov 17 20:30:13 2002
+++ b/arch/arm/mach-iop310/iop310-pci.c	Sun Nov 17 20:30:13 2002
@@ -11,10 +11,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c
--- a/arch/arm/mach-iop310/iq80310-irq.c	Sun Nov 17 20:30:04 2002
+++ b/arch/arm/mach-iop310/iq80310-irq.c	Sun Nov 17 20:30:04 2002
@@ -14,10 +14,6 @@
  *     Moved demux from asm to C - DS
  *     Fixes for various revision boards - DS
  */
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
 #include <linux/init.h>
 
 #include <asm/irq.h>
diff -Nru a/arch/arm/mach-iop310/iq80310-time.c b/arch/arm/mach-iop310/iq80310-time.c
--- a/arch/arm/mach-iop310/iq80310-time.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-iop310/iq80310-time.c	Sun Nov 17 20:30:15 2002
@@ -11,14 +11,11 @@
  * published by the Free Software Foundation.
  *
  */
-#include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/timex.h>
-#include <linux/smp.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
diff -Nru a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c
--- a/arch/arm/mach-iop310/xs80200-irq.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-iop310/xs80200-irq.c	Sun Nov 17 20:30:14 2002
@@ -11,8 +11,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
diff -Nru a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
--- a/arch/arm/mach-pxa/dma.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/mach-pxa/dma.c	Sun Nov 17 20:30:16 2002
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 
 #include <asm/system.h>
diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
--- a/arch/arm/mach-pxa/idp.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-pxa/idp.c	Sun Nov 17 20:30:02 2002
@@ -17,9 +17,7 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 
-#include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
--- a/arch/arm/mach-pxa/irq.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-pxa/irq.c	Sun Nov 17 20:30:15 2002
@@ -14,7 +14,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
 
diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
--- a/arch/arm/mach-pxa/lubbock.c	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mach-pxa/lubbock.c	Sun Nov 17 20:30:12 2002
@@ -16,9 +16,7 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 
-#include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
diff -Nru a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
--- a/arch/arm/mach-pxa/pm.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-pxa/pm.c	Sun Nov 17 20:30:14 2002
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/errno.h>
diff -Nru a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
--- a/arch/arm/mach-rpc/dma.c	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/mach-rpc/dma.c	Sun Nov 17 20:30:16 2002
@@ -9,7 +9,6 @@
  *
  *  DMA functions specific to RiscPC architecture
  */
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
--- a/arch/arm/mach-sa1100/adsbitsy.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-sa1100/adsbitsy.c	Sun Nov 17 20:30:02 2002
@@ -11,8 +11,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
--- a/arch/arm/mach-sa1100/assabet.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-sa1100/assabet.c	Sun Nov 17 20:30:02 2002
@@ -13,7 +13,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/errno.h>
diff -Nru a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
--- a/arch/arm/mach-sa1100/dma.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mach-sa1100/dma.c	Sun Nov 17 20:30:02 2002
@@ -11,8 +11,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 
diff -Nru a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
--- a/arch/arm/mach-sa1100/flexanet.c	Sun Nov 17 20:30:13 2002
+++ b/arch/arm/mach-sa1100/flexanet.c	Sun Nov 17 20:30:13 2002
@@ -11,7 +11,6 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/errno.h>
diff -Nru a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
--- a/arch/arm/mach-sa1100/graphicsclient.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-sa1100/graphicsclient.c	Sun Nov 17 20:30:15 2002
@@ -11,8 +11,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ptrace.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
--- a/arch/arm/mach-sa1100/graphicsmaster.c	Sun Nov 17 20:30:13 2002
+++ b/arch/arm/mach-sa1100/graphicsmaster.c	Sun Nov 17 20:30:13 2002
@@ -9,8 +9,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 
diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
--- a/arch/arm/mach-sa1100/h3600.c	Sun Nov 17 20:30:04 2002
+++ b/arch/arm/mach-sa1100/h3600.c	Sun Nov 17 20:30:04 2002
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
-#include <linux/sched.h>
 #include <linux/pm.h>
 #include <linux/serial_core.h>
 
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-sa1100/irq.c	Sun Nov 17 20:30:15 2002
@@ -11,8 +11,6 @@
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/ptrace.h>
 
diff -Nru a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
--- a/arch/arm/mach-sa1100/neponset.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-sa1100/neponset.c	Sun Nov 17 20:30:14 2002
@@ -4,8 +4,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
--- a/arch/arm/mach-sa1100/pm.c	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mach-sa1100/pm.c	Sun Nov 17 20:30:12 2002
@@ -26,8 +26,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/errno.h>
 #include <linux/device.h>
diff -Nru a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
--- a/arch/arm/mach-sa1100/sa1111.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-sa1100/sa1111.c	Sun Nov 17 20:30:15 2002
@@ -18,8 +18,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
diff -Nru a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c
--- a/arch/arm/mach-sa1100/stork.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-sa1100/stork.c	Sun Nov 17 20:30:15 2002
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-sa1100/system3.c	Sun Nov 17 20:30:15 2002
@@ -37,7 +37,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/errno.h>
diff -Nru a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c
--- a/arch/arm/mach-shark/dma.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mach-shark/dma.c	Sun Nov 17 20:30:14 2002
@@ -9,12 +9,9 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
-#include <asm/io.h>
-
 #include <asm/mach/dma.h>
 
 void __init arch_dma_init(dma_t *dma)
diff -Nru a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c
--- a/arch/arm/mach-tbox/core.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mach-tbox/core.c	Sun Nov 17 20:30:15 2002
@@ -7,7 +7,6 @@
  *  Extra MM routines for the Tbox architecture
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
--- a/arch/arm/mm/Makefile	Sun Nov 17 20:30:16 2002
+++ b/arch/arm/mm/Makefile	Sun Nov 17 20:30:16 2002
@@ -22,24 +22,21 @@
 p-$(CONFIG_CPU_26)	+= proc-arm2_3.o
 
 # ARMv3
-p-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o  tlb-v3.o   copypage-v3.o
-p-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o  tlb-v3.o   copypage-v3.o
+p-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o  tlb-v3.o    copypage-v3.o
+p-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o  tlb-v3.o    copypage-v3.o
 
 # ARMv4
-p-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o  tlb-v4.o   copypage-v4wt.o abort-lv4t.o
-p-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o  tlb-v4wb.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o  tlb-v4wb.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o tlb-v4wb.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_SA110)	+= proc-sa110.o   tlb-v4wb.o copypage-v4wb.o abort-ev4.o   minicache.o
-p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o   tlb-v4wb.o copypage-v4mc.o abort-ev4.o   minicache.o
+p-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o  tlb-v4.o    copypage-v4wt.o abort-lv4t.o
+p-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o  tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o  tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_SA110)	+= proc-sa110.o   tlb-v4wb.o  copypage-v4wb.o abort-ev4.o   minicache.o
+p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o   tlb-v4wb.o  copypage-v4mc.o abort-ev4.o   minicache.o
 
 # ARMv5
-p-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o  tlb-v4wb.o copypage-v4wb.o abort-ev5tej.o
-p-$(CONFIG_CPU_XSCALE)	+= proc-xscale.o  tlb-v4wb.o copypage-xscale.o abort-xscale.o minicache.o
+p-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o  tlb-v4wbi.o copypage-v4wb.o abort-ev5tej.o
+p-$(CONFIG_CPU_XSCALE)	+= proc-xscale.o  tlb-v4wbi.o copypage-xscale.o abort-xscale.o minicache.o
 
 obj-y		+= $(sort $(p-y))
 
 include $(TOPDIR)/Rules.make
-
-# Special dependencies
-$(obj)/$(p-y):	include/asm-arm/constants.h
diff -Nru a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
--- a/arch/arm/mm/alignment.c	Sun Nov 17 20:30:03 2002
+++ b/arch/arm/mm/alignment.c	Sun Nov 17 20:30:03 2002
@@ -11,7 +11,6 @@
 #include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -19,7 +18,6 @@
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
-#include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mm/discontig.c b/arch/arm/mm/discontig.c
--- a/arch/arm/mm/discontig.c	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mm/discontig.c	Sun Nov 17 20:30:15 2002
@@ -26,10 +26,10 @@
 static bootmem_data_t node_bootmem_data[NR_NODES];
 
 pg_data_t discontig_node_data[NR_NODES] = {
-  { bdata: &node_bootmem_data[0] },
-  { bdata: &node_bootmem_data[1] },
-  { bdata: &node_bootmem_data[2] },
-  { bdata: &node_bootmem_data[3] }
+  { .bdata = &node_bootmem_data[0] },
+  { .bdata = &node_bootmem_data[1] },
+  { .bdata = &node_bootmem_data[2] },
+  { .bdata = &node_bootmem_data[3] }
 };
 
 EXPORT_SYMBOL(discontig_node_data);
diff -Nru a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
--- a/arch/arm/mm/fault-armv.c	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mm/fault-armv.c	Sun Nov 17 20:30:12 2002
@@ -131,21 +131,22 @@
  * We take the easy way out of this problem - we make the
  * PTE uncacheable.  However, we leave the write buffer on.
  */
-static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
+static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte, entry;
+	int ret = 0;
 
 	pgd = pgd_offset(vma->vm_mm, address);
 	if (pgd_none(*pgd))
-		return;
+		goto no_pgd;
 	if (pgd_bad(*pgd))
 		goto bad_pgd;
 
 	pmd = pmd_offset(pgd, address);
 	if (pmd_none(*pmd))
-		return;
+		goto no_pmd;
 	if (pmd_bad(*pmd))
 		goto bad_pmd;
 
@@ -161,23 +162,64 @@
 		pte_val(entry) &= ~L_PTE_CACHEABLE;
 		set_pte(pte, entry);
 		flush_tlb_page(vma, address);
+		ret = 1;
 	}
 	pte_unmap(pte);
-	return;
+	return ret;
 
 bad_pgd:
 	pgd_ERROR(*pgd);
 	pgd_clear(pgd);
-	return;
+no_pgd:
+	return 0;
 
 bad_pmd:
 	pmd_ERROR(*pmd);
 	pmd_clear(pmd);
-	return;
+no_pmd:
+	return 0;
+}
+
+void __flush_dcache_page(struct page *page)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct list_head *l;
+	unsigned long kaddr = (unsigned long)page_address(page);
+
+	cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0);
+
+	if (!page->mapping)
+		return;
+
+	/*
+	 * With a VIVT cache, we need to also write back
+	 * and invalidate any user data.
+	 */
+	list_for_each(l, &page->mapping->i_mmap_shared) {
+		struct vm_area_struct *mpnt;
+		unsigned long off;
+
+		mpnt = list_entry(l, struct vm_area_struct, shared);
+
+		/*
+		 * If this VMA is not in our MM, we can ignore it.
+		 */
+		if (mpnt->vm_mm != mm)
+			continue;
+
+		if (page->index < mpnt->vm_pgoff)
+			continue;
+
+		off = page->index - mpnt->vm_pgoff;
+		if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
+			continue;
+
+		flush_cache_page(mpnt, off);
+	}
 }
 
 static void
-make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
+make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
 {
 	struct list_head *l;
 	struct mm_struct *mm = vma->vm_mm;
@@ -213,14 +255,17 @@
 		if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
 			continue;
 
+		off = mpnt->vm_start + (off << PAGE_SHIFT);
+
 		/*
 		 * Ok, it is within mpnt.  Fix it up.
 		 */
-		adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
-		aliases ++;
+		aliases += adjust_pte(mpnt, off);
 	}
 	if (aliases)
 		adjust_pte(vma, addr);
+	else
+		flush_cache_page(vma, addr);
 }
 
 /*
@@ -245,9 +290,12 @@
 		return;
 	page = pfn_to_page(pfn);
 	if (page->mapping) {
-		if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
-			__flush_dcache_page(page);
+		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
+		unsigned long kaddr = (unsigned long)page_address(page);
+
+		if (dirty)
+			cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0);
 
-		make_coherent(vma, addr, page);
+		make_coherent(vma, addr, page, dirty);
 	}
 }
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mm/init.c	Sun Nov 17 20:30:02 2002
@@ -9,7 +9,6 @@
  */
 #include <linux/config.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
--- a/arch/arm/mm/mm-armv.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mm/mm-armv.c	Sun Nov 17 20:30:14 2002
@@ -9,7 +9,6 @@
  *
  *  Page table sludge for ARM v3 and v4 processor architectures.
  */
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
@@ -166,14 +165,13 @@
 static inline void
 alloc_init_section(unsigned long virt, unsigned long phys, int prot)
 {
-	pmd_t *pmdp, pmd;
+	pmd_t *pmdp;
 
 	pmdp = pmd_offset(pgd_offset_k(virt), virt);
 	if (virt & (1 << 20))
 		pmdp++;
 
-	pmd_val(pmd) = phys | prot;
-	set_pmd(pmdp, pmd);
+	set_pmd(pmdp, __pmd(phys | prot));
 }
 
 /*
@@ -186,19 +184,20 @@
 static inline void
 alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
 {
-	pmd_t *pmdp, pmd;
+	pmd_t *pmdp;
 	pte_t *ptep;
 
 	pmdp = pmd_offset(pgd_offset_k(virt), virt);
 
 	if (pmd_none(*pmdp)) {
+		unsigned long pmdval;
 		ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
 					       sizeof(pte_t));
 
-		pmd_val(pmd) = __pa(ptep) | prot_l1;
-		set_pmd(pmdp, pmd);
-		pmd_val(pmd) += 256 * sizeof(pte_t);
-		set_pmd(pmdp + 1, pmd);
+		pmdval = __pa(ptep) | prot_l1;
+		pmdp[0] = __pmd(pmdval);
+		pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
+		cpu_flush_pmd(pmdp);
 	}
 	ptep = pte_offset_kernel(pmdp, virt);
 
@@ -360,8 +359,9 @@
  */
 void setup_mm_for_reboot(char mode)
 {
+	unsigned long pmdval;
 	pgd_t *pgd;
-	pmd_t pmd;
+	pmd_t *pmd;
 	int i;
 
 	if (current->mm && current->mm->pgd)
@@ -370,10 +370,11 @@
 		pgd = init_mm.pgd;
 
 	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
-		pmd_val(pmd) = (i << PGDIR_SHIFT) |
-			PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
-			PMD_TYPE_SECT;
-		set_pmd(pmd_offset(pgd + i, i << PGDIR_SHIFT), pmd);
+		pmdval = (i << PGDIR_SHIFT) |
+			 PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
+			 PMD_BIT4 | PMD_TYPE_SECT;
+		pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+		set_pmd(pmd, __pmd(pmdval));
 	}
 }
 
diff -Nru a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
--- a/arch/arm/mm/proc-arm1020.S	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mm/proc-arm1020.S	Sun Nov 17 20:30:02 2002
@@ -365,17 +365,15 @@
 	mov	pc, lr
         
 /*
- * cpu_arm1020_set_pmd(pmdp, pmd)
+ * cpu_arm1020_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_arm1020_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_arm1020_flush_pmd)
 #ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r0, c7, c10, 4
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  (drain is done by TLB fns)
@@ -515,7 +513,7 @@
 
 	/* pgtable */
 	.word	cpu_arm1020_set_pgd
-	.word	cpu_arm1020_set_pmd
+	.word	cpu_arm1020_flush_pmd
 	.word	cpu_arm1020_set_pte
 
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
diff -Nru a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
--- a/arch/arm/mm/proc-arm6_7.S	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mm/proc-arm6_7.S	Sun Nov 17 20:30:15 2002
@@ -234,34 +234,14 @@
 		mov	pc, lr
 
 /*
- * Function: arm6_set_pmd ()
+ * Function: arm6_flush_pmd(pmdp)
  *
  * Params  : r0 = Address to set
- *	   : r1 = value to set
- *
- * Purpose : Set a PMD and flush it out of any WB cache
- */
-ENTRY(cpu_arm6_set_pmd)
-		and	r2, r1, #11
-		teq	r2, #1
-		teqne	r2, #9
-		teqne	r2, #10
-		orreq	r1, r1, #16			@ Updatable = 1 if Page table/Cacheable section
-		str	r1, [r0]
-		mov	pc, lr
-
-/*
- * Function: arm7_set_pmd ()
- *
- * Params  : r0 = Address to set
- *	   : r1 = value to set
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-ENTRY(cpu_arm7_set_pmd)
-		tst	r1, #3
-		orrne	r1, r1, #16			@ Updatable bit is always set on ARM7
-		str	r1, [r0]
+ENTRY(cpu_arm6_flush_pmd)
+ENTRY(cpu_arm7_flush_pmd)
 		mov	pc, lr
 
 /*
@@ -368,7 +348,7 @@
 
 		/* pgtable */
 		.word	cpu_arm6_set_pgd
-		.word	cpu_arm6_set_pmd
+		.word	cpu_arm6_flush_pmd
 		.word	cpu_arm6_set_pte
 
 		.size	arm6_processor_functions, . - arm6_processor_functions
@@ -402,7 +382,7 @@
 
 		/* pgtable */
 		.word	cpu_arm7_set_pgd
-		.word	cpu_arm7_set_pmd
+		.word	cpu_arm7_flush_pmd
 		.word	cpu_arm7_set_pte
 
 		.size	arm7_processor_functions, . - arm7_processor_functions
diff -Nru a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
--- a/arch/arm/mm/proc-arm720.S	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mm/proc-arm720.S	Sun Nov 17 20:30:14 2002
@@ -115,17 +115,13 @@
 		mov	pc, lr
 
 /*
- * Function: arm720_set_pmd ()
+ * Function: arm720_flush_pmd(pmdp)
  *
  * Params  : r0 = Address to set
- *	   : r1 = value to set
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-ENTRY(cpu_arm720_set_pmd)
-		tst	r1, #3
-		orrne	r1, r1, #16			@ Updatable bit is
-		str	r1, [r0]			@ always set on ARM720
+ENTRY(cpu_arm720_flush_pmd)
 		mov	pc, lr
 
 /*
@@ -222,7 +218,7 @@
 
 		/* pgtable */
 		.word	cpu_arm720_set_pgd
-		.word	cpu_arm720_set_pmd
+		.word	cpu_arm720_flush_pmd
 		.word	cpu_arm720_set_pte
 
 		.size	arm720_processor_functions, . - arm720_processor_functions
diff -Nru a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
--- a/arch/arm/mm/proc-arm920.S	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/mm/proc-arm920.S	Sun Nov 17 20:30:02 2002
@@ -368,17 +368,15 @@
 	mov	pc, lr
 
 /*
- * cpu_arm920_set_pmd(pmdp, pmd)
+ * cpu_arm920_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_arm920_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_arm920_flush_pmd)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
@@ -503,7 +501,7 @@
 
 	/* pgtable */
 	.word	cpu_arm920_set_pgd
-	.word	cpu_arm920_set_pmd
+	.word	cpu_arm920_flush_pmd
 	.word	cpu_arm920_set_pte
 
 	.size	arm920_processor_functions, . - arm920_processor_functions
diff -Nru a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
--- a/arch/arm/mm/proc-arm922.S	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mm/proc-arm922.S	Sun Nov 17 20:30:15 2002
@@ -369,17 +369,15 @@
 	mov	pc, lr
 
 /*
- * cpu_arm922_set_pmd(pmdp, pmd)
+ * cpu_arm922_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_arm922_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_arm922_flush_pmd)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
@@ -502,7 +500,7 @@
 
 	/* pgtable */
 	.word	cpu_arm922_set_pgd
-	.word	cpu_arm922_set_pmd
+	.word	cpu_arm922_flush_pmd
 	.word	cpu_arm922_set_pte
 
 	.size	arm922_processor_functions, . - arm922_processor_functions
diff -Nru a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
--- a/arch/arm/mm/proc-arm926.S	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mm/proc-arm926.S	Sun Nov 17 20:30:14 2002
@@ -350,17 +350,15 @@
 	mov	pc, lr
 
 /*
- * cpu_arm926_set_pmd(pmdp, pmd)
+ * cpu_arm926_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_arm926_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_arm926_flush_pmd)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
@@ -500,7 +498,7 @@
 
 	/* pgtable */
 	.word	cpu_arm926_set_pgd
-	.word	cpu_arm926_set_pmd
+	.word	cpu_arm926_flush_pmd
 	.word	cpu_arm926_set_pte
 
 	.size	arm926_processor_functions, . - arm926_processor_functions
diff -Nru a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
--- a/arch/arm/mm/proc-sa110.S	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mm/proc-sa110.S	Sun Nov 17 20:30:14 2002
@@ -425,18 +425,16 @@
 	mov	pc, lr
 
 /*
- * cpu_sa110_set_pmd(pmdp, pmd)
+ * cpu_sa110_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_sa110_set_pmd)
-ENTRY(cpu_sa1100_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_sa110_flush_pmd)
+ENTRY(cpu_sa1100_flush_pmd)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
@@ -544,7 +542,7 @@
 
 	/* pgtable */
 	.word	cpu_sa110_set_pgd
-	.word	cpu_sa110_set_pmd
+	.word	cpu_sa110_flush_pmd
 	.word	cpu_sa110_set_pte
 
 	.size	sa110_processor_functions, . - sa110_processor_functions
@@ -584,7 +582,7 @@
 
 	/* pgtable */
 	.word	cpu_sa1100_set_pgd
-	.word	cpu_sa1100_set_pmd
+	.word	cpu_sa1100_flush_pmd
 	.word	cpu_sa1100_set_pte
 
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
diff -Nru a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
--- a/arch/arm/mm/proc-syms.c	Sun Nov 17 20:30:14 2002
+++ b/arch/arm/mm/proc-syms.c	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mm/proc-syms.c
  *
- *  Copyright (C) 2000 Russell King
+ *  Copyright (C) 2000-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +15,8 @@
 #include <asm/proc-fns.h>
 #include <asm/tlbflush.h>
 
+EXPORT_SYMBOL(__flush_dcache_page);
+
 #ifndef MULTI_CPU
 EXPORT_SYMBOL(cpu_cache_clean_invalidate_all);
 EXPORT_SYMBOL(cpu_cache_clean_invalidate_range);
@@ -25,7 +27,7 @@
 EXPORT_SYMBOL(cpu_icache_invalidate_range);
 EXPORT_SYMBOL(cpu_icache_invalidate_page);
 EXPORT_SYMBOL(cpu_set_pgd);
-EXPORT_SYMBOL(cpu_set_pmd);
+EXPORT_SYMBOL(cpu_flush_pmd);
 EXPORT_SYMBOL(cpu_set_pte);
 #else
 EXPORT_SYMBOL(processor);
diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
--- a/arch/arm/mm/proc-xscale.S	Sun Nov 17 20:30:15 2002
+++ b/arch/arm/mm/proc-xscale.S	Sun Nov 17 20:30:15 2002
@@ -573,17 +573,15 @@
 	cpwait_ret lr, ip
 
 /*
- * cpu_xscale_set_pmd(pmdp, pmd)
+ * cpu_xscale_flush_pmd(pmdp)
  *
  * Set a level 1 translation table entry, and clean it out of
  * any caches such that the MMUs can load it correctly.
  *
  * pmdp: pointer to PMD entry
- * pmd:  PMD value to store
  */
 	.align	5
-ENTRY(cpu_xscale_set_pmd)
-	str	r1, [r0]
+ENTRY(cpu_xscale_flush_pmd)
 	mov	ip, #0
 	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
 	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
@@ -721,7 +719,7 @@
 
 	/* pgtable */
 	.word	cpu_xscale_set_pgd
-	.word	cpu_xscale_set_pmd
+	.word	cpu_xscale_flush_pmd
 	.word	cpu_xscale_set_pte
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
diff -Nru a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
--- a/arch/arm/mm/tlb-v4wb.S	Sun Nov 17 20:30:12 2002
+++ b/arch/arm/mm/tlb-v4wb.S	Sun Nov 17 20:30:12 2002
@@ -7,10 +7,10 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  ARM architecture version 4 and version 5 TLB handling functions.
- *  These assume a split I/D TLBs, with a write buffer.
+ *  ARM architecture version 4 TLB handling functions.
+ *  These assume a split I/D TLBs w/o I TLB entry, with a write buffer.
  *
- *  Processors: ARM920 ARM922 ARM926 SA110 SA1100 SA1110 XScale
+ *  Processors: SA110 SA1100 SA1110
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
@@ -67,50 +67,6 @@
 	blo	1b
 	mov	pc, lr
 
-/*
- * These two are optimised for ARM920, ARM922, ARM926, Xscale
- */
-
-/*
- *	v4wb_flush_user_tlb_range(start, end, mm)
- *
- *	Invalidate a range of TLB entries in the specified address space.
- *
- *	- start - range start address
- *	- end   - range end address
- *	- mm    - mm_struct describing address space
- */
-	.align	5
-ENTRY(v4wbi_flush_user_tlb_range)
-	vma_vm_mm ip, r2
-	act_mm	r3				@ get current->active_mm
-	eors	r3, ip, r3			@ == mm ?
-	movne	pc, lr				@ no, we dont do anything
-	mov	r3, #0
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	vma_vm_flags r2, r2
-	bic	r0, r0, #0x0ff
-	bic	r0, r0, #0xf00
-1:	tst	r2, #VM_EXEC
-	mcrne	p15, 0, r0, c8, c5, 1		@ invalidate I TLB entry
-	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
-	add	r0, r0, #PAGE_SZ
-	cmp	r0, r1
-	blo	1b
-	mov	pc, lr
-
-ENTRY(v4wbi_flush_kern_tlb_range)
-	mov	r3, #0
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	bic	r0, r0, #0x0ff
-	bic	r0, r0, #0xf00
-1:	mcr	p15, 0, r0, c8, c5, 1		@ invalidate I TLB entry
-	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
-	add	r0, r0, #PAGE_SZ
-	cmp	r0, r1
-	blo	1b
-	mov	pc, lr
-
 	__INIT
 
 	.type	v4wb_tlb_fns, #object
@@ -119,10 +75,3 @@
 	.long	v4wb_flush_kern_tlb_range
 	.long	v4wb_tlb_flags
 	.size	v4wb_tlb_fns, . - v4wb_tlb_fns
-
-	.type	v4wbi_tlb_fns, #object
-ENTRY(v4wbi_tlb_fns)
-	.long	v4wbi_flush_user_tlb_range
-	.long	v4wbi_flush_kern_tlb_range
-	.long	v4wbi_tlb_flags
-	.size	v4wbi_tlb_fns, . - v4wbi_tlb_fns
diff -Nru a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mm/tlb-v4wbi.S	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,68 @@
+/*
+ *  linux/arch/arm/mm/tlbv4wbi.S
+ *
+ *  Copyright (C) 1997-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ARM architecture version 4 and version 5 TLB handling functions.
+ *  These assume a split I/D TLBs, with a write buffer.
+ *
+ *  Processors: ARM920 ARM922 ARM926 XScale
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/constants.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ *	v4wb_flush_user_tlb_range(start, end, mm)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - range start address
+ *	- end   - range end address
+ *	- mm    - mm_struct describing address space
+ */
+	.align	5
+ENTRY(v4wbi_flush_user_tlb_range)
+	vma_vm_mm ip, r2
+	act_mm	r3				@ get current->active_mm
+	eors	r3, ip, r3			@ == mm ?
+	movne	pc, lr				@ no, we dont do anything
+	mov	r3, #0
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+	vma_vm_flags r2, r2
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+1:	tst	r2, #VM_EXEC
+	mcrne	p15, 0, r0, c8, c5, 1		@ invalidate I TLB entry
+	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mov	pc, lr
+
+ENTRY(v4wbi_flush_kern_tlb_range)
+	mov	r3, #0
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+1:	mcr	p15, 0, r0, c8, c5, 1		@ invalidate I TLB entry
+	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mov	pc, lr
+
+	__INIT
+
+	.type	v4wbi_tlb_fns, #object
+ENTRY(v4wbi_tlb_fns)
+	.long	v4wbi_flush_user_tlb_range
+	.long	v4wbi_flush_kern_tlb_range
+	.long	v4wbi_tlb_flags
+	.size	v4wbi_tlb_fns, . - v4wbi_tlb_fns
diff -Nru a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
--- a/arch/arm/tools/Makefile	Sun Nov 17 20:30:02 2002
+++ b/arch/arm/tools/Makefile	Sun Nov 17 20:30:02 2002
@@ -4,9 +4,6 @@
 # Copyright (C) 2001 Russell King
 #
 
-include $(TOPDIR)/Rules.make
-
 include/asm-arm/mach-types.h: $(obj)/mach-types $(obj)/gen-mach-types
 	@echo '  Generating $@'
-	@awk -f $(obj)/gen-mach-types $(obj)/mach-types > $@
-
+	@$(AWK) -f $(obj)/gen-mach-types $(obj)/mach-types > $@
diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig
--- a/arch/cris/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/cris/Kconfig	Sun Nov 17 20:30:15 2002
@@ -589,7 +589,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/cris/drivers/axisflashmap.c b/arch/cris/drivers/axisflashmap.c
--- a/arch/cris/drivers/axisflashmap.c	Sun Nov 17 20:30:15 2002
+++ b/arch/cris/drivers/axisflashmap.c	Sun Nov 17 20:30:15 2002
@@ -151,16 +151,16 @@
 }
 
 static struct map_info axis_map = {
-	name: "Axis flash",
-	size: WINDOW_SIZE,
-	buswidth: CONFIG_ETRAX_FLASH_BUSWIDTH,
-	read8: flash_read8,
-	read16: flash_read16,
-	read32: flash_read32,
-	copy_from: flash_copy_from,
-	write8: flash_write8,
-	write16: flash_write16,
-	write32: flash_write32,
+	.name = "Axis flash",
+	.size = WINDOW_SIZE,
+	.buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
+	.read8 = flash_read8,
+	.read16 = flash_read16,
+	.read32 = flash_read32,
+	.copy_from = flash_copy_from,
+	.write8 = flash_write8,
+	.write16 = flash_write16,
+	.write32 = flash_write32,
 };
 
 /* If no partition-table was found, we use this default-set.
@@ -175,57 +175,57 @@
  */
 static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
 	{
-		name: "boot firmware",
-		size: CONFIG_ETRAX_PTABLE_SECTOR,
-		offset: 0
+		.name = "boot firmware",
+		.size = CONFIG_ETRAX_PTABLE_SECTOR,
+		.offset = 0
 	},
 	{
-		name: "kernel",
-		size: 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
-		offset: CONFIG_ETRAX_PTABLE_SECTOR
+		.name = "kernel",
+		.size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
+		.offset = CONFIG_ETRAX_PTABLE_SECTOR
 	},
 	{
-		name: "filesystem",
-		size: 5 * CONFIG_ETRAX_PTABLE_SECTOR,
-		offset: 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
+		.name = "filesystem",
+		.size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
+		.offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
 	}
 };
 
 static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
 	{
-		name: "part0",
-		size: 0,
-		offset: 0
+		.name = "part0",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part1",
-		size: 0,
-		offset: 0
+		.name = "part1",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part2",
-		size: 0,
-		offset: 0
+		.name = "part2",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part3",
-		size: 0,
-		offset: 0
+		.name = "part3",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part4",
-		size: 0,
-		offset: 0
+		.name = "part4",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part5",
-		size: 0,
-		offset: 0
+		.name = "part5",
+		.size = 0,
+		.offset = 0
 	},
 	{
-		name: "part6",
-		size: 0,
-		offset: 0
+		.name = "part6",
+		.size = 0,
+		.offset = 0
 	},
 };
 
diff -Nru a/arch/cris/drivers/ds1302.c b/arch/cris/drivers/ds1302.c
--- a/arch/cris/drivers/ds1302.c	Sun Nov 17 20:30:15 2002
+++ b/arch/cris/drivers/ds1302.c	Sun Nov 17 20:30:15 2002
@@ -479,8 +479,8 @@
 /* The various file operations we support. */
 
 static struct file_operations rtc_fops = {
-        owner:          THIS_MODULE,
-        ioctl:          rtc_ioctl,	
+        .owner          = THIS_MODULE,
+        .ioctl          = rtc_ioctl,	
 }; 
 
 /* Just probe for the RTC and register the device to handle the ioctl needed. */
diff -Nru a/arch/cris/drivers/eeprom.c b/arch/cris/drivers/eeprom.c
--- a/arch/cris/drivers/eeprom.c	Sun Nov 17 20:30:12 2002
+++ b/arch/cris/drivers/eeprom.c	Sun Nov 17 20:30:12 2002
@@ -149,11 +149,11 @@
 /* This is the exported file-operations structure for this device. */
 struct file_operations eeprom_fops =
 {
-  llseek:  eeprom_lseek,
-  read:    eeprom_read,
-  write:   eeprom_write,
-  open:    eeprom_open,
-  release: eeprom_close
+  .llseek  = eeprom_lseek,
+  .read    = eeprom_read,
+  .write   = eeprom_write,
+  .open    = eeprom_open,
+  .release = eeprom_close
 };
 
 /* eeprom init call. Probes for different eeprom models. */
diff -Nru a/arch/cris/drivers/gpio.c b/arch/cris/drivers/gpio.c
--- a/arch/cris/drivers/gpio.c	Sun Nov 17 20:30:02 2002
+++ b/arch/cris/drivers/gpio.c	Sun Nov 17 20:30:02 2002
@@ -407,12 +407,12 @@
 }
 
 struct file_operations gpio_fops = {
-	owner:       THIS_MODULE,
-	poll:        gpio_poll,
-	ioctl:       gpio_ioctl,
-	write:       gpio_write,
-	open:        gpio_open,
-	release:     gpio_release,
+	.owner       = THIS_MODULE,
+	.poll        = gpio_poll,
+	.ioctl       = gpio_ioctl,
+	.write       = gpio_write,
+	.open        = gpio_open,
+	.release     = gpio_release,
 };
 
 /* main driver initialization routine, called from mem.c */
diff -Nru a/arch/cris/drivers/i2c.c b/arch/cris/drivers/i2c.c
--- a/arch/cris/drivers/i2c.c	Sun Nov 17 20:30:02 2002
+++ b/arch/cris/drivers/i2c.c	Sun Nov 17 20:30:02 2002
@@ -654,10 +654,10 @@
 }
 
 static struct file_operations i2c_fops = {
-	owner:    THIS_MODULE,
-	ioctl:    i2c_ioctl,
-	open:     i2c_open,
-	release:  i2c_release,
+	.owner    = THIS_MODULE,
+	.ioctl    = i2c_ioctl,
+	.open     = i2c_open,
+	.release  = i2c_release,
 };
 
 static int __init
diff -Nru a/arch/cris/drivers/sync_serial.c b/arch/cris/drivers/sync_serial.c
--- a/arch/cris/drivers/sync_serial.c	Sun Nov 17 20:30:03 2002
+++ b/arch/cris/drivers/sync_serial.c	Sun Nov 17 20:30:03 2002
@@ -177,12 +177,12 @@
 #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
 
 static struct file_operations sync_serial_fops = {
-       owner:	THIS_MODULE,
-       write:	sync_serial_write,
-       read:	sync_serial_read,
-       ioctl:	sync_serial_ioctl,
-       open:	sync_serial_open,
-       release: sync_serial_release
+       .owner	= THIS_MODULE,
+       .write	= sync_serial_write,
+       .read	= sync_serial_read,
+       .ioctl	= sync_serial_ioctl,
+       .open	= sync_serial_open,
+       .release = sync_serial_release
 };
 
 static int __init etrax_sync_serial_init(void)
diff -Nru a/arch/cris/kernel/debugport.c b/arch/cris/kernel/debugport.c
--- a/arch/cris/kernel/debugport.c	Sun Nov 17 20:30:02 2002
+++ b/arch/cris/kernel/debugport.c	Sun Nov 17 20:30:02 2002
@@ -227,16 +227,16 @@
 }
 
 static struct console sercons = {
-        name:    "ttyS",
-        write:   console_write,
-        read:    NULL,
-        device:  console_device,
-        unblank: NULL,
-	setup:   console_setup,
-	flags:   CON_PRINTBUFFER,
-	index:   DEBUG_PORT_IDX,
-	cflag:   0,
-	next:    NULL
+        .name    = "ttyS",
+        .write   = console_write,
+        .read    = NULL,
+        .device  = console_device,
+        .unblank = NULL,
+	.setup   = console_setup,
+	.flags   = CON_PRINTBUFFER,
+	.index   = DEBUG_PORT_IDX,
+	.cflag   = 0,
+	.next    = NULL
 };
 
 /*
diff -Nru a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
--- a/arch/cris/kernel/setup.c	Sun Nov 17 20:30:15 2002
+++ b/arch/cris/kernel/setup.c	Sun Nov 17 20:30:15 2002
@@ -280,10 +280,10 @@
 }
 
 struct seq_operations cpuinfo_op = {
-	start:  c_start,
-	next:   c_next,
-	stop:   c_stop,
-	show:   show_cpuinfo,
+	.start  = c_start,
+	.next   = c_next,
+	.stop   = c_stop,
+	.show   = show_cpuinfo,
 };
 
 #endif /* CONFIG_PROC_FS */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Sun Nov 17 20:30:03 2002
+++ b/arch/i386/Kconfig	Sun Nov 17 20:30:03 2002
@@ -1298,7 +1298,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -1604,13 +1604,14 @@
 	  This options enables addition error checking for high memory systems.
 	  Disable for production systems.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
+# Reimplemented RSN.
+#config KALLSYMS
+#	bool "Load all symbols for debugging/kksymoops"
+#	depends on DEBUG_KERNEL
+#	help
+#	  Say Y here to let the kernel print out symbolic crash information and
+#	  symbolic stack backtraces. This increases the size of the kernel
+#	  somewhat, as all symbols have to be loaded into the kernel image.
 
 config X86_EXTRA_IRQS
 	bool
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/kernel/Makefile	Sun Nov 17 20:30:04 2002
@@ -24,10 +24,11 @@
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o suspend_asm.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_PROFILING)		+= profile.o
 obj-$(CONFIG_EDD)             	+= edd.o
+obj-$(CONFIG_MODULES)		+= module.o
 
 EXTRA_AFLAGS   := -traditional
 
diff -Nru a/arch/i386/kernel/acpi_wakeup.S b/arch/i386/kernel/acpi_wakeup.S
--- a/arch/i386/kernel/acpi_wakeup.S	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/kernel/acpi_wakeup.S	Sun Nov 17 20:30:04 2002
@@ -262,6 +262,48 @@
 
 ENTRY(saved_magic)	.long	0
 
+ENTRY(do_suspend_lowlevel)
+	cmpl $0,4(%esp)
+	jne .L1432
+	call save_processor_state
+
+	movl %esp, saved_context_esp
+	movl %eax, saved_context_eax
+	movl %ebx, saved_context_ebx
+	movl %ecx, saved_context_ecx
+	movl %edx, saved_context_edx
+	movl %ebp, saved_context_ebp
+	movl %esi, saved_context_esi
+	movl %edi, saved_context_edi
+	pushfl ; popl saved_context_eflags
+
+	movl $.L1432,saved_eip
+	movl %esp,saved_esp
+	movl %ebp,saved_ebp
+	movl %ebx,saved_ebx
+	movl %edi,saved_edi
+	movl %esi,saved_esi
+
+	pushl $3
+	call acpi_enter_sleep_state
+	addl $4,%esp
+	ret
+	.p2align 4,,7
+.L1432:
+	movl $104,%eax
+	movw %eax, %ds
+	movl saved_context_esp, %esp
+	movl saved_context_ebp, %ebp
+	movl saved_context_eax, %eax
+	movl saved_context_ebx, %ebx
+	movl saved_context_ecx, %ecx
+	movl saved_context_edx, %edx
+	movl saved_context_esi, %esi
+	movl saved_context_edi, %edi
+	call restore_processor_state
+	pushl saved_context_eflags ; popfl
+	ret
+
 ALIGN
 # saved registers
 saved_gdt:	.long	0,0
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	Sun Nov 17 20:30:02 2002
+++ b/arch/i386/kernel/apm.c	Sun Nov 17 20:30:02 2002
@@ -1221,8 +1221,10 @@
 
 static void set_time(void)
 {
-	if (got_clock_diff)	/* Must know time zone in order to set clock */
-		CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
+	if (got_clock_diff) {	/* Must know time zone in order to set clock */
+		xtime.tv_sec = get_cmos_time() + clock_cmos_diff;
+		xtime.tv_nsec = 0; 
+	} 
 }
 
 static void get_time_diff(void)
@@ -1232,7 +1234,7 @@
 	 * Estimate time zone so that set_time can update the clock
 	 */
 	clock_cmos_diff = -get_cmos_time();
-	clock_cmos_diff += CURRENT_TIME;
+	clock_cmos_diff += get_seconds();
 	got_clock_diff = 1;
 #endif
 }
diff -Nru a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
--- a/arch/i386/kernel/cpu/amd.c	Sun Nov 17 20:30:15 2002
+++ b/arch/i386/kernel/cpu/amd.c	Sun Nov 17 20:30:15 2002
@@ -188,15 +188,15 @@
 static struct cpu_dev amd_cpu_dev __initdata = {
 	.c_vendor	= "AMD",
 	.c_ident 	= { "AuthenticAMD" },
-	c_models: {
-		{ X86_VENDOR_AMD,	4,
+	.c_models = {
+		{ .vendor = X86_VENDOR_AMD, .family = 4, .model_names =
 		  {
-			  [3] "486 DX/2",
-			  [7] "486 DX/2-WB",
-			  [8] "486 DX/4", 
-			  [9] "486 DX/4-WB", 
-			  [14] "Am5x86-WT",
-			  [15] "Am5x86-WB" 
+			  [3] = "486 DX/2",
+			  [7] = "486 DX/2-WB",
+			  [8] = "486 DX/4", 
+			  [9] = "486 DX/4-WB", 
+			  [14] = "Am5x86-WT",
+			  [15] = "Am5x86-WB" 
 		  }
 		},
 	},
diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
--- a/arch/i386/kernel/cpu/intel.c	Sun Nov 17 20:30:12 2002
+++ b/arch/i386/kernel/cpu/intel.c	Sun Nov 17 20:30:12 2002
@@ -392,52 +392,52 @@
 static struct cpu_dev intel_cpu_dev __initdata = {
 	.c_vendor	= "Intel",
 	.c_ident 	= { "GenuineIntel" },
-	c_models: {
-		{ X86_VENDOR_INTEL,	4,
+	.c_models = {
+		{ .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = 
 		  { 
-			  [0] "486 DX-25/33", 
-			  [1] "486 DX-50", 
-			  [2] "486 SX", 
-			  [3] "486 DX/2", 
-			  [4] "486 SL", 
-			  [5] "486 SX/2", 
-			  [7] "486 DX/2-WB", 
-			  [8] "486 DX/4", 
-			  [9] "486 DX/4-WB"
+			  [0] = "486 DX-25/33", 
+			  [1] = "486 DX-50", 
+			  [2] = "486 SX", 
+			  [3] = "486 DX/2", 
+			  [4] = "486 SL", 
+			  [5] = "486 SX/2", 
+			  [7] = "486 DX/2-WB", 
+			  [8] = "486 DX/4", 
+			  [9] = "486 DX/4-WB"
 		  }
 		},
-		{ X86_VENDOR_INTEL,	5,
+		{ .vendor = X86_VENDOR_INTEL, .family = 5, .model_names =
 		  { 
-			  [0] "Pentium 60/66 A-step", 
-			  [1] "Pentium 60/66", 
-			  [2] "Pentium 75 - 200",
-			  [3] "OverDrive PODP5V83", 
-			  [4] "Pentium MMX",
-			  [7] "Mobile Pentium 75 - 200", 
-			  [8] "Mobile Pentium MMX"
+			  [0] = "Pentium 60/66 A-step", 
+			  [1] = "Pentium 60/66", 
+			  [2] = "Pentium 75 - 200",
+			  [3] = "OverDrive PODP5V83", 
+			  [4] = "Pentium MMX",
+			  [7] = "Mobile Pentium 75 - 200", 
+			  [8] = "Mobile Pentium MMX"
 		  }
 		},
-		{ X86_VENDOR_INTEL,     6,
+		{ .vendor = X86_VENDOR_INTEL, .family = 6, .model_names =
 		  { 
-			  [0] "Pentium Pro A-step",
-			  [1] "Pentium Pro", 
-			  [3] "Pentium II (Klamath)", 
-			  [4] "Pentium II (Deschutes)", 
-			  [5] "Pentium II (Deschutes)", 
-			  [6] "Mobile Pentium II",
-			  [7] "Pentium III (Katmai)", 
-			  [8] "Pentium III (Coppermine)", 
-			  [10] "Pentium III (Cascades)",
-			  [11] "Pentium III (Tualatin)",
+			  [0] = "Pentium Pro A-step",
+			  [1] = "Pentium Pro", 
+			  [3] = "Pentium II (Klamath)", 
+			  [4] = "Pentium II (Deschutes)", 
+			  [5] = "Pentium II (Deschutes)", 
+			  [6] = "Mobile Pentium II",
+			  [7] = "Pentium III (Katmai)", 
+			  [8] = "Pentium III (Coppermine)", 
+			  [10] = "Pentium III (Cascades)",
+			  [11] = "Pentium III (Tualatin)",
 		  }
 		},
-		{ X86_VENDOR_INTEL,     15,
+		{ .vendor = X86_VENDOR_INTEL, .family = 15, .model_names =
 		  {
-			  [0] "Pentium 4 (Unknown)",
-			  [1] "Pentium 4 (Willamette)",
-			  [2] "Pentium 4 (Northwood)",
-			  [4] "Pentium 4 (Foster)",
-			  [5] "Pentium 4 (Foster)",
+			  [0] = "Pentium 4 (Unknown)",
+			  [1] = "Pentium 4 (Willamette)",
+			  [2] = "Pentium 4 (Northwood)",
+			  [4] = "Pentium 4 (Foster)",
+			  [5] = "Pentium 4 (Foster)",
 		  }
 		},
 	},
diff -Nru a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
--- a/arch/i386/kernel/cpu/nexgen.c	Sun Nov 17 20:30:02 2002
+++ b/arch/i386/kernel/cpu/nexgen.c	Sun Nov 17 20:30:02 2002
@@ -44,8 +44,11 @@
 static struct cpu_dev nexgen_cpu_dev __initdata = {
 	.c_vendor	= "Nexgen",
 	.c_ident	= { "NexGenDriven" },
-	c_models: {
-		{ X86_VENDOR_NEXGEN,5, { [1] "Nx586" } },
+	.c_models = {
+			{ .vendor = X86_VENDOR_NEXGEN,
+			  .family = 5,
+			  .model_names = { [1] = "Nx586" }
+			},
 	},
 	.c_init		= init_nexgen,
 	.c_identify	= nexgen_identify,
diff -Nru a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c
--- a/arch/i386/kernel/cpu/rise.c	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/kernel/cpu/rise.c	Sun Nov 17 20:30:04 2002
@@ -31,13 +31,13 @@
 static struct cpu_dev rise_cpu_dev __initdata = {
 	.c_vendor	= "Rise",
 	.c_ident	= { "RiseRiseRise" },
-	c_models: {
-		{ X86_VENDOR_RISE,	5,
+	.c_models = {
+		{ .vendor = X86_VENDOR_RISE, .family = 5, .model_names = 
 		  { 
-			  [0] "iDragon", 
-			  [2] "iDragon", 
-			  [8] "iDragon II", 
-			  [9] "iDragon II"
+			  [0] = "iDragon", 
+			  [2] = "iDragon", 
+			  [8] = "iDragon II", 
+			  [9] = "iDragon II"
 		  }
 		},
 	},
diff -Nru a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c
--- a/arch/i386/kernel/cpu/umc.c	Sun Nov 17 20:30:03 2002
+++ b/arch/i386/kernel/cpu/umc.c	Sun Nov 17 20:30:03 2002
@@ -13,11 +13,11 @@
 static struct cpu_dev umc_cpu_dev __initdata = {
 	.c_vendor	= "UMC",
 	.c_ident 	= { "UMC UMC UMC" },
-	c_models: {
-		{ X86_VENDOR_UMC,	4,
+	.c_models = {
+		{ .vendor = X86_VENDOR_UMC, .family = 4, .model_names =
 		  { 
-			  [1] "U5D", 
-			  [2] "U5S", 
+			  [1] = "U5D", 
+			  [2] = "U5S", 
 		  }
 		},
 	},
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Sun Nov 17 20:30:12 2002
+++ b/arch/i386/kernel/entry.S	Sun Nov 17 20:30:12 2002
@@ -66,7 +66,9 @@
 OLDSS		= 0x38
 
 CF_MASK		= 0x00000001
+TF_MASK		= 0x00000100
 IF_MASK		= 0x00000200
+DF_MASK		= 0x00000400 
 NT_MASK		= 0x00004000
 VM_MASK		= 0x00020000
 
@@ -134,6 +136,17 @@
 	movl %eax,EFLAGS(%esp)	#
 	movl %edx,EIP(%esp)	# Now we move them to their "normal" places
 	movl %ecx,CS(%esp)	#
+
+	#
+	# Call gates don't clear TF and NT in eflags like
+	# traps do, so we need to do it ourselves.
+	# %eax already contains eflags (but it may have
+	# DF set, clear that also)
+	#
+	andl $~(DF_MASK | TF_MASK | NT_MASK),%eax
+	pushl %eax
+	popfl
+
 	movl %esp, %ebx
 	pushl %ebx
 	andl $-8192, %ebx	# GET_THREAD_INFO
@@ -156,6 +169,17 @@
 	movl %eax,EFLAGS(%esp)	#
 	movl %edx,EIP(%esp)	# Now we move them to their "normal" places
 	movl %ecx,CS(%esp)	#
+
+	#
+	# Call gates don't clear TF and NT in eflags like
+	# traps do, so we need to do it ourselves.
+	# %eax already contains eflags (but it may have
+	# DF set, clear that also)
+	#
+	andl $~(DF_MASK | TF_MASK | NT_MASK),%eax
+	pushl %eax
+	popfl
+
 	movl %esp, %ebx
 	pushl %ebx
 	andl $-8192, %ebx	# GET_THREAD_INFO
@@ -612,10 +636,10 @@
 	.long sys_adjtimex
 	.long sys_mprotect	/* 125 */
 	.long sys_sigprocmask
-	.long sys_create_module
+	.long sys_ni_syscall	/* old "create_module" */ 
 	.long sys_init_module
 	.long sys_delete_module
-	.long sys_get_kernel_syms	/* 130 */
+	.long sys_ni_syscall	/* 130:	old "get_kernel_syms" */
 	.long sys_quotactl
 	.long sys_getpgid
 	.long sys_fchdir
@@ -652,7 +676,7 @@
 	.long sys_setresuid16
 	.long sys_getresuid16	/* 165 */
 	.long sys_vm86
-	.long sys_query_module
+	.long sys_ni_syscall	/* Old sys_query_module */
 	.long sys_poll
 	.long sys_nfsservctl
 	.long sys_setresgid16	/* 170 */
@@ -743,6 +767,7 @@
 	.long sys_epoll_ctl	/* 255 */
 	.long sys_epoll_wait
  	.long sys_remap_file_pages
+ 	.long sys_set_tid_address
 
 
 	.rept NR_syscalls-(.-sys_call_table)/4
diff -Nru a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/module.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,124 @@
+/*  Kernel module help for i386.
+    Copyright (C) 2001 Rusty Russell.
+
+    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
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+long module_core_size(const Elf32_Ehdr *hdr,
+		      const Elf32_Shdr *sechdrs,
+		      const char *secstrings,
+		      struct module *module)
+{
+	return module->core_size;
+}
+
+long module_init_size(const Elf32_Ehdr *hdr,
+		      const Elf32_Shdr *sechdrs,
+		      const char *secstrings,
+		      struct module *module)
+{
+	return module->init_size;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_offset
+			+ ELF32_R_SYM(rel[i].r_info);
+		if (!sym->st_value) {
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_386_32:
+			/* We add the value into the location given */
+			*location += sym->st_value;
+			break;
+		case R_386_PC32:
+			/* Add the value, subtract its postition */
+			*location += sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
diff -Nru a/arch/i386/kernel/suspend.c b/arch/i386/kernel/suspend.c
--- a/arch/i386/kernel/suspend.c	Sun Nov 17 20:30:15 2002
+++ b/arch/i386/kernel/suspend.c	Sun Nov 17 20:30:15 2002
@@ -28,26 +28,11 @@
 #include <asm/tlbflush.h>
 
 static struct saved_context saved_context;
+unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
+unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
+unsigned long saved_context_eflags;
 
-/*
- * save_processor_context
- * 
- * Save the state of the processor before we go to sleep.
- *
- * return_stack is the value of the stack pointer (%esp) as the caller sees it.
- * A good way could not be found to obtain it from here (don't want to make _too_
- * many assumptions about the layout of the stack this far down.) Also, the 
- * handy little __builtin_frame_pointer(level) where level > 0, is blatantly 
- * buggy - it returns the value of the stack at the proper location, not the 
- * location, like it should (as of gcc 2.91.66)
- * 
- * Note that the context and timing of this function is pretty critical.
- * With a minimal amount of things going on in the caller and in here, gcc
- * does a good job of being just a dumb compiler.  Watch the assembly output
- * if anything changes, though, and make sure everything is going in the right
- * place. 
- */
-static inline void save_processor_context (void)
+void save_processor_state(void)
 {
 	kernel_fpu_begin();
 
@@ -60,23 +45,6 @@
 	asm volatile ("str %0"  : "=m" (saved_context.tr));
 
 	/*
-	 * save the general registers.
-	 * note that gcc has constructs to specify output of certain registers,
-	 * but they're not used here, because it assumes that you want to modify
-	 * those registers, so it tries to be smart and save them beforehand.
-	 * It's really not necessary, and kinda fishy (check the assembly output),
-	 * so it's avoided. 
-	 */
-	asm volatile ("movl %%esp, %0" : "=m" (saved_context.esp));
-	asm volatile ("movl %%eax, %0" : "=m" (saved_context.eax));
-	asm volatile ("movl %%ebx, %0" : "=m" (saved_context.ebx));
-	asm volatile ("movl %%ecx, %0" : "=m" (saved_context.ecx));
-	asm volatile ("movl %%edx, %0" : "=m" (saved_context.edx));
-	asm volatile ("movl %%ebp, %0" : "=m" (saved_context.ebp));
-	asm volatile ("movl %%esi, %0" : "=m" (saved_context.esi));
-	asm volatile ("movl %%edi, %0" : "=m" (saved_context.edi));
-	/* FIXME: Need to save XMM0..XMM15? */
-	/*
 	 * segment registers
 	 */
 	asm volatile ("movw %%es, %0" : "=m" (saved_context.es));
@@ -91,11 +59,6 @@
 	asm volatile ("movl %%cr2, %0" : "=r" (saved_context.cr2));
 	asm volatile ("movl %%cr3, %0" : "=r" (saved_context.cr3));
 	asm volatile ("movl %%cr4, %0" : "=r" (saved_context.cr4));
-
-	/*
-	 * eflags
-	 */
-	asm volatile ("pushfl ; popl %0" : "=m" (saved_context.eflags));
 }
 
 static void
@@ -106,26 +69,8 @@
         kernel_fpu_end();
 }
 
-/*
- * restore_processor_context
- * 
- * Restore the processor context as it was before we went to sleep
- * - descriptor tables
- * - control registers
- * - segment registers
- * - flags
- * 
- * Note that it is critical that this function is declared inline.  
- * It was separated out from restore_state to make that function
- * a little clearer, but it needs to be inlined because we won't have a
- * stack when we get here (so we can't push a return address).
- */
-static inline void restore_processor_context (void)
+void restore_processor_state(void)
 {
-	/*
-	 * first restore %ds, so we can access our data properly
-	 */
-	asm volatile ("movw %0, %%ds" :: "r" (__KERNEL_DS));
 
 	/*
 	 * control registers
@@ -144,24 +89,6 @@
 	asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss));
 
 	/*
-	 * the other general registers
-	 *
-	 * note that even though gcc has constructs to specify memory 
-	 * input into certain registers, it will try to be too smart
-	 * and save them at the beginning of the function.  This is esp.
-	 * bad since we don't have a stack set up when we enter, and we 
-	 * want to preserve the values on exit. So, we set them manually.
-	 */
-	asm volatile ("movl %0, %%esp" :: "m" (saved_context.esp));
-	asm volatile ("movl %0, %%ebp" :: "m" (saved_context.ebp));
-	asm volatile ("movl %0, %%eax" :: "m" (saved_context.eax));
-	asm volatile ("movl %0, %%ebx" :: "m" (saved_context.ebx));
-	asm volatile ("movl %0, %%ecx" :: "m" (saved_context.ecx));
-	asm volatile ("movl %0, %%edx" :: "m" (saved_context.edx));
-	asm volatile ("movl %0, %%esi" :: "m" (saved_context.esi));
-	asm volatile ("movl %0, %%edi" :: "m" (saved_context.edi));
-
-	/*
 	 * now restore the descriptor tables to their proper values
 	 * ltr is done i fix_processor_context().
 	 */
@@ -170,42 +97,15 @@
 	asm volatile ("lldt %0" :: "m" (saved_context.ldt));
 
 	fix_processor_context();
-
-	/*
-	 * the flags
-	 */
-	asm volatile ("pushl %0 ; popfl" :: "m" (saved_context.eflags));
-
 	do_fpu_end();
 }
 
-#ifdef CONFIG_ACPI_SLEEP
-void do_suspend_lowlevel(int resume)
-{
-/*
- * FIXME: This function should really be written in assembly. Actually
- * requirement is that it does not touch stack, because %esp will be
- * wrong during resume before restore_processor_context(). Check
- * assembly if you modify this.
- */
-	if (!resume) {
-		save_processor_context();
-		acpi_save_register_state((unsigned long)&&acpi_sleep_done);
-		acpi_enter_sleep_state(3);
-		return;
-	}
-acpi_sleep_done:
-	acpi_restore_register_state();
-	restore_processor_context();
-}
-#endif
-
 void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
 	struct tss_struct * t = init_tss + cpu;
 
-	set_tss_desc(cpu,t);	/* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy tsc or some similar stupidity. */
+	set_tss_desc(cpu,t);	/* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
         cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
 
 	load_TR_desc();				/* This does ltr */
@@ -226,77 +126,9 @@
 
 }
 
-
 #ifdef CONFIG_SOFTWARE_SUSPEND
 /* Local variables for do_magic */
-static int loop __nosavedata = 0;
-static int loop2 __nosavedata = 0;
-
-/*
- * (KG): Since we affect stack here, we make this function as flat and easy
- * as possible in order to not provoke gcc to use local variables on the stack.
- * Note that on resume, all (expect nosave) variables will have the state from
- * the time of writing (suspend_save_image) and the registers (including the
- * stack pointer, but excluding the instruction pointer) will be loaded with 
- * the values saved at save_processor_context() time.
- */
-void do_magic(int resume)
-{
-	/* DANGER WILL ROBINSON!
-	 *
-	 * If this function is too difficult for gcc to optimize, it will crash and burn!
-	 * see above.
-	 *
-	 * DO NOT TOUCH.
-	 */
-
-	if (!resume) {
-		do_magic_suspend_1();
-		save_processor_context();	/* We need to capture registers and memory at "same time" */
-		do_magic_suspend_2();		/* If everything goes okay, this function does not return */
-		return;
-	}
+int loop __nosavedata = 0;
+int loop2 __nosavedata = 0;
 
-	/* We want to run from swapper_pg_dir, since swapper_pg_dir is stored in constant
-	 * place in memory 
-	 */
-
-        __asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir)));
-
-/*
- * Final function for resuming: after copying the pages to their original
- * position, it restores the register state.
- *
- * What about page tables? Writing data pages may toggle
- * accessed/dirty bits in our page tables. That should be no problems
- * with 4MB page tables. That's why we require have_pse.  
- *
- * This loops destroys stack from under itself, so it better should
- * not use any stack space, itself. When this function is entered at
- * resume time, we move stack to _old_ place.  This is means that this
- * function must use no stack and no local variables in registers,
- * until calling restore_processor_context();
- *
- * Critical section here: noone should touch saved memory after
- * do_magic_resume_1; copying works, because nr_copy_pages,
- * pagedir_nosave, loop and loop2 are nosavedata.
- */
-	do_magic_resume_1();
-
-	for (loop=0; loop < nr_copy_pages; loop++) {
-		/* You may not call something (like copy_page) here: see above */
-		for (loop2=0; loop2 < PAGE_SIZE; loop2++) {
-			*(((char *)((pagedir_nosave+loop)->orig_address))+loop2) =
-				*(((char *)((pagedir_nosave+loop)->address))+loop2);
-			__flush_tlb();
-		}
-	}
-
-	restore_processor_context();
-
-/* Ahah, we now run with our old stack, and with registers copied from
-   suspend time */
-
-	do_magic_resume_2();
-}
 #endif
diff -Nru a/arch/i386/kernel/suspend_asm.S b/arch/i386/kernel/suspend_asm.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/suspend_asm.S	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,80 @@
+.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+
+ENTRY(do_magic):
+	pushl %ebx
+	cmpl $0,8(%esp)
+	jne .L1450
+	call do_magic_suspend_1
+	call save_processor_state
+
+	movl %esp, saved_context_esp
+	movl %eax, saved_context_eax
+	movl %ebx, saved_context_ebx
+	movl %ecx, saved_context_ecx
+	movl %edx, saved_context_edx
+	movl %ebp, saved_context_ebp
+	movl %esi, saved_context_esi
+	movl %edi, saved_context_edi
+	pushfl ; popl saved_context_eflags
+
+	call do_magic_suspend_2
+	jmp .L1449
+	.p2align 4,,7
+.L1450:
+	movl $swapper_pg_dir-__PAGE_OFFSET,%ecx
+	movl %ecx,%cr3
+
+	call do_magic_resume_1
+	movl $0,loop
+	cmpl $0,nr_copy_pages
+	je .L1453
+	.p2align 4,,7
+.L1455:
+	movl $0,loop2
+	.p2align 4,,7
+.L1459:
+	movl pagedir_nosave,%ecx
+	movl loop,%eax
+	movl loop2,%edx
+	sall $4,%eax
+	movl 4(%ecx,%eax),%ebx
+	movl (%ecx,%eax),%eax
+	movb (%edx,%eax),%al
+	movb %al,(%edx,%ebx)
+	movl %cr3, %eax;              
+	movl %eax, %cr3;  # flush TLB 
+
+	movl loop2,%eax
+	leal 1(%eax),%edx
+	movl %edx,loop2
+	movl %edx,%eax
+	cmpl $4095,%eax
+	jbe .L1459
+	movl loop,%eax
+	leal 1(%eax),%edx
+	movl %edx,loop
+	movl %edx,%eax
+	cmpl nr_copy_pages,%eax
+	jb .L1455
+	.p2align 4,,7
+.L1453:
+	movl $104,%eax
+
+	movw %eax, %ds
+	movl saved_context_esp, %esp
+	movl saved_context_ebp, %ebp
+	movl saved_context_eax, %eax
+	movl saved_context_ebx, %ebx
+	movl saved_context_ecx, %ecx
+	movl saved_context_edx, %edx
+	movl saved_context_esi, %esi
+	movl saved_context_edi, %edi
+	call restore_processor_state
+	pushl saved_context_eflags ; popfl
+	call do_magic_resume_2
+.L1449:
+	popl %ebx
+	ret
diff -Nru a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c
--- a/arch/i386/kernel/sys_i386.c	Sun Nov 17 20:30:15 2002
+++ b/arch/i386/kernel/sys_i386.c	Sun Nov 17 20:30:15 2002
@@ -294,14 +294,17 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+	struct hugetlb_key *key;
 	int retval;
 
 	vma = find_vma(current->mm, addr);
 	if (!vma || !(vma->vm_flags & VM_HUGETLB) || vma->vm_start != addr)
 		return -EINVAL;
 	down_write(&mm->mmap_sem);
+	key = (struct hugetlb_key *)vma->vm_private_data;
 	retval = do_munmap(vma->vm_mm, addr, vma->vm_end - addr);
 	up_write(&mm->mmap_sem);
+	hugetlb_release_key(key);
 	return retval;
 }
 #else
diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
--- a/arch/i386/kernel/timers/timer_tsc.c	Sun Nov 17 20:30:14 2002
+++ b/arch/i386/kernel/timers/timer_tsc.c	Sun Nov 17 20:30:14 2002
@@ -224,7 +224,7 @@
 }
 
 static struct notifier_block time_cpufreq_notifier_block = {
-	notifier_call:	time_cpufreq_notifier
+	.notifier_call	= time_cpufreq_notifier
 };
 #endif
 
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/kernel/traps.c	Sun Nov 17 20:30:04 2002
@@ -95,7 +95,8 @@
 
 #ifdef CONFIG_MODULES
 
-extern struct module kernel_module;
+/* FIXME: Accessed without a lock --RR */
+extern struct list_head modules;
 
 static inline int kernel_text_address(unsigned long addr)
 {
@@ -106,11 +107,11 @@
 	    addr <= (unsigned long) &_etext)
 		return 1;
 
-	for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+	list_for_each_entry(mod, &modules, list) {
 		/* mod_bound tests for addr being inside the vmalloc'ed
 		 * module area. Of course it'd be better to test only
 		 * for the .text subset... */
-		if (mod_bound(addr, 0, mod)) {
+		if (mod_bound((void *)addr, 0, mod)) {
 			retval = 1;
 			break;
 		}
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Sun Nov 17 20:30:03 2002
+++ b/arch/i386/kernel/vm86.c	Sun Nov 17 20:30:03 2002
@@ -31,6 +31,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
diff -Nru a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c
--- a/arch/i386/mm/extable.c	Sun Nov 17 20:30:16 2002
+++ b/arch/i386/mm/extable.c	Sun Nov 17 20:30:16 2002
@@ -44,15 +44,17 @@
 	return ret;
 #else
 	unsigned long flags;
-	/* The kernel is the last "module" -- no need to treat it special.  */
-	struct module *mp;
+	struct list_head *i;
 
+	/* The kernel is the last "module" -- no need to treat it special.  */
 	spin_lock_irqsave(&modlist_lock, flags);
-	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
+	list_for_each(i, &extables) {
+		struct exception_table *ex
+			= list_entry(i, struct exception_table, list);
+		if (ex->num_entries == 0)
 			continue;
-		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_end - 1, addr);
+		ret = search_one_table(ex->entry,
+				       ex->entry + ex->num_entries - 1, addr);
 		if (ret)
 			break;
 	}
diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
--- a/arch/i386/mm/hugetlbpage.c	Sun Nov 17 20:30:15 2002
+++ b/arch/i386/mm/hugetlbpage.c	Sun Nov 17 20:30:15 2002
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/err.h>
 #include <asm/mman.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
@@ -27,22 +28,120 @@
 static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
 
 #define MAX_ID 	32
-static struct htlbpagekey {
-	struct inode *in;
+
+struct hugetlb_key {
+	struct radix_tree_root tree;
+	atomic_t count;
+	spinlock_t lock;
 	int key;
-} htlbpagek[MAX_ID];
+	int busy;
+	uid_t uid;
+	gid_t gid;
+	umode_t mode;
+	loff_t size;
+};
+
+static struct hugetlb_key htlbpagek[MAX_ID];
+
+static void mark_key_busy(struct hugetlb_key *hugetlb_key)
+{
+	hugetlb_key->busy = 1;
+}
+
+static void clear_key_busy(struct hugetlb_key *hugetlb_key)
+{
+	hugetlb_key->busy = 0;
+}
 
-static struct inode *find_key_inode(int key)
+static int key_busy(struct hugetlb_key *hugetlb_key)
+{
+	return hugetlb_key->busy;
+}
+
+static struct hugetlb_key *find_key(int key)
 {
 	int i;
 
 	for (i = 0; i < MAX_ID; i++) {
 		if (htlbpagek[i].key == key)
-			return (htlbpagek[i].in);
+			return &htlbpagek[i];
 	}
 	return NULL;
 }
 
+static int check_size_prot(struct hugetlb_key *key, unsigned long len, int prot, int flag);
+/*
+ * Call without htlbpage_lock, returns with htlbpage_lock held.
+ */
+struct hugetlb_key *alloc_key(int key, unsigned long len, int prot, int flag)
+{
+	struct hugetlb_key *hugetlb_key;
+
+	do {
+		spin_lock(&htlbpage_lock);
+		hugetlb_key = find_key(key);
+		if (!hugetlb_key) {
+			if (!capable(CAP_SYS_ADMIN) || !in_group_p(0))
+				hugetlb_key = ERR_PTR(-EPERM);
+			else if (!(flag & IPC_CREAT))
+				hugetlb_key = ERR_PTR(-ENOENT);
+			else {
+				int i;
+				for (i = 0; i < MAX_ID; ++i)
+					if (!htlbpagek[i].key)
+						break;
+				if (i == MAX_ID) {
+					hugetlb_key = ERR_PTR(-ENOMEM);
+				} else {
+					hugetlb_key = &htlbpagek[i];
+					mark_key_busy(hugetlb_key);
+					hugetlb_key->key = key;
+					INIT_RADIX_TREE(&hugetlb_key->tree, GFP_ATOMIC);
+					hugetlb_key->uid = current->fsuid;
+					hugetlb_key->gid = current->fsgid;
+					hugetlb_key->mode = prot;
+					hugetlb_key->size = len;
+				}
+			}
+		} else if (key_busy(hugetlb_key)) {
+			hugetlb_key = ERR_PTR(-EAGAIN);
+			spin_unlock(&htlbpage_lock);
+		} else if (check_size_prot(hugetlb_key, len, prot, flag) < 0) {
+			hugetlb_key->key = 0;
+			hugetlb_key = ERR_PTR(-EINVAL);
+		} 
+	} while (hugetlb_key == ERR_PTR(-EAGAIN));
+	if (!IS_ERR(hugetlb_key))
+		atomic_inc(&hugetlb_key->count);
+	return hugetlb_key;
+}
+
+void hugetlb_release_key(struct hugetlb_key *key)
+{
+	unsigned long index;
+	unsigned long max_idx;
+
+	if (!atomic_dec_and_test(&key->count)) {
+		spin_lock(&htlbpage_lock);
+		clear_key_busy(key);
+		spin_unlock(&htlbpage_lock);
+		return;	
+	}
+
+	max_idx = (key->size >> HPAGE_SHIFT);
+	for (index = 0; index < max_idx; ++index) {
+		struct page *page = radix_tree_lookup(&key->tree, index);
+		if (!page)
+			continue;
+		huge_page_release(page);
+	}
+	spin_lock(&htlbpage_lock);
+	key->key = 0;
+	clear_key_busy(key);
+	INIT_RADIX_TREE(&key->tree, GFP_ATOMIC);
+	spin_unlock(&htlbpage_lock);
+}
+
 static struct page *alloc_hugetlb_page(void)
 {
 	int i;
@@ -236,55 +335,29 @@
 	free_huge_page(page);
 }
 
-static void
-free_rsrc(struct inode * inode)
-{
-	int i;
-	spin_lock(&htlbpage_lock);
-	for (i=0;i<MAX_ID;i++) 
-		if (htlbpagek[i].key == inode->i_ino) {
-			htlbpagek[i].key = 0;
-			htlbpagek[i].in = NULL;
-			break;
-		}
-	spin_unlock(&htlbpage_lock);
-	kfree(inode);
-}
-
 void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
 	pte_t *pte;
 	struct page *page;
-	int free_more = 0;
-	struct inode *inode = NULL;
+	struct hugetlb_key *key = vma->vm_private_data;
 
 	BUG_ON(start & (HPAGE_SIZE - 1));
 	BUG_ON(end & (HPAGE_SIZE - 1));
 
-	if (start < end) {
-		pte = huge_pte_offset(mm, start);
-		page = pte_page(*pte);
-		if ((page->mapping != NULL) && (page_count(page) == 2) &&
-			((inode=page->mapping->host)->i_mapping->a_ops == NULL)) 
-			free_more = 1;
-	}
+	spin_lock(&htlbpage_lock);
+	if (key ) 
+		mark_key_busy(key);
+	spin_unlock(&htlbpage_lock);
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		pte = huge_pte_offset(mm, address);
 		page = pte_page(*pte);
-		if (free_more) {
-			ClearPageDirty(page);
-			SetPageLocked(page);
-			remove_from_page_cache(page);
-			ClearPageLocked(page);
-			set_page_count(page, 1);
-		}
 		huge_page_release(page);
 		pte_clear(pte);
 	}
-	if (free_more)
-		free_rsrc(inode);
+	if (key)
+		hugetlb_release_key(key);
 	mm->rss -= (end - start) >> PAGE_SHIFT;
 	flush_tlb_range(vma, start, end);
 }
@@ -297,109 +370,108 @@
 	spin_unlock(&mm->page_table_lock);
 }
 
-static struct inode *set_new_inode(unsigned long len, int prot, int flag, int key)
-{
-	struct inode *inode;
-	int i;
-
-	for (i = 0; i < MAX_ID; i++) {
-		if (htlbpagek[i].key == 0)
-			break;
-	}
-	if (i == MAX_ID)
-		return NULL;
-	inode = kmalloc(sizeof (struct inode), GFP_ATOMIC);
-	if (inode == NULL)
-		return NULL;
-
-	inode_init_once(inode);
-	atomic_inc(&inode->i_writecount);
-	inode->i_mapping = &inode->i_data;
-	inode->i_mapping->host = inode;
-	inode->i_ino = (unsigned long)key;
-
-	htlbpagek[i].key = key;
-	htlbpagek[i].in = inode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_mode = prot;
-	inode->i_size = len;
-	return inode;
-}
-
-static int check_size_prot(struct inode *inode, unsigned long len, int prot, int flag)
+static int check_size_prot(struct hugetlb_key *key, unsigned long len, int prot, int flag)
 {
-	if (inode->i_uid != current->fsuid)
+	if (key->uid != current->fsuid)
 		return -1;
-	if (inode->i_gid != current->fsgid)
+	if (key->gid != current->fsgid)
 		return -1;
-	if (inode->i_size != len)
+	if (key->size != len)
 		return -1;
 	return 0;
 }
 
-static int alloc_shared_hugetlb_pages(int key, unsigned long addr, unsigned long len, int prot, int flag)
+struct page *key_find_page(struct hugetlb_key *key, unsigned long index)
+{
+	struct page *page = radix_tree_lookup(&key->tree, index);
+	if (page)
+		get_page(page);
+	return page;
+}
+
+int key_add_page(struct page *page, struct hugetlb_key *key, unsigned long index)
+{
+	int error = radix_tree_insert(&key->tree, index, page);
+	if (!error)
+		get_page(page);
+	return error;
+}
+
+static int prefault_key(struct hugetlb_key *key, struct vm_area_struct *vma)
 {
 	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	struct inode *inode;
-	struct address_space *mapping;
-	int idx;
-	int retval = -ENOMEM;
-	int newalloc = 0;
+	unsigned long addr;
+	int ret = 0;
 
-try_again:
-	spin_lock(&htlbpage_lock);
+	BUG_ON(vma->vm_start & ~HPAGE_MASK);
+	BUG_ON(vma->vm_end & ~HPAGE_MASK);
 
-	inode = find_key_inode(key);
-	if (inode == NULL) {
-		if (!capable(CAP_SYS_ADMIN)) {
-			if (!in_group_p(0)) {
-				retval = -EPERM;
-				goto out_err;
-			}
-		}
-		if (!(flag & IPC_CREAT)) {
-			retval = -ENOENT;
-			goto out_err;
-		}
-		inode = set_new_inode(len, prot, flag, key);
-		if (inode == NULL)
-			goto out_err;
-		newalloc = 1;
-	} else {
-		if (check_size_prot(inode, len, prot, flag) < 0) {
-			retval = -EINVAL;
-			goto out_err;
+	spin_lock(&mm->page_table_lock);
+	spin_lock(&key->lock);
+	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+		unsigned long idx;
+		pte_t *pte = huge_pte_alloc(mm, addr);
+		struct page *page;
+
+		if (!pte) {
+			ret = -ENOMEM;
+			goto out;
 		}
-		else if (atomic_read(&inode->i_writecount)) {
-			spin_unlock(&htlbpage_lock);
-			goto try_again;
+		if (!pte_none(*pte))
+			continue;
+
+		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+		page = key_find_page(key, idx);
+		if (!page) {
+			page = alloc_hugetlb_page();
+			if (!page) {
+				spin_unlock(&key->lock);
+				ret = -ENOMEM;
+				goto out;
+			}
+			key_add_page(page, key, idx);
 		}
+		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
 	}
+	spin_unlock(&key->lock);
+out:
+	spin_unlock(&mm->page_table_lock);
+	return ret;
+}
+
+static int alloc_shared_hugetlb_pages(int key, unsigned long addr, unsigned long len, int prot, int flag)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	struct hugetlb_key *hugetlb_key;
+	int retval = -ENOMEM;
+
+	hugetlb_key = alloc_key(key, len, prot, flag );
 	spin_unlock(&htlbpage_lock);
-	mapping = inode->i_mapping;
+	if (IS_ERR(hugetlb_key)) 
+		return PTR_ERR(hugetlb_key);
 
 	addr = do_mmap_pgoff(NULL, addr, len, (unsigned long) prot,
 			MAP_NORESERVE|MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0);
 	if (IS_ERR((void *) addr))
-		goto freeinode;
+		goto out_release;
 
 	vma = find_vma(mm, addr);
 	if (!vma) {
 		retval = -EINVAL;
-		goto freeinode;
+		goto out_release;
 	}
 
-	retval = hugetlb_prefault(mapping, vma);
+	retval = prefault_key(hugetlb_key, vma);
 	if (retval)
 		goto out;
 
 	vma->vm_flags |= (VM_HUGETLB | VM_RESERVED);
 	vma->vm_ops = &hugetlb_vm_ops;
-	spin_unlock(&mm->page_table_lock);
+	vma->vm_private_data = hugetlb_key;
 	spin_lock(&htlbpage_lock);
-	atomic_set(&inode->i_writecount, 0);
+	clear_key_busy(hugetlb_key);
 	spin_unlock(&htlbpage_lock);
 	return retval;
 out:
@@ -410,23 +482,12 @@
 		zap_hugepage_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
 		vma->vm_end = raddr;
 	}
-	spin_unlock(&mm->page_table_lock);
+	spin_lock(&mm->page_table_lock);
 	do_munmap(mm, vma->vm_start, len);
-	if (newalloc)
-		goto freeinode;
+	spin_unlock(&mm->page_table_lock);
+out_release:
+	hugetlb_release_key(hugetlb_key);
 	return retval;
-out_err: spin_unlock(&htlbpage_lock);
-freeinode:
-	 if (newalloc) {
-		 for(idx=0;idx<MAX_ID;idx++)
-			 if (htlbpagek[idx].key == inode->i_ino) {
-				 htlbpagek[idx].key = 0;
-				 htlbpagek[idx].in = NULL;
-				 break;
-			 }
-		 kfree(inode);
-	 }
-	 return retval;
 }
 
 int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
@@ -578,6 +639,10 @@
 	}
 	htlbpage_max = htlbpagemem = htlbzone_pages = i;
 	printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem);
+	for (i = 0; i < MAX_ID; ++i) {
+		atomic_set(&htlbpagek[i].count, 0);
+		spin_lock_init(&htlbpagek[i].lock);
+	}
 	return 0;
 }
 module_init(hugetlb_init);
diff -Nru a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
--- a/arch/i386/pci/numa.c	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/pci/numa.c	Sun Nov 17 20:30:04 2002
@@ -84,8 +84,8 @@
 }
 
 static struct pci_ops pci_direct_conf1_mq = {
-	read:	pci_conf1_mq_read,
-	write:	pci_conf1_mq_write
+	.read	= pci_conf1_mq_read,
+	.write	= pci_conf1_mq_write
 };
 
 
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S	Sun Nov 17 20:30:04 2002
+++ b/arch/i386/vmlinux.lds.S	Sun Nov 17 20:30:04 2002
@@ -26,6 +26,7 @@
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
+  . = ALIGN(64);
   __start___ksymtab = .;	/* Kernel symbol table */
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/ia64/Kconfig	Sun Nov 17 20:30:15 2002
@@ -601,7 +601,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -813,13 +813,13 @@
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
+#  config KALLSYMS
+#  	bool "Load all symbols for debugging/kksymoops"
+#  	depends on DEBUG_KERNEL
+#  	help
+#  	  Say Y here to let the kernel print out symbolic crash information and
+#  	  symbolic stack backtraces. This increases the size of the kernel
+#  	  somewhat, as all symbols have to be loaded into the kernel image.
 
 config IA64_PRINT_HAZARDS
 	bool "Print possible IA-64 dependency violations to console"
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Sun Nov 17 20:30:13 2002
+++ b/arch/ia64/hp/sim/simscsi.c	Sun Nov 17 20:30:13 2002
@@ -115,6 +115,9 @@
 {
 	templ->proc_name = "simscsi";
 	host = scsi_register(templ, 0);
+	if(host == NULL)
+		return 0;
+
 	return 1;	/* fake one SCSI host adapter */
 }
 
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Sun Nov 17 20:30:14 2002
+++ b/arch/ia64/ia32/sys_ia32.c	Sun Nov 17 20:30:14 2002
@@ -2605,7 +2605,7 @@
 
 	/* SMP: This is fairly trivial. We grab CURRENT_TIME and
 	   stuff it to user space. No side effects */
-	i = CURRENT_TIME;
+	i = get_seconds();
 	if (tloc) {
 		if (put_user(i, tloc))
 			i = -EFAULT;
diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig
--- a/arch/m68k/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/m68k/Kconfig	Sun Nov 17 20:30:14 2002
@@ -731,7 +731,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -752,7 +752,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sd_mod.o.  If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  Do not compile this driver as a
+	  <file:Documentation/scsi/scsi.txt>.  Do not compile this driver as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI disk. In this case, do not compile the driver
 	  for your SCSI host adapter (below) as a module either.
@@ -781,14 +781,14 @@
 	  If you want to use a SCSI tape drive under Linux, say Y and read the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and
-	  <file:drivers/scsi/README.st> in the kernel source.  This is NOT for
+	  <file:Documentation/scsi/st.txt> in the kernel source.  This is NOT for
 	  SCSI CD-ROMs.
 
 	  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 st.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config ST_EXTRA_DEVS
 	int "Maximum number of SCSI tapes that can be loaded as modules"
@@ -820,7 +820,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sr_mod.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR_VENDOR
 	bool "Enable vendor-specific extensions (for SCSI CDROM)"
@@ -866,13 +866,13 @@
 	  quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
 	  For other devices, it's possible that you'll have to write the
 	  driver software yourself. Please read the file
-	  <file:Documentation/scsi-generic.txt> for more information.
+	  <file:Documentation/scsi/scsi-generic.txt> for more information.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
-	  say N.
+	  <file:Documentation/scsi/scsi.txt>. The module will be called sg.o.
+	  If unsure, say N.
 
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/mips/Kconfig	Sun Nov 17 20:30:14 2002
@@ -904,7 +904,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c
--- a/arch/mips/au1000/common/serial.c	Sun Nov 17 20:30:12 2002
+++ b/arch/mips/au1000/common/serial.c	Sun Nov 17 20:30:12 2002
@@ -3043,12 +3043,12 @@
 }
 
 static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name		= "ttyS",
+	.write		= serial_console_write,
+	.device		= serial_console_device,
+	.setup		= serial_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
 };
 
 /*
diff -Nru a/arch/mips/baget/vacserial.c b/arch/mips/baget/vacserial.c
--- a/arch/mips/baget/vacserial.c	Sun Nov 17 20:30:14 2002
+++ b/arch/mips/baget/vacserial.c	Sun Nov 17 20:30:14 2002
@@ -2772,12 +2772,12 @@
 }
 
 static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name		= "ttyS",
+	.write		= serial_console_write,
+	.device		= serial_console_device,
+	.setup		= serial_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
 };
 
 /*
diff -Nru a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c
--- a/arch/mips/dec/promcon.c	Sun Nov 17 20:30:14 2002
+++ b/arch/mips/dec/promcon.c	Sun Nov 17 20:30:14 2002
@@ -42,12 +42,12 @@
 
 static struct console sercons =
 {
-    name:	"ttyS",
-    write:	prom_console_write,
-    device:	prom_console_device,
-    setup:	prom_console_setup,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
+    .name	= "ttyS",
+    .write	= prom_console_write,
+    .device	= prom_console_device,
+    .setup	= prom_console_setup,
+    .flags	= CON_PRINTBUFFER,
+    .index	= -1,
 };
 
 /*
diff -Nru a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
--- a/arch/mips/kernel/gdb-stub.c	Sun Nov 17 20:30:15 2002
+++ b/arch/mips/kernel/gdb-stub.c	Sun Nov 17 20:30:15 2002
@@ -953,11 +953,11 @@
 }
 
 static struct console gdb_console = {
-	name:	"gdb",
-	write:	gdb_console_write,
-	device:	gdb_console_dev,
-	flags:	CON_PRINTBUFFER,
-	index:	-1
+	.name	= "gdb",
+	.write	= gdb_console_write,
+	.device	= gdb_console_dev,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1
 };
 
 __init void register_gdb_console(void)
diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
--- a/arch/mips/kernel/sysirix.c	Sun Nov 17 20:30:15 2002
+++ b/arch/mips/kernel/sysirix.c	Sun Nov 17 20:30:15 2002
@@ -518,7 +518,7 @@
 
 asmlinkage int irix_gtime(struct pt_regs *regs)
 {
-	return CURRENT_TIME;
+	return get_seconds();
 }
 
 int vm_enough_memory(long pages);
diff -Nru a/arch/mips/lib/rtc-no.c b/arch/mips/lib/rtc-no.c
--- a/arch/mips/lib/rtc-no.c	Sun Nov 17 20:30:02 2002
+++ b/arch/mips/lib/rtc-no.c	Sun Nov 17 20:30:02 2002
@@ -24,7 +24,7 @@
 }
 
 struct rtc_ops no_rtc_ops = {
-    rtc_read_data:  (void *) &shouldnt_happen,
-    rtc_write_data: (void *) &shouldnt_happen,
-    rtc_bcd_mode:   (void *) &shouldnt_happen
+    .rtc_read_data  = (void *) &shouldnt_happen,
+    .rtc_write_data = (void *) &shouldnt_happen,
+    .rtc_bcd_mode   = (void *) &shouldnt_happen
 };
diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig
--- a/arch/mips64/Kconfig	Sun Nov 17 20:30:12 2002
+++ b/arch/mips64/Kconfig	Sun Nov 17 20:30:12 2002
@@ -488,7 +488,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/mips64/sgi-ip27/ip27-console.c b/arch/mips64/sgi-ip27/ip27-console.c
--- a/arch/mips64/sgi-ip27/ip27-console.c	Sun Nov 17 20:30:15 2002
+++ b/arch/mips64/sgi-ip27/ip27-console.c	Sun Nov 17 20:30:15 2002
@@ -45,11 +45,11 @@
 }
 
 static struct console ip27_prom_console = {
-    name:	"prom",
-    write:	ip27prom_console_write,
-    device:	ip27prom_console_dev,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
+    .name	= "prom",
+    .write	= ip27prom_console_write,
+    .device	= ip27prom_console_dev,
+    .flags	= CON_PRINTBUFFER,
+    .index	= -1,
 };
 
 __init void ip27_setup_console(void)
diff -Nru a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c
--- a/arch/mips64/sgi-ip27/ip27-rtc.c	Sun Nov 17 20:30:14 2002
+++ b/arch/mips64/sgi-ip27/ip27-rtc.c	Sun Nov 17 20:30:14 2002
@@ -178,10 +178,10 @@
  */
 
 static struct file_operations rtc_fops = {
-	owner:		THIS_MODULE,
-	ioctl:		rtc_ioctl,
-	open:		rtc_open,
-	release:	rtc_release,
+	.owner		= THIS_MODULE,
+	.ioctl		= rtc_ioctl,
+	.open		= rtc_open,
+	.release	= rtc_release,
 };
 
 static struct miscdevice rtc_dev=
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/parisc/Kconfig	Sun Nov 17 20:30:14 2002
@@ -257,7 +257,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	Sun Nov 17 20:30:12 2002
+++ b/arch/parisc/kernel/sys_parisc32.c	Sun Nov 17 20:30:12 2002
@@ -660,7 +660,7 @@
 
 asmlinkage long sys32_time(time_t32 *tloc)
 {
-    time_t now = CURRENT_TIME;
+    time_t now = get_seconds();
     time_t32 now32 = now;
 
     if (tloc)
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/ppc/Kconfig	Sun Nov 17 20:30:15 2002
@@ -1393,7 +1393,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -1807,9 +1807,9 @@
 	bool "Highmem debugging"
 	depends on DEBUG_KERNEL && HIGHMEM
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
+#  config KALLSYMS
+#  	bool "Load all symbols for debugging/kksymoops"
+#  	depends on DEBUG_KERNEL
 
 config KGDB
 	bool "Include kgdb kernel debugger"
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/ppc64/Kconfig	Sun Nov 17 20:30:14 2002
@@ -332,7 +332,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
--- a/arch/ppc64/kernel/LparData.c	Sun Nov 17 20:30:12 2002
+++ b/arch/ppc64/kernel/LparData.c	Sun Nov 17 20:30:12 2002
@@ -149,11 +149,11 @@
 
 struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
 	{
-		xInstCacheOperandSize: 32,
-		xDataCacheOperandSize: 32,
-		xProcFreq:     50000000,
-		xTimeBaseFreq: 50000000,
-		xPVR: 0x3600
+		.xInstCacheOperandSize = 32,
+		.xDataCacheOperandSize = 32,
+		.xProcFreq     = 50000000,
+		.xTimeBaseFreq = 50000000,
+		.xPVR = 0x3600
 	}
 };
 	
diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c
--- a/arch/ppc64/kernel/pci_dma.c	Sun Nov 17 20:30:14 2002
+++ b/arch/ppc64/kernel/pci_dma.c	Sun Nov 17 20:30:14 2002
@@ -60,11 +60,11 @@
 struct TceTable   virtBusVethTceTable;	/* Tce table for virtual ethernet */
 struct TceTable   virtBusVioTceTable;	/* Tce table for virtual I/O */
 
-struct iSeries_Device_Node iSeries_veth_dev_node = { LogicalSlot: 0xFF, DevTceTable: &virtBusVethTceTable };
-struct iSeries_Device_Node iSeries_vio_dev_node  = { LogicalSlot: 0xFF, DevTceTable: &virtBusVioTceTable };
+struct iSeries_Device_Node iSeries_veth_dev_node = { .LogicalSlot = 0xFF, .DevTceTable = &virtBusVethTceTable };
+struct iSeries_Device_Node iSeries_vio_dev_node  = { .LogicalSlot = 0xFF, .DevTceTable = &virtBusVioTceTable };
 
-struct pci_dev    iSeries_veth_dev_st = { sysdata: &iSeries_veth_dev_node };
-struct pci_dev    iSeries_vio_dev_st  = { sysdata: &iSeries_vio_dev_node  };
+struct pci_dev    iSeries_veth_dev_st = { .sysdata = &iSeries_veth_dev_node };
+struct pci_dev    iSeries_vio_dev_st  = { .sysdata = &iSeries_vio_dev_node  };
 
 struct pci_dev  * iSeries_veth_dev = &iSeries_veth_dev_st;
 struct pci_dev  * iSeries_vio_dev  = &iSeries_vio_dev_st;
diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c
--- a/arch/ppc64/kernel/rtas_flash.c	Sun Nov 17 20:30:15 2002
+++ b/arch/ppc64/kernel/rtas_flash.c	Sun Nov 17 20:30:15 2002
@@ -199,10 +199,10 @@
 }
 
 static struct file_operations rtas_flash_operations = {
-	read:		rtas_flash_read,
-	write:		rtas_flash_write,
-	open:		rtas_flash_open,
-	release:	rtas_flash_release,
+	.read		= rtas_flash_read,
+	.write		= rtas_flash_write,
+	.open		= rtas_flash_open,
+	.release	= rtas_flash_release,
 };
 
 
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	Sun Nov 17 20:30:14 2002
+++ b/arch/ppc64/kernel/setup.c	Sun Nov 17 20:30:14 2002
@@ -119,10 +119,10 @@
 }
 
 static struct console udbg_console = {
-	name:	"udbg",
-	write:	udbg_console_write,
-	flags:	CON_PRINTBUFFER,
-	index:	-1,
+	.name	= "udbg",
+	.write	= udbg_console_write,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 static int early_console_initialized;
diff -Nru a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
--- a/arch/s390/kernel/debug.c	Sun Nov 17 20:30:03 2002
+++ b/arch/s390/kernel/debug.c	Sun Nov 17 20:30:03 2002
@@ -150,10 +150,11 @@
 static int initialized;
 
 static struct file_operations debug_file_ops = {
-	read:    debug_output,
-	write:   debug_input,	
-	open:    debug_open,
-	release: debug_close,
+	.owner	 = THIS_MODULE,
+	.read    = debug_output,
+	.write   = debug_input,	
+	.open    = debug_open,
+	.release = debug_close,
 };
 
 static struct proc_dir_entry *debug_proc_root_entry;
@@ -497,7 +498,6 @@
 #ifdef DEBUG
 	printk("debug_open\n");
 #endif
-	MOD_INC_USE_COUNT;
 	down(&debug_lock);
 
 	/* find debug log and view */
@@ -554,8 +554,6 @@
 
       out:
 	up(&debug_lock);
-	if (rc != 0)
-		MOD_DEC_USE_COUNT;
 	return rc;
 }
 
@@ -575,7 +573,6 @@
 	debug_info_free(p_info->debug_info_snap);
 	debug_info_put(p_info->debug_info_org);
 	kfree(file->private_data);
-	MOD_DEC_USE_COUNT;
 	return 0;		/* success */
 }
 
diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
--- a/arch/s390/kernel/setup.c	Sun Nov 17 20:30:03 2002
+++ b/arch/s390/kernel/setup.c	Sun Nov 17 20:30:03 2002
@@ -553,8 +553,8 @@
 {
 }
 struct seq_operations cpuinfo_op = {
-	start:	c_start,
-	next:	c_next,
-	stop:	c_stop,
-	show:	show_cpuinfo,
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
 };
diff -Nru a/arch/s390x/kernel/debug.c b/arch/s390x/kernel/debug.c
--- a/arch/s390x/kernel/debug.c	Sun Nov 17 20:30:03 2002
+++ b/arch/s390x/kernel/debug.c	Sun Nov 17 20:30:03 2002
@@ -150,10 +150,11 @@
 static int initialized;
 
 static struct file_operations debug_file_ops = {
-	read:    debug_output,
-	write:   debug_input,	
-	open:    debug_open,
-	release: debug_close,
+	.owner	 = THIS_MODULE,
+	.read    = debug_output,
+	.write   = debug_input,	
+	.open    = debug_open,
+	.release = debug_close,
 };
 
 static struct proc_dir_entry *debug_proc_root_entry;
@@ -497,7 +498,6 @@
 #ifdef DEBUG
 	printk("debug_open\n");
 #endif
-	MOD_INC_USE_COUNT;
 	down(&debug_lock);
 
 	/* find debug log and view */
@@ -554,8 +554,6 @@
 
       out:
 	up(&debug_lock);
-	if (rc != 0)
-		MOD_DEC_USE_COUNT;
 	return rc;
 }
 
@@ -575,7 +573,6 @@
 	debug_info_free(p_info->debug_info_snap);
 	debug_info_put(p_info->debug_info_org);
 	kfree(file->private_data);
-	MOD_DEC_USE_COUNT;
 	return 0;		/* success */
 }
 
diff -Nru a/arch/s390x/kernel/setup.c b/arch/s390x/kernel/setup.c
--- a/arch/s390x/kernel/setup.c	Sun Nov 17 20:30:13 2002
+++ b/arch/s390x/kernel/setup.c	Sun Nov 17 20:30:13 2002
@@ -547,8 +547,8 @@
 {
 }
 struct seq_operations cpuinfo_op = {
-	start:	c_start,
-	next:	c_next,
-	stop:	c_stop,
-	show:	show_cpuinfo,
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
 };
diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig
--- a/arch/sh/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/sh/Kconfig	Sun Nov 17 20:30:15 2002
@@ -733,7 +733,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	Sun Nov 17 20:30:02 2002
+++ b/arch/sparc/Kconfig	Sun Nov 17 20:30:02 2002
@@ -662,7 +662,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -683,7 +683,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sd_mod.o.  If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  Do not compile this driver as a
+	  <file:Documentation/scsi/scsi.txt>.  Do not compile this driver as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI disk. In this case, do not compile the driver
 	  for your SCSI host adapter (below) as a module either.
@@ -712,14 +712,14 @@
 	  If you want to use a SCSI tape drive under Linux, say Y and read the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and
-	  <file:drivers/scsi/README.st> in the kernel source.  This is NOT for
-	  SCSI CD-ROMs.
+	  <file:Documentation/scsi/st.txt> in the kernel source.  This is NOT
+	  for SCSI CD-ROMs.
 
 	  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 st.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config CHR_DEV_OSST
 	tristate "SCSI OnStream SC-x0 tape support"
@@ -734,7 +734,7 @@
 	  tapes (QIC-157) and can be driven by the standard driver st.
 	  For more information, you may have a look at the SCSI-HOWTO
 	  <http://www.linuxdoc.org/docs.html#howto>  and
-	  <file:drivers/scsi/README.osst>  in the kernel source.
+	  <file:Documentation/scsi/osst.txt>  in the kernel source.
 	  More info on the OnStream driver may be found on
 	  <http://linux1.onstream.nl/test/>
 	  Please also have a look at the standard st docu, as most of it
@@ -744,7 +744,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called osst.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR
 	tristate "SCSI CDROM support"
@@ -759,7 +759,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sr_mod.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR_VENDOR
 	bool "Enable vendor-specific extensions (for SCSI CDROM)"
@@ -805,13 +805,13 @@
 	  quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
 	  For other devices, it's possible that you'll have to write the
 	  driver software yourself. Please read the file
-	  <file:Documentation/scsi-generic.txt> for more information.
+	  <file:Documentation/scsi/scsi-generic.txt> for more information.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
-	  say N.
+	  <file:Documentation/scsi/scsi.txt>. The module will be called sg.o.
+	  If unsure, say N.
 
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile
--- a/arch/sparc/Makefile	Sun Nov 17 20:30:03 2002
+++ b/arch/sparc/Makefile	Sun Nov 17 20:30:03 2002
@@ -21,8 +21,9 @@
 ifeq ($(NEW_GAS),y)
 AS              := $(AS) -32
 LDFLAGS		:= -m elf32_sparc
-LDFLAGS_BLOB	:= --format binary --oformat elf32-sparc
 endif
+
+LDFLAGS_BLOB	:= --format binary --oformat elf32-sparc
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
 ifneq ($(IS_EGCS),y)
diff -Nru a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
--- a/arch/sparc/kernel/Makefile	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc/kernel/Makefile	Sun Nov 17 20:30:15 2002
@@ -22,6 +22,7 @@
 obj-$(CONFIG_SUN_AUXIO) += auxio.o
 obj-$(CONFIG_PCI) += ebus.o
 obj-$(CONFIG_SUN_PM) += apc.o pmc.o
+obj-$(CONFIG_MODULES) += module.o
 
 ifdef CONFIG_SUNOS_EMUL
 obj-y += sys_sunos.o sunos_ioctl.o
diff -Nru a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/sparc/kernel/module.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,139 @@
+/* Kernel module help for sparc32.
+ *
+ * Copyright (C) 2001 Rusty Russell.
+ * Copyright (C) 2002 David S. Miller.
+ */
+
+#include <linux/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+static void *alloc_and_zero(unsigned long size)
+{
+	void *ret;
+
+	/* We handle the zero case fine, unlike vmalloc */
+	if (size == 0)
+		return NULL;
+
+	ret = vmalloc(size);
+	if (!ret)
+		ret = ERR_PTR(-ENOMEM);
+	else
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+/* Free memory returned from module_core_alloc/module_init_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+void *module_core_alloc(const Elf32_Ehdr *hdr,
+			const Elf32_Shdr *sechdrs,
+			const char *secstrings,
+			struct module *module)
+{
+	return alloc_and_zero(module->core_size);
+}
+
+void *module_init_alloc(const Elf32_Ehdr *hdr,
+			const Elf32_Shdr *sechdrs,
+			const char *secstrings,
+			struct module *module)
+{
+	return alloc_and_zero(module->init_size);
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_offset;
+	Elf32_Sym *sym;
+	u8 *location;
+	u32 *loc32;
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		Elf32_Addr v;
+
+		/* This is where to make the change */
+		location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+			+ rel[i].r_offset;
+		loc32 = (u32 *) location;
+		/* This is the symbol it is referring to */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_offset
+			+ ELF32_R_SYM(rel[i].r_info);
+		if (!(v = sym->st_value)) {
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+		v += rel[i].r_addend;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_SPARC_32:
+			location[0] = v >> 24;
+			location[1] = v >> 16;
+			location[2] = v >>  8;
+			location[3] = v >>  0;
+			break;
+
+		case R_SPARC_WDISP30:
+			v -= (Elf32_Addr) location;
+			*loc32 = (*loc32 & ~0x3fffffff) |
+				((v >> 2) & 0x3fffffff);
+			break;
+
+		case R_SPARC_WDISP22:
+			v -= (Elf32_Addr) location;
+			*loc32 = (*loc32 & ~0x3fffff) |
+				((v >> 2) & 0x3fffff);
+			break;
+
+		case R_SPARC_LO10:
+			*loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff);
+			break;
+
+		case R_SPARC_HI22:
+			*loc32 = (*loc32 & ~0x3fffff) |
+				((v >> 10) & 0x3fffff);
+			break;
+
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %x\n",
+			       me->name,
+			       (int) (ELF32_R_TYPE(rel[i].r_info) & 0xff));
+			return -ENOEXEC;
+		};
+	}
+	return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Sun Nov 17 20:30:14 2002
+++ b/arch/sparc/kernel/systbls.S	Sun Nov 17 20:30:14 2002
@@ -54,7 +54,7 @@
 /*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
+/*180*/	.long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_ni_syscall
 /*185*/	.long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
 /*190*/	.long sys_init_module, sys_personality, sparc_remap_file_pages, sys_nis_syscall, sys_nis_syscall
 /*195*/	.long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
@@ -62,7 +62,7 @@
 /*205*/	.long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
-/*220*/	.long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
+/*220*/	.long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 /*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
 /*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
 					  /* "We are the Knights of the Forest of Ni!!" */
diff -Nru a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c
--- a/arch/sparc/mm/extable.c	Sun Nov 17 20:30:14 2002
+++ b/arch/sparc/mm/extable.c	Sun Nov 17 20:30:14 2002
@@ -62,7 +62,7 @@
 unsigned long
 search_exception_table(unsigned long addr, unsigned long *g2)
 {
-	unsigned long ret = 0, flags;
+	unsigned long ret = 0;
 
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
@@ -70,15 +70,19 @@
 			       __stop___ex_table-1, addr, g2);
 	return ret;
 #else
-	/* The kernel is the last "module" -- no need to treat it special.  */
-	struct module *mp;
+	unsigned long flags;
+	struct list_head *i;
 
+	/* The kernel is the last "module" -- no need to treat it special.  */
 	spin_lock_irqsave(&modlist_lock, flags);
-	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
+	list_for_each(i, &extables) {
+		struct exception_table *ex =
+			list_entry(i, struct exception_table, list);
+		if (ex->num_entries == 0)
 			continue;
-		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_end-1, addr, g2);
+		ret = search_one_table(ex->entry,
+				       ex->entry + ex->num_entries - 1,
+				       addr, g2);
 		if (ret)
 			break;
 	}
diff -Nru a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
--- a/arch/sparc/mm/io-unit.c	Sun Nov 17 20:30:14 2002
+++ b/arch/sparc/mm/io-unit.c	Sun Nov 17 20:30:14 2002
@@ -135,7 +135,8 @@
 
 	/* FIXME: Cache some resolved pages - often several sg entries are to the same page */
 	spin_lock_irqsave(&iounit->lock, flags);
-	for (; sz >= 0; sz--) {
+	while (sz != 0) {
+		--sz;
 		sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
 		sg[sz].dvma_length = sg[sz].length;
 	}
@@ -163,7 +164,8 @@
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
 
 	spin_lock_irqsave(&iounit->lock, flags);
-	for (; sz >= 0; sz--) {
+	while (sz != 0) {
+		--sz;
 		len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
 		vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
 		IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
diff -Nru a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
--- a/arch/sparc/mm/iommu.c	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc/mm/iommu.c	Sun Nov 17 20:30:15 2002
@@ -171,7 +171,8 @@
 
 static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	for (; sz >= 0; sz--) {
+	while (sz != 0) {
+		--sz;
 		sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
 		sg[sz].dvma_length = (__u32) (sg[sz].length);
 	}
@@ -180,7 +181,8 @@
 static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 	flush_page_for_dma(0);
-	for (; sz >= 0; sz--) {
+	while (sz != 0) {
+		--sz;
 		sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
 		sg[sz].dvma_length = (__u32) (sg[sz].length);
 	}
@@ -191,6 +193,7 @@
 	unsigned long page, oldpage = 0;
 
 	while(sz >= 0) {
+		--sz;
 		page = ((unsigned long) sg[sz].offset) & PAGE_MASK;
 		if (oldpage == page)
 			page += PAGE_SIZE; /* We flushed that page already */
@@ -200,7 +203,6 @@
 		}
 		sg[sz].dvma_address = (__u32) (page_address(sg[sz].page) + sg[sz].offset);
 		sg[sz].dvma_length = (__u32) (sg[sz].length);
-		sz--;
 		oldpage = page - PAGE_SIZE;
 	}
 }
diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
--- a/arch/sparc/mm/sun4c.c	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc/mm/sun4c.c	Sun Nov 17 20:30:15 2002
@@ -1219,10 +1219,10 @@
 
 static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	while (sz >= 0) {
+	while (sz != 0) {
+		--sz;
 		sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length);
 		sg[sz].dvma_length = sg[sz].length;
-		sz--;
 	}
 }
 
@@ -1235,9 +1235,9 @@
 
 static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	while (sz >= 0) {
+	while (sz != 0) {
+		--sz;
 		sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length);
-		sz--;
 	}
 }
 
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
--- a/arch/sparc/vmlinux.lds.S	Sun Nov 17 20:30:02 2002
+++ b/arch/sparc/vmlinux.lds.S	Sun Nov 17 20:30:02 2002
@@ -29,9 +29,12 @@
   __start___ex_table = .;
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
+
+  . = ALIGN(64);
   __start___ksymtab = .;
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
+
   __start___kallsyms = .;	/* All kernel symbols */
   __kallsyms : { *(__kallsyms) }
   __stop___kallsyms = .;
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc64/Kconfig	Sun Nov 17 20:30:15 2002
@@ -757,7 +757,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -778,7 +778,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sd_mod.o.  If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  Do not compile this driver as a
+	  <file:Documentation/scsi/scsi.txt>.  Do not compile this driver as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI disk. In this case, do not compile the driver
 	  for your SCSI host adapter (below) as a module either.
@@ -807,14 +807,14 @@
 	  If you want to use a SCSI tape drive under Linux, say Y and read the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and
-	  <file:drivers/scsi/README.st> in the kernel source.  This is NOT for
-	  SCSI CD-ROMs.
+	  <file:Documentation/scsi/st.txt> in the kernel source.  This is NOT
+	  for SCSI CD-ROMs.
 
 	  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 st.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config CHR_DEV_OSST
 	tristate "SCSI OnStream SC-x0 tape support"
@@ -829,7 +829,7 @@
 	  tapes (QIC-157) and can be driven by the standard driver st.
 	  For more information, you may have a look at the SCSI-HOWTO
 	  <http://www.linuxdoc.org/docs.html#howto>  and
-	  <file:drivers/scsi/README.osst>  in the kernel source.
+	  <file:Documentation/scsi/osst.txt>  in the kernel source.
 	  More info on the OnStream driver may be found on
 	  <http://linux1.onstream.nl/test/>
 	  Please also have a look at the standard st docu, as most of it
@@ -839,7 +839,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called osst.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR
 	tristate "SCSI CDROM support"
@@ -854,7 +854,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sr_mod.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR_VENDOR
 	bool "Enable vendor-specific extensions (for SCSI CDROM)"
@@ -900,13 +900,13 @@
 	  quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
 	  For other devices, it's possible that you'll have to write the
 	  driver software yourself. Please read the file
-	  <file:Documentation/scsi-generic.txt> for more information.
+	  <file:Documentation/scsi/scsi-generic.txt> for more information.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
-	  say N.
+	  <file:Documentation/scsi/scsi.txt>. The module will be called sg.o.
+	  If unsure, say N.
 
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
@@ -1025,7 +1025,7 @@
 	  Information on the configuration options for this controller can be
 	  found by checking the help file for each of the available
 	  configuration options. You should read
-	  <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
+	  <file:Documentation/scsi/aic7xxx_old.txt> at a minimum before
 	  contacting the maintainer with any questions.  The SCSI-HOWTO,
 	  available from <http://www.linuxdoc.org/docs.html#howto>, can also
 	  be of great help.
@@ -1051,7 +1051,7 @@
 
 	  If you say Y here, you can still turn off TCQ on troublesome devices
 	  with the use of the tag_info boot parameter.  See the file
-	  <file:drivers/scsi/README.aic7xxx> for more information on that and
+	  <file:Documentation/scsi/aic7xxx.txt> for more information on that and
 	  other aic7xxx setup commands.  If this option is turned off, you may
 	  still enable TCQ on known good devices by use of the tag_info boot
 	  parameter.
@@ -1061,7 +1061,7 @@
 
 	  However, TCQ can increase performance on some hard drives by as much
 	  as 50% or more, so it is recommended that if you say N here, you
-	  should at least read the <file:drivers/scsi/README.aic7xxx> file so
+	  should at least read the <file:Documentation/scsi/aic7xxx.txt> file so
 	  you will know how to enable this option manually should your drives
 	  prove to be safe in regards to TCQ.
 
@@ -1200,7 +1200,7 @@
 	  only one may be active at a time.  If you have a 53c8xx board, you
 	  probably do not want to use the "NCR53c7,8xx SCSI support".
 
-	  Please read <file:drivers/scsi/README.ncr53c8xx> for more
+	  Please read <file:Documentation/scsi/ncr53c8xx.txt> for more
 	  information.
 
 config SCSI_SYM53C8XX
@@ -1227,7 +1227,7 @@
 	  SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them.
 	  The 'excl' option is also supported by the NCR53C8XX driver.
 
-	  Please read <file:drivers/scsi/README.ncr53c8xx> for more
+	  Please read <file:Documentation/scsi/ncr53c8xx.txt> for more
 	  information.
 
 config SCSI_NCR53C8XX_DEFAULT_TAGS
@@ -1371,7 +1371,7 @@
 	  If you say Y here, make sure to choose "BIOS" at the question "PCI
 	  access mode".
 
-	  Please read the file <file:drivers/scsi/README.qlogicisp>.  You
+	  Please read the file <file:Documentation/scsi/qlogicisp.txt>.  You
 	  should also read the SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>.
 
diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
--- a/arch/sparc64/kernel/Makefile	Sun Nov 17 20:30:04 2002
+++ b/arch/sparc64/kernel/Makefile	Sun Nov 17 20:30:04 2002
@@ -21,6 +21,7 @@
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o
 obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
 obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
+obj-$(CONFIG_MODULES) += module.o
 
 ifdef CONFIG_SUNOS_EMUL
   obj-y += sys_sunos32.o sunos_ioctl32.o
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S	Sun Nov 17 20:30:13 2002
+++ b/arch/sparc64/kernel/head.S	Sun Nov 17 20:30:13 2002
@@ -482,7 +482,7 @@
 	membar	#Sync
 
 	mov	2, %g2		/* Set TLB type to cheetah+. */
-	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g5,g2,1f)
+	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g5,g7,1f)
 
 	mov	1, %g2		/* Set TLB type to cheetah. */
 
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc64/kernel/ioctl32.c	Sun Nov 17 20:30:15 2002
@@ -5265,7 +5265,7 @@
 {
 	int i;
 	if (!additional_ioctls) {
-		additional_ioctls = module_map(PAGE_SIZE);
+		additional_ioctls = vmalloc(PAGE_SIZE);
 		if (!additional_ioctls)
 			return -ENOMEM;
 		memset(additional_ioctls, 0, PAGE_SIZE);
diff -Nru a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/sparc64/kernel/module.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,260 @@
+/* Kernel module help for sparc64.
+ *
+ * Copyright (C) 2001 Rusty Russell.
+ * Copyright (C) 2002 David S. Miller.
+ */
+
+#include <linux/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+
+static struct vm_struct * modvmlist = NULL;
+
+static void module_unmap(void * addr)
+{
+	struct vm_struct **p, *tmp;
+	int i;
+
+	if (!addr)
+		return;
+	if ((PAGE_SIZE-1) & (unsigned long) addr) {
+		printk("Trying to unmap module with bad address (%p)\n", addr);
+		return;
+	}
+
+	for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
+		if (tmp->addr == addr) {
+			*p = tmp->next;
+			goto found;
+		}
+	}
+	printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
+	return;
+
+found:
+	unmap_vm_area(tmp);
+	
+	for (i = 0; i < tmp->nr_pages; i++) {
+		if (unlikely(!tmp->pages[i]))
+			BUG();
+		__free_page(tmp->pages[i]);
+	}
+
+	kfree(tmp->pages);
+	kfree(tmp);
+}
+
+
+static void *module_map(unsigned long size)
+{
+	struct vm_struct **p, *tmp, *area;
+	struct page **pages;
+	void * addr;
+	unsigned int nr_pages, array_size, i;
+
+	size = PAGE_ALIGN(size);
+	if (!size || size > MODULES_LEN)
+		return NULL;
+		
+	addr = (void *) MODULES_VADDR;
+	for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
+		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
+			break;
+		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+	}
+	if ((unsigned long) addr + size >= MODULES_END)
+		return NULL;
+	
+	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+	if (!area)
+		return NULL;
+	area->size = size + PAGE_SIZE;
+	area->addr = addr;
+	area->next = *p;
+	area->pages = NULL;
+	area->nr_pages = 0;
+	area->phys_addr = 0;
+	*p = area;
+
+	nr_pages = size >> PAGE_SHIFT;
+	array_size = (nr_pages * sizeof(struct page *));
+
+	area->nr_pages = nr_pages;
+	area->pages = pages = kmalloc(array_size, GFP_KERNEL);
+	if (!area->pages)
+		goto fail;
+
+	memset(area->pages, 0, array_size);
+
+	for (i = 0; i < area->nr_pages; i++) {
+		area->pages[i] = alloc_page(GFP_KERNEL);
+		if (unlikely(!area->pages[i]))
+			goto fail;
+	}
+	
+	if (map_vm_area(area, PAGE_KERNEL, &pages)) {
+		unmap_vm_area(area);
+		goto fail;
+	}
+
+	return area->addr;
+
+fail:
+	if (area->pages) {
+		for (i = 0; i < area->nr_pages; i++) {
+			if (area->pages[i])
+				__free_page(area->pages[i]);
+		}
+		kfree(area->pages);
+	}
+	kfree(area);
+
+	return NULL;
+}
+
+static void *alloc_and_zero(unsigned long size)
+{
+	void *ret;
+
+	/* We handle the zero case fine, unlike vmalloc */
+	if (size == 0)
+		return NULL;
+
+	ret = module_map(size);
+	if (!ret)
+		ret = ERR_PTR(-ENOMEM);
+	else
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+/* Free memory returned from module_core_alloc/module_init_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	module_unmap(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+void *module_core_alloc(const Elf64_Ehdr *hdr,
+			const Elf64_Shdr *sechdrs,
+			const char *secstrings,
+			struct module *module)
+{
+	return alloc_and_zero(module->core_size);
+}
+
+void *module_init_alloc(const Elf64_Ehdr *hdr,
+			const Elf64_Shdr *sechdrs,
+			const char *secstrings,
+			struct module *module)
+{
+	return alloc_and_zero(module->init_size);
+}
+
+int apply_relocate(Elf64_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int apply_relocate_add(Elf64_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i;
+	Elf64_Rela *rel = (void *)sechdrs[relsec].sh_offset;
+	Elf64_Sym *sym;
+	u8 *location;
+	u32 *loc32;
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		Elf64_Addr v;
+
+		/* This is where to make the change */
+		location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+			+ rel[i].r_offset;
+		loc32 = (u32 *) location;
+
+		BUG_ON(((u64)location >> (u64)32) != (u64)0);
+
+		/* This is the symbol it is referring to */
+		sym = (Elf64_Sym *)sechdrs[symindex].sh_offset
+			+ ELF64_R_SYM(rel[i].r_info);
+		if (!(v = sym->st_value)) {
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+		v += rel[i].r_addend;
+
+		switch (ELF64_R_TYPE(rel[i].r_info) & 0xff) {
+		case R_SPARC_64:
+			location[0] = v >> 56;
+			location[1] = v >> 48;
+			location[2] = v >> 40;
+			location[3] = v >> 32;
+			location[4] = v >> 24;
+			location[5] = v >> 16;
+			location[6] = v >>  8;
+			location[7] = v >>  0;
+			break;
+
+		case R_SPARC_32:
+			location[0] = v >> 24;
+			location[1] = v >> 16;
+			location[2] = v >>  8;
+			location[3] = v >>  0;
+			break;
+
+		case R_SPARC_WDISP30:
+			v -= (Elf64_Addr) location;
+			*loc32 = (*loc32 & ~0x3fffffff) |
+				((v >> 2) & 0x3fffffff);
+			break;
+
+		case R_SPARC_WDISP22:
+			v -= (Elf64_Addr) location;
+			*loc32 = (*loc32 & ~0x3fffff) |
+				((v >> 2) & 0x3fffff);
+			break;
+
+		case R_SPARC_LO10:
+			*loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff);
+			break;
+
+		case R_SPARC_HI22:
+			*loc32 = (*loc32 & ~0x3fffff) |
+				((v >> 10) & 0x3fffff);
+			break;
+
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %x\n",
+			       me->name,
+			       (int) (ELF64_R_TYPE(rel[i].r_info) & 0xff));
+			return -ENOEXEC;
+		};
+	}
+	return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
--- a/arch/sparc64/kernel/setup.c	Sun Nov 17 20:30:12 2002
+++ b/arch/sparc64/kernel/setup.c	Sun Nov 17 20:30:12 2002
@@ -573,8 +573,6 @@
 		serial_console = 2;
 		break;
 	};
-	if (serial_console)
-		conswitchp = NULL;
 
 	paging_init();
 }
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Sun Nov 17 20:30:14 2002
+++ b/arch/sparc64/kernel/sys_sparc32.c	Sun Nov 17 20:30:14 2002
@@ -3113,388 +3113,22 @@
 
 #ifdef CONFIG_MODULES
 
-extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
+extern asmlinkage long sys_init_module(void *, unsigned long, const char *);
 
-asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
+asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
 {
-	return sys_create_module(name_user, (size_t)size);
+	return sys_init_module(umod, len, uargs);
 }
 
-extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
+extern asmlinkage long sys_delete_module(const char *, unsigned int);
 
-/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
- * module structure, even if from 32bit modutils... Why to pollute kernel... :))
- */
-asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
-{
-	return sys_init_module(name_user, mod_user);
-}
-
-extern asmlinkage int sys_delete_module(const char *name_user);
-
-asmlinkage int sys32_delete_module(const char *name_user)
-{
-	return sys_delete_module(name_user);
-}
-
-struct module_info32 {
-	u32 addr;
-	u32 size;
-	u32 flags;
-	s32 usecount;
-};
-
-/* Query various bits about modules.  */
-
-static inline long
-get_mod_name(const char *user_name, char **buf)
-{
-	unsigned long page;
-	long retval;
-
-	if ((unsigned long)user_name >= TASK_SIZE
-	    && !segment_eq(get_fs (), KERNEL_DS))
-		return -EFAULT;
-
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
-	if (retval > 0) {
-		if (retval < PAGE_SIZE) {
-			*buf = (char *)page;
-			return retval;
-		}
-		retval = -ENAMETOOLONG;
-	} else if (!retval)
-		retval = -EINVAL;
-
-	free_page(page);
-	return retval;
-}
-
-static inline void
-put_mod_name(char *buf)
-{
-	free_page((unsigned long)buf);
-}
-
-static __inline__ struct module *find_module(const char *name)
-{
-	struct module *mod;
-
-	for (mod = module_list; mod ; mod = mod->next) {
-		if (mod->flags & MOD_DELETED)
-			continue;
-		if (!strcmp(mod->name, name))
-			break;
-	}
-
-	return mod;
-}
-
-static int
-qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
-	struct module *mod;
-	size_t nmod, space, len;
-
-	nmod = space = 0;
-
-	for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
-		len = strlen(mod->name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, mod->name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
-	}
-
-	if (put_user(nmod, ret))
-		return -EFAULT;
-	else
-		return 0;
-
-calc_space_needed:
-	space += len;
-	while ((mod = mod->next)->next != NULL)
-		space += strlen(mod->name)+1;
-
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
-}
-
-static int
-qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
-	size_t i, space, len;
-
-	if (mod->next == NULL)
-		return -EINVAL;
-	if (!MOD_CAN_QUERY(mod))
-		return put_user(0, ret);
-
-	space = 0;
-	for (i = 0; i < mod->ndeps; ++i) {
-		const char *dep_name = mod->deps[i].dep->name;
-
-		len = strlen(dep_name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, dep_name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
-	}
-
-	return put_user(i, ret);
-
-calc_space_needed:
-	space += len;
-	while (++i < mod->ndeps)
-		space += strlen(mod->deps[i].dep->name)+1;
-
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
-}
-
-static int
-qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
-	size_t nrefs, space, len;
-	struct module_ref *ref;
-
-	if (mod->next == NULL)
-		return -EINVAL;
-	if (!MOD_CAN_QUERY(mod))
-		if (put_user(0, ret))
-			return -EFAULT;
-		else
-			return 0;
-
-	space = 0;
-	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
-		const char *ref_name = ref->ref->name;
-
-		len = strlen(ref_name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, ref_name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
-	}
-
-	if (put_user(nrefs, ret))
-		return -EFAULT;
-	else
-		return 0;
-
-calc_space_needed:
-	space += len;
-	while ((ref = ref->next_ref) != NULL)
-		space += strlen(ref->ref->name)+1;
-
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
-}
-
-static inline int
-qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
-	size_t i, space, len;
-	struct module_symbol *s;
-	char *strings;
-	unsigned *vals;
-
-	if (!MOD_CAN_QUERY(mod))
-		if (put_user(0, ret))
-			return -EFAULT;
-		else
-			return 0;
-
-	space = mod->nsyms * 2*sizeof(u32);
-
-	i = len = 0;
-	s = mod->syms;
-
-	if (space > bufsize)
-		goto calc_space_needed;
-
-	if (!access_ok(VERIFY_WRITE, buf, space))
-		return -EFAULT;
-
-	bufsize -= space;
-	vals = (unsigned *)buf;
-	strings = buf+space;
-
-	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
-		len = strlen(s->name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-
-		if (copy_to_user(strings, s->name, len)
-		    || __put_user(s->value, vals+0)
-		    || __put_user(space, vals+1))
-			return -EFAULT;
-
-		strings += len;
-		bufsize -= len;
-		space += len;
-	}
-
-	if (put_user(i, ret))
-		return -EFAULT;
-	else
-		return 0;
-
-calc_space_needed:
-	for (; i < mod->nsyms; ++i, ++s)
-		space += strlen(s->name)+1;
-
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
-}
-
-static inline int
-qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
 {
-	int error = 0;
-
-	if (mod->next == NULL)
-		return -EINVAL;
-
-	if (sizeof(struct module_info32) <= bufsize) {
-		struct module_info32 info;
-		info.addr = (unsigned long)mod;
-		info.size = mod->size;
-		info.flags = mod->flags;
-		info.usecount =
-			((mod_member_present(mod, can_unload)
-			  && mod->can_unload)
-			 ? -1 : atomic_read(&mod->uc.usecount));
-
-		if (copy_to_user(buf, &info, sizeof(struct module_info32)))
-			return -EFAULT;
-	} else
-		error = -ENOSPC;
-
-	if (put_user(sizeof(struct module_info32), ret))
-		return -EFAULT;
-
-	return error;
-}
-
-asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
-{
-	struct module *mod;
-	int err;
-
-	lock_kernel();
-	if (name_user == 0) {
-		/* This finds "kernel_module" which is not exported. */
-		for(mod = module_list; mod->next != NULL; mod = mod->next)
-			;
-	} else {
-		long namelen;
-		char *name;
-
-		if ((namelen = get_mod_name(name_user, &name)) < 0) {
-			err = namelen;
-			goto out;
-		}
-		err = -ENOENT;
-		if (namelen == 0) {
-			/* This finds "kernel_module" which is not exported. */
-			for(mod = module_list; mod->next != NULL; mod = mod->next)
-				;
-		} else if ((mod = find_module(name)) == NULL) {
-			put_mod_name(name);
-			goto out;
-		}
-		put_mod_name(name);
-	}
-
-	switch (which)
-	{
-	case 0:
-		err = 0;
-		break;
-	case QM_MODULES:
-		err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
-		break;
-	case QM_DEPS:
-		err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
-		break;
-	case QM_REFS:
-		err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
-		break;
-	case QM_SYMBOLS:
-		err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
-		break;
-	case QM_INFO:
-		err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-out:
-	unlock_kernel();
-	return err;
-}
-
-struct kernel_sym32 {
-	u32 value;
-	char name[60];
-};
-		 
-extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
-
-asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
-{
-	int len, i;
-	struct kernel_sym *tbl;
-	mm_segment_t old_fs;
-	
-	len = sys_get_kernel_syms(NULL);
-	if (!table) return len;
-	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
-	if (!tbl) return -ENOMEM;
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	sys_get_kernel_syms(tbl);
-	set_fs (old_fs);
-	for (i = 0; i < len; i++, table++) {
-		if (put_user (tbl[i].value, &table->value) ||
-		    copy_to_user (table->name, tbl[i].name, 60))
-			break;
-	}
-	kfree (tbl);
-	return i;
+	return sys_delete_module(name_user, flags);
 }
 
 #else /* CONFIG_MODULES */
 
-asmlinkage unsigned long
-sys32_create_module(const char *name_user, size_t size)
-{
-	return -ENOSYS;
-}
-
 asmlinkage int
 sys32_init_module(const char *name_user, struct module *mod_user)
 {
@@ -3507,24 +3141,6 @@
 	return -ENOSYS;
 }
 
-asmlinkage int
-sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
-		 size_t *ret)
-{
-	/* Let the program know about the new interface.  Not that
-	   it'll do them much good.  */
-	if (which == 0)
-		return 0;
-
-	return -ENOSYS;
-}
-
-asmlinkage int
-sys32_get_kernel_syms(struct kernel_sym *table)
-{
-	return -ENOSYS;
-}
-
 #endif  /* CONFIG_MODULES */
 
 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
@@ -4336,7 +3952,7 @@
 				    &kernel_mask);
 	set_fs(old_fs);
 
-	if (ret == 0) {
+	if (ret > 0) {
 		if (put_user(kernel_mask, user_mask_ptr))
 			ret = -EFAULT;
 	}
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Sun Nov 17 20:30:13 2002
+++ b/arch/sparc64/kernel/systbls.S	Sun Nov 17 20:30:13 2002
@@ -55,7 +55,7 @@
 	.word sys_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
+/*180*/	.word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys_ni_syscall
 	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname
 /*190*/	.word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
@@ -63,7 +63,7 @@
 	.word sys32_readahead, sys32_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
-/*220*/	.word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
+/*220*/	.word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
 /*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_alloc_hugepages
 	.word sys_free_hugepages, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
@@ -114,7 +114,7 @@
 	.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
+/*180*/	.word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
 	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname
 /*190*/	.word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
@@ -122,7 +122,7 @@
 	.word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_nis_syscall
 /*210*/	.word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 	.word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
-/*220*/	.word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
+/*220*/	.word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
 /*230*/	.word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall
 	.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
diff -Nru a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
--- a/arch/sparc64/mm/Makefile	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc64/mm/Makefile	Sun Nov 17 20:30:15 2002
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -ansi
 
-obj-y    := ultra.o fault.o init.o generic.o extable.o modutil.o
+obj-y    := ultra.o fault.o init.o generic.o extable.o
 
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 
diff -Nru a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
--- a/arch/sparc64/mm/extable.c	Sun Nov 17 20:30:13 2002
+++ b/arch/sparc64/mm/extable.c	Sun Nov 17 20:30:13 2002
@@ -62,7 +62,7 @@
 unsigned long
 search_exception_table(unsigned long addr, unsigned long *g2)
 {
-	unsigned long ret = 0, flags;
+	unsigned long ret = 0;
 
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
@@ -70,15 +70,19 @@
 			       __stop___ex_table-1, addr, g2);
 	return ret;
 #else
-	/* The kernel is the last "module" -- no need to treat it special.  */
-	struct module *mp;
+	unsigned long flags;
+	struct list_head *i;
 
+	/* The kernel is the last "module" -- no need to treat it special.  */
 	spin_lock_irqsave(&modlist_lock, flags);
-	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
+	list_for_each(i, &extables) {
+		struct exception_table *ex =
+			list_entry(i, struct exception_table, list);
+		if (ex->num_entries == 0)
 			continue;
-		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_end-1, addr, g2);
+		ret = search_one_table(ex->entry,
+				       ex->entry + ex->num_entries - 1,
+				       addr, g2);
 		if (ret)
 			break;
 	}
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Sun Nov 17 20:30:12 2002
+++ b/arch/sparc64/mm/init.c	Sun Nov 17 20:30:12 2002
@@ -1696,7 +1696,7 @@
 
 #ifdef CONFIG_HUGETLB_PAGE
 long htlbpagemem = 0;
-long htlbpage_max;
+int htlbpage_max;
 long htlbzone_pages;
 extern struct list_head htlbpage_freelist;
 #endif
diff -Nru a/arch/sparc64/mm/modutil.c b/arch/sparc64/mm/modutil.c
--- a/arch/sparc64/mm/modutil.c	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,117 +0,0 @@
-/*  $Id: modutil.c,v 1.11 2001/12/05 06:05:35 davem Exp $
- *  arch/sparc64/mm/modutil.c
- *
- *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *  Based upon code written by Linus Torvalds and others.
- */
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static struct vm_struct * modvmlist = NULL;
-
-void module_unmap (void * addr)
-{
-	struct vm_struct **p, *tmp;
-	int i;
-
-	if (!addr)
-		return;
-	if ((PAGE_SIZE-1) & (unsigned long) addr) {
-		printk("Trying to unmap module with bad address (%p)\n", addr);
-		return;
-	}
-
-	for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
-		if (tmp->addr == addr) {
-			*p = tmp->next;
-			goto found;
-		}
-	}
-	printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
-	return;
-
-found:
-	unmap_vm_area(tmp);
-	
-	for (i = 0; i < tmp->nr_pages; i++) {
-		if (unlikely(!tmp->pages[i]))
-			BUG();
-		__free_page(tmp->pages[i]);
-	}
-
-	kfree(tmp->pages);
-	kfree(tmp);
-}
-
-
-void * module_map (unsigned long size)
-{
-	struct vm_struct **p, *tmp, *area;
-	struct page **pages;
-	void * addr;
-	unsigned int nr_pages, array_size, i;
-
-	size = PAGE_ALIGN(size);
-	if (!size || size > MODULES_LEN)
-		return NULL;
-		
-	addr = (void *) MODULES_VADDR;
-	for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
-		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
-			break;
-		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
-	}
-	if ((unsigned long) addr + size >= MODULES_END)
-		return NULL;
-	
-	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
-	if (!area)
-		return NULL;
-	area->size = size + PAGE_SIZE;
-	area->addr = addr;
-	area->next = *p;
-	area->pages = NULL;
-	area->nr_pages = 0;
-	area->phys_addr = 0;
-	*p = area;
-
-	nr_pages = size >> PAGE_SHIFT;
-	array_size = (nr_pages * sizeof(struct page *));
-
-	area->nr_pages = nr_pages;
-	area->pages = pages = kmalloc(array_size, GFP_KERNEL);
-	if (!area->pages)
-		goto fail;
-
-	memset(area->pages, 0, array_size);
-
-	for (i = 0; i < area->nr_pages; i++) {
-		area->pages[i] = alloc_page(GFP_KERNEL);
-		if (unlikely(!area->pages[i]))
-			goto fail;
-	}
-	
-	if (map_vm_area(area, PAGE_KERNEL, &pages)) {
-		unmap_vm_area(area);
-		goto fail;
-	}
-
-	return area->addr;
-
-fail:
-	if (area->pages) {
-		for (i = 0; i < area->nr_pages; i++) {
-			if (area->pages[i])
-				__free_page(area->pages[i]);
-		}
-		kfree(area->pages);
-	}
-	kfree(area);
-
-	return NULL;
-}
diff -Nru a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
--- a/arch/sparc64/solaris/timod.c	Sun Nov 17 20:30:13 2002
+++ b/arch/sparc64/solaris/timod.c	Sun Nov 17 20:30:13 2002
@@ -651,10 +651,11 @@
 		SOLD("LISTEN done");
 	}
 	if (!(filp->f_flags & O_NONBLOCK)) {
-		poll_table wait_table, *wait;
+		struct poll_wqueues wait_table;
+		poll_table *wait;
 
 		poll_initwait(&wait_table);
-		wait = &wait_table;
+		wait = &wait_table.pt;
 		for(;;) {
 			SOLD("loop");
 			set_current_state(TASK_INTERRUPTIBLE);
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
--- a/arch/sparc64/vmlinux.lds.S	Sun Nov 17 20:30:15 2002
+++ b/arch/sparc64/vmlinux.lds.S	Sun Nov 17 20:30:15 2002
@@ -27,10 +27,13 @@
   _edata  =  .;
   PROVIDE (edata = .);
   .fixup   : { *(.fixup) }
+
   . = ALIGN(16);
   __start___ex_table = .;
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
+
+  . = ALIGN(64);
   __start___ksymtab = .;
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
diff -Nru a/arch/um/Makefile b/arch/um/Makefile
--- a/arch/um/Makefile	Sun Nov 17 20:30:14 2002
+++ b/arch/um/Makefile	Sun Nov 17 20:30:14 2002
@@ -1,9 +1,6 @@
 ARCH_DIR = arch/um
 OS := $(shell uname -s)
 
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
-
 EXTRAVERSION := $(EXTRAVERSION)-1um
 include/linux/version.h: arch/$(ARCH)/Makefile
 
@@ -59,16 +56,17 @@
 
 GEN_HEADERS = $(ARCH_DIR)/include/task.h
 
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
+
 $(ARCH_DIR)/vmlinux.lds.S :
 	touch $@
 
 prepare: $(ARCH_SYMLINKS) $(GEN_HEADERS)
 
-
 LDFLAGS_vmlinux = -r $(ARCH_DIR)/main.o
 
 vmlinux: $(ARCH_DIR)/main.o 
-
 
 $(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
 	$(call if_changed_dep,as_s_S)
diff -Nru a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
--- a/arch/um/Makefile-i386	Sun Nov 17 20:30:15 2002
+++ b/arch/um/Makefile-i386	Sun Nov 17 20:30:15 2002
@@ -8,6 +8,9 @@
 ELF_ARCH = $(SUBARCH)
 ELF_FORMAT = elf32-$(SUBARCH)
 
+OBJCOPYFLAGS  := -O binary -R .note -R .comment -S
+LDFLAGS_BLOB	:= --format binary --oformat elf32-i386
+
 SYS_DIR		:= $(ARCH_DIR)/include/sysdep-i386
 SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/util
 
@@ -21,11 +24,14 @@
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
 	$< > $@
 
-$(SYS_UTIL_DIR)/mk_sc $(SYS_UTIL_DIR)/mk_thread: $(SYS_UTIL_DIR) FORCE ; 
+$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
+	@$(call descend,$(SYS_UTIL_DIR),$@)
+
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) FORCE ; 
+	@$(call descend,$(SYS_UTIL_DIR),$@)
 
 $(SYS_UTIL_DIR): include/asm FORCE
 	@$(call descend,$@,)
 
 sysclean :
 	rm -f $(SYS_HEADERS)
-	@$(call descend,$(SYS_DIR),clean)
diff -Nru a/arch/um/defconfig b/arch/um/defconfig
--- a/arch/um/defconfig	Sun Nov 17 20:30:14 2002
+++ b/arch/um/defconfig	Sun Nov 17 20:30:14 2002
@@ -219,13 +219,16 @@
 # CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
 # CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 # CONFIG_SUNRPC is not set
 # CONFIG_LOCKD is not set
 # CONFIG_EXPORTFS is not set
+# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -236,6 +239,7 @@
 # CONFIG_NCPFS_SMALLDOS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_AFS_FS is not set
 # CONFIG_ZISOFS_FS is not set
 
 #
@@ -332,7 +336,9 @@
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -362,6 +368,8 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PCMCIA is not set
 
 #
 # Self-contained MTD device drivers
diff -Nru a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
--- a/arch/um/drivers/Makefile	Sun Nov 17 20:30:14 2002
+++ b/arch/um/drivers/Makefile	Sun Nov 17 20:30:14 2002
@@ -15,7 +15,7 @@
 # So, what this does is figure out by hand (crudely) what file -lpcap really 
 # is and just use it.
 
-PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.{a,so}; do \
+PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.a; do \
        [ -f $$f ] && echo $$f ; done | head -1)
 
 slip-objs := slip_kern.o slip_user.o
@@ -47,7 +47,7 @@
 obj-$(CONFIG_PORT_CHAN) += port.o
 obj-$(CONFIG_PTY_CHAN) += pty.o
 obj-$(CONFIG_TTY_CHAN) += tty.o 
-obj-$(CONFIG_XTERM_CHAN) += xterm.o
+obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
 
 CFLAGS_pcap_user.o = -I/usr/include/pcap
diff -Nru a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
--- a/arch/um/drivers/mconsole_kern.c	Sun Nov 17 20:30:02 2002
+++ b/arch/um/drivers/mconsole_kern.c	Sun Nov 17 20:30:02 2002
@@ -111,6 +111,8 @@
     remove <dev> - Remove a device from UML
     sysrq <letter> - Performs the SysRq action controlled by the letter
     cad - invoke the Ctl-Alt-Del handler
+    stop - pause the UML; it will do nothing until it receives a 'go'
+    go - continue the UML after a 'stop'
 "
 
 void mconsole_help(struct mc_request *req)
diff -Nru a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
--- a/arch/um/drivers/port_kern.c	Sun Nov 17 20:30:02 2002
+++ b/arch/um/drivers/port_kern.c	Sun Nov 17 20:30:02 2002
@@ -20,6 +20,7 @@
 
 struct port_list {
 	struct list_head list;
+	int has_connection;
 	struct semaphore sem;
 	int port;
 	int fd;
@@ -49,28 +50,32 @@
 	struct connection *conn = data;
 	int fd;
 
-	list_del(&conn->list);
-
  	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
+		if(fd == -EAGAIN)
+			return;
+
 		printk("os_rcv_fd returned %d\n", -fd);
 		os_close_file(conn->fd);
 	}
+
+	list_del(&conn->list);
+
 	conn->fd = fd;
 	list_add(&conn->list, &conn->port->connections);
 
 	up(&conn->port->sem);
 }
 
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static int port_accept(struct port_list *port)
 {
-	struct port_list *port = data;
 	struct connection *conn;
-	int fd, socket[2], pid;
+	int fd, socket[2], pid, ret = 0;
 
 	fd = port_connection(port->fd, socket, &pid);
 	if(fd < 0){
-		printk("port_connection returned %d\n", -fd);
+		if(fd != -EAGAIN)
+			printk("port_connection returned %d\n", -fd);
 		goto out;
 	}
 
@@ -94,6 +99,7 @@
 	}
 
 	list_add(&conn->list, &port->pending);
+	ret = 1;
 	goto out;
 
  out_free:
@@ -102,17 +108,45 @@
 	os_close_file(fd);
 	if(pid != -1) os_kill_process(pid);
  out:
-	reactivate_fd(port->fd, ACCEPT_IRQ);
+	return(ret);
 } 
 
 DECLARE_MUTEX(ports_sem);
 struct list_head ports = LIST_HEAD_INIT(ports);
 
+void port_work_proc(void *unused)
+{
+	struct port_list *port;
+	struct list_head *ele;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	list_for_each(ele, &ports){
+		port = list_entry(ele, struct port_list, list);
+		if(!port->has_connection)
+			continue;
+		reactivate_fd(port->fd, ACCEPT_IRQ);
+		while(port_accept(port)) ;
+		port->has_connection = 0;
+	}
+	local_irq_restore(flags);
+}
+
+DECLARE_WORK(port_work, port_work_proc, NULL);
+
+static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+	struct port_list *port = data;
+
+	port->has_connection = 1;
+	schedule_work(&port_work);
+} 
+
 void *port_data(int port_num)
 {
 	struct list_head *ele;
 	struct port_list *port;
-	struct port_dev *dev;
+	struct port_dev *dev = NULL;
 	int fd;
 
 	down(&ports_sem);
@@ -140,13 +174,14 @@
 	}
 
 	*port = ((struct port_list) 
-		{ list : 	LIST_HEAD_INIT(port->list),
-		  sem :		__SEMAPHORE_INITIALIZER(port->sem, 0),
-		  lock :	SPIN_LOCK_UNLOCKED,
-		  port : 	port_num,
-		  fd : 		fd,
-		  pending :	LIST_HEAD_INIT(port->pending),
-		  connections :	LIST_HEAD_INIT(port->connections) });
+		{ list :	 	LIST_HEAD_INIT(port->list),
+		  has_connection :	0,
+		  sem :			__SEMAPHORE_INITIALIZER(port->sem, 0),
+		  lock :		SPIN_LOCK_UNLOCKED,
+		  port :	 	port_num,
+		  fd : 			fd,
+		  pending :		LIST_HEAD_INIT(port->pending),
+		  connections :		LIST_HEAD_INIT(port->connections) });
 	list_add(&port->list, &ports);
 
  found:
@@ -159,8 +194,7 @@
  	*dev = ((struct port_dev) { port : 		port,
  				    fd :		-1,
  				    helper_pid : 	-1 });
-	up(&ports_sem);
-	return(dev);
+	goto out;
 
  out_free:
 	kfree(port);
@@ -168,7 +202,7 @@
 	os_close_file(fd);
  out:
 	up(&ports_sem);
-	return(NULL);
+	return(dev);
 }
 
 void port_remove_dev(void *d)
diff -Nru a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
--- a/arch/um/drivers/ssl.c	Sun Nov 17 20:30:14 2002
+++ b/arch/um/drivers/ssl.c	Sun Nov 17 20:30:14 2002
@@ -44,6 +44,7 @@
 	xterm_title:	"Serial Line #%d",
 	raw:		1,
 	tramp_stack :	0,
+	in_kernel :	1,
 };
 
 static struct line_driver driver = {
diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
--- a/arch/um/drivers/stdio_console.c	Sun Nov 17 20:30:12 2002
+++ b/arch/um/drivers/stdio_console.c	Sun Nov 17 20:30:12 2002
@@ -75,6 +75,7 @@
 	xterm_title:	"Virtual Console #%d",
 	raw:		1,
 	tramp_stack :	0,
+	in_kernel :	1,
 };
 
 static struct line_driver driver = {
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	Sun Nov 17 20:30:14 2002
+++ b/arch/um/drivers/ubd_kern.c	Sun Nov 17 20:30:14 2002
@@ -6,12 +6,15 @@
 /* 2001-09-28...2002-04-17
  * Partition stuff by James_McMechan@hotmail.com
  * old style ubd by setting UBD_SHIFT to 0
+ * 2002-09-27...2002-10-18 massive tinkering for 2.5
+ * partitions have changed in 2.5
  */
 
 #define MAJOR_NR UBD_MAJOR
 #define UBD_SHIFT 4
 
 #include "linux/config.h"
+#include "linux/module.h"
 #include "linux/blk.h"
 #include "linux/blkdev.h"
 #include "linux/hdreg.h"
@@ -51,15 +54,17 @@
 static int ubd_release(struct inode * inode, struct file * file);
 static int ubd_ioctl(struct inode * inode, struct file * file,
 		     unsigned int cmd, unsigned long arg);
-static int ubd_revalidate(struct gendisk *disk);
 
 #define MAX_DEV (8)
+#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
+
+#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT)
 
 static struct block_device_operations ubd_blops = {
+        .owner		= THIS_MODULE,
         .open		= ubd_open,
         .release	= ubd_release,
         .ioctl		= ubd_ioctl,
-        .revalidate_disk= ubd_revalidate,
 };
 
 /* Protected by the queue_lock */
@@ -169,8 +174,6 @@
 	struct proc_dir_entry *dir, *ent;
 	char name[64];
 
-	if(!fake_ide) return;
-
 	if(proc_ide_root == NULL) make_proc_ide();
 
 	dir = proc_mkdir(dev_name, proc_ide);
@@ -415,88 +418,135 @@
 	return(os_file_size(file, size_out));
 }
 
-/* Initialized in an initcall, and unchanged thereafter */
-devfs_handle_t ubd_dir_handle;
-devfs_handle_t ubd_fake_dir_handle;
+static void ubd_close(struct ubd *dev)
+{
+	os_close_file(dev->fd);
+	if(dev->cow.file == NULL)
+		return;
 
-static int ubd_add(int n)
+	os_close_file(dev->cow.fd);
+	vfree(dev->cow.bitmap);
+	dev->cow.bitmap = NULL;
+}
+
+static int ubd_open_dev(struct ubd *dev)
 {
- 	devfs_handle_t real, fake;
-	char name[sizeof("nnnnnn\0")];
-	struct ubd *dev = &ubd_dev[n];
-	struct gendisk *disk, *fake_disk = NULL;
-	u64 size;
+	struct openflags flags;
+	int err, n, create_cow, *create_ptr;
 
-	if (!dev->file)
-		goto out;
+	create_cow = 0;
+	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
+	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
+				&dev->cow.data_offset, create_ptr);
 
-	disk = alloc_disk(1 << UBD_SHIFT);
-	if (!disk)
-		return -1;
-	disk->major = MAJOR_NR;
-	disk->first_minor = n << UBD_SHIFT;
-	disk->fops = &ubd_blops;
-	if (fakehd_set)
-		sprintf(disk->disk_name, "hd%c", n + 'a');
-	else
-		sprintf(disk->disk_name, "ubd%d", n);
-
-	if (fake_major) {
-		fake_disk = alloc_disk(1 << UBD_SHIFT);
-		if (!fake_disk) {
-			put_disk(disk);
-			return -1;
+	if((dev->fd == -ENOENT) && create_cow){
+		n = dev - ubd_dev;
+		dev->fd = create_cow_file(dev->file, dev->cow.file, 
+					  dev->openflags, 1 << 9,
+					  &dev->cow.bitmap_offset, 
+					  &dev->cow.bitmap_len,
+					  &dev->cow.data_offset);
+		if(dev->fd >= 0){
+			printk(KERN_INFO "Creating \"%s\" as COW file for "
+			       "\"%s\"\n", dev->file, dev->cow.file);
 		}
-		fake_disk->major = fake_major;
-		fake_disk->first_minor = n << UBD_SHIFT;
-		fake_disk->fops = &ubd_blops;
-		sprintf(fake_disk->disk_name, "ubd%d", n);
-		fake_gendisk[n] = fake_disk;
 	}
 
-	ubd_gendisk[n] = disk;
-
-	if (!dev->is_dir && ubd_file_size(dev, &size) == 0) {
-		set_capacity(disk, size/512);
-		if (fake_major)
-			set_capacity(fake_disk, size/512);
-	}
- 
-	sprintf(name, "%d", n);
-	real = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE, 
-			      MAJOR_NR, n << UBD_SHIFT,
-			      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP,
-			      &ubd_blops, NULL);
- 	if(real == NULL) 
- 		goto out;
- 	ubd_dev[n].real = real;
-
-	if (fake_major) {
-		fake = devfs_register(ubd_fake_dir_handle, name, 
-				      DEVFS_FL_REMOVABLE, fake_major,
-				      n << UBD_SHIFT, 
-				      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
-				      S_IWGRP, &ubd_blops, NULL);
- 		if(fake == NULL)
-			goto out_unregister;
-
- 		ubd_dev[n].fake = fake;
-		fake_disk->private_data = &ubd_dev[n];
-		fake_disk->queue = &ubd_queue;
-		add_disk(fake_disk);
+	if(dev->fd < 0) return(dev->fd);
+
+	if(dev->cow.file != NULL){
+		err = -ENOMEM;
+		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
+		if(dev->cow.bitmap == NULL) goto error;
+		flush_tlb_kernel_vm();
+
+		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
+				      dev->cow.bitmap_offset, 
+				      dev->cow.bitmap_len);
+		if(err) goto error;
+
+		flags = dev->openflags;
+		flags.w = 0;
+		err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, 
+				    NULL, NULL);
+		if(err < 0) goto error;
+		dev->cow.fd = err;
 	}
- 
-	disk->private_data = &ubd_dev[n];
+	return(0);
+ error:
+	os_close_file(dev->fd);
+	return(err);
+}
+
+static int ubd_new_disk(int major, u64 size, char *name, int unit,
+			struct gendisk **disk_out, devfs_handle_t dir_handle,
+			devfs_handle_t *handle_out)
+{
+	char devfs_name[sizeof("nnnnnn\0")];
+	struct gendisk *disk;
+	int minor = unit << UBD_SHIFT;
+
+	disk = alloc_disk(1 << UBD_SHIFT);
+	if(disk == NULL)
+		return(-ENOMEM);
+
+	disk->major = major;
+	disk->first_minor = minor;
+	disk->fops = &ubd_blops;
+	set_capacity(disk, size / 512);
+	/* needs to be ubd -> /dev/ubd/discX/disc */
+	sprintf(disk->disk_name, "ubd");
+	*disk_out = disk;
+
+	/* /dev/ubd/N style names */
+	sprintf(devfs_name, "%d", unit);
+	*handle_out = devfs_register(dir_handle, devfs_name,
+				     DEVFS_FL_REMOVABLE, major, minor,
+				     S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
+				     S_IWGRP, &ubd_blops, NULL);
+	disk->private_data = &ubd_dev[unit];
 	disk->queue = &ubd_queue;
 	add_disk(disk);
-	make_ide_entries(disk->disk_name);
 	return(0);
+}
 
- out_unregister:
-	devfs_unregister(real);
-	ubd_dev[n].real = NULL;
- out:
-	return(-1);
+/* Initialized in an initcall, and unchanged thereafter */
+devfs_handle_t ubd_dir_handle;
+devfs_handle_t ubd_fake_dir_handle;
+
+static int ubd_add(int n)
+{
+	struct ubd *dev = &ubd_dev[n];
+	int err;
+
+	if (!dev->file || dev->is_dir)
+		return(-ENODEV);
+
+	if (ubd_open_dev(dev))
+		return(-ENODEV);
+
+	err = ubd_file_size(dev, &dev->size);
+	if(err)
+		return(err);
+
+	err = ubd_new_disk(MAJOR_NR, dev->size, "ubd", n, &ubd_gendisk[n], 
+			   ubd_dir_handle, &dev->real);
+	if(err) 
+		return(err);
+ 
+	if(fake_major)
+		ubd_new_disk(fake_major, dev->size, "ubd%d", n, 
+			     &fake_gendisk[n], ubd_fake_dir_handle, 
+			     &dev->fake);
+
+	/* perhaps this should also be under the "if (fake_major)" above */
+	/* using the fake_disk->disk_name and also the fakehd_set name */
+	if (fake_ide)
+		make_ide_entries(ubd_gendisk[n]->disk_name);
+
+	ubd_close(dev);
+	return 0;
 }
 
 static int ubd_config(char *str)
@@ -527,34 +577,39 @@
 static int ubd_remove(char *str)
 {
 	struct ubd *dev;
-	int n, err;
+	int n, err = -ENODEV;
+
+	if(!isdigit(*str))
+		return(err);	/* it should be a number 0-7/a-h */
 
-	if(!isdigit(*str)) 
-		return(-1);
 	n = *str - '0';
 	if(n > MAX_DEV) 
-		return(-1);
+		return(err);
+
 	dev = &ubd_dev[n];
+	if(dev->count > 0)
+		return(-EBUSY);	/* you cannot remove a open disk */
 
 	err = 0;
  	spin_lock(&ubd_lock);
+
+	if(ubd_gendisk[n] == NULL)
+		goto out;
+
 	del_gendisk(ubd_gendisk[n]);
 	put_disk(ubd_gendisk[n]);
 	ubd_gendisk[n] = NULL;
-	if (fake_major) {
+	if(dev->real != NULL) 
+		devfs_unregister(dev->real);
+
+	if(fake_gendisk[n] != NULL){
 		del_gendisk(fake_gendisk[n]);
 		put_disk(fake_gendisk[n]);
 		fake_gendisk[n] = NULL;
+		if(dev->fake != NULL) 
+			devfs_unregister(dev->fake);
 	}
-	if(dev->file == NULL)
-		goto out;
-	err = -1;
-	if(dev->count > 0)
-		goto out;
-	if(dev->real != NULL) 
-		devfs_unregister(dev->real);
-	if(dev->fake != NULL) 
-		devfs_unregister(dev->fake);
+
 	*dev = ((struct ubd) DEFAULT_UBD);
 	err = 0;
  out:
@@ -563,9 +618,9 @@
 }
 
 static struct mc_device ubd_mc = {
-	name:		"ubd",
-	config:		ubd_config,
-	remove:		ubd_remove,
+	.name		= "ubd",
+	.config		= ubd_config,
+	.remove		= ubd_remove,
 };
 
 static int ubd_mc_init(void)
@@ -585,8 +640,10 @@
 		printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
 		return -1;
 	}
+
 	blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
 	elevator_init(&ubd_queue, &elevator_noop);
+
 	if(fake_major != 0){
 		char name[sizeof("ubd_nnn\0")];
 
@@ -631,81 +688,23 @@
 
 device_initcall(ubd_driver_init);
 
-static void ubd_close(struct ubd *dev)
-{
-	os_close_file(dev->fd);
-	if(dev->cow.file != NULL) {
-		os_close_file(dev->cow.fd);
-		vfree(dev->cow.bitmap);
-		dev->cow.bitmap = NULL;
-	}
-}
-
-static int ubd_open_dev(struct ubd *dev)
-{
-	struct openflags flags;
-	int err, n, create_cow, *create_ptr;
-
-	create_cow = 0;
-	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
-				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
-				&dev->cow.data_offset, create_ptr);
-
-	if((dev->fd == -ENOENT) && create_cow){
-		n = dev - ubd_dev;
-		dev->fd = create_cow_file(dev->file, dev->cow.file, 
-					  dev->openflags, 1 << 9,
-					  &dev->cow.bitmap_offset, 
-					  &dev->cow.bitmap_len,
-					  &dev->cow.data_offset);
-		if(dev->fd >= 0){
-			printk(KERN_INFO "Creating \"%s\" as COW file for "
-			       "\"%s\"\n", dev->file, dev->cow.file);
-		}
-	}
-
-	if(dev->fd < 0) return(dev->fd);
-
-	if(dev->cow.file != NULL){
-		err = -ENOMEM;
-		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-		if(dev->cow.bitmap == NULL) goto error;
-		flush_tlb_kernel_vm();
-
-		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
-				      dev->cow.bitmap_offset, 
-				      dev->cow.bitmap_len);
-		if(err) goto error;
-
-		flags = dev->openflags;
-		flags.w = 0;
-		err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, 
-				    NULL, NULL);
-		if(err < 0) goto error;
-		dev->cow.fd = err;
-	}
-	return(0);
- error:
-	os_close_file(dev->fd);
-	return(err);
-}
-
 static int ubd_open(struct inode *inode, struct file *filp)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	int err;
+	int err = -EISDIR;
+
 	if(dev->is_dir == 1)
 		goto out;
 
+	err = 0;
 	if(dev->count == 0){
 		dev->openflags = dev->boot_openflags;
 
 		err = ubd_open_dev(dev);
 		if(err){
-			printk(KERN_ERR "%s: Can't open \"%s\": "
-			       "errno = %d\n", disk->disk_name, dev->file, -err);
+			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
+			       disk->disk_name, dev->file, -err);
 			goto out;
 		}
 	}
@@ -722,7 +721,8 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	if(dev->count == 0)
+
+	if(--dev->count == 0)
 		ubd_close(dev);
 	return(0);
 }
@@ -772,7 +772,7 @@
 	__u64 block;
 	int nsect;
 
-	if (req->rq_status == RQ_INACTIVE) return(1);
+	if(req->rq_status == RQ_INACTIVE) return(1);
 
 	if(dev->is_dir){
 		strcpy(req->buffer, "HOSTFS:");
@@ -784,7 +784,8 @@
 	}
 
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
-		printk("Write attempted on readonly ubd device %s\n", disk->disk_name);
+		printk("Write attempted on readonly ubd device %s\n", 
+		       disk->disk_name);
  		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
  		spin_unlock(&ubd_io_lock);
@@ -848,7 +849,6 @@
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
 	struct ubd *dev = inode->i_bdev->bd_disk->private_data;
 	int err;
- 	struct ubd *dev;
 	struct hd_driveid ubd_id = {
 		.cyls =		0,
 		.heads =	128,
@@ -868,7 +868,7 @@
 
 	case HDIO_SET_UNMASKINTR:
 		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if((arg > 1) || inode->i_bdev->bd_contains != inode->i_bdev)
+		if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev))
 			return(-EINVAL);
 		return(0);
 
@@ -888,7 +888,7 @@
 
 	case HDIO_SET_MULTCOUNT:
 		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if (inode->i_bdev->bd_contains != inode->i_bdev)
+		if(inode->i_bdev->bd_contains != inode->i_bdev)
 			return(-EINVAL);
 		return(0);
 
@@ -911,27 +911,6 @@
 		return(0);
 	}
 	return(-EINVAL);
-}
-
-static int ubd_revalidate(struct gendisk *disk)
-{
-	__u64 size;
-	int err;
-	struct ubd *dev = disk->private_data;
-
-	err = 0;
-	spin_lock(&ubd_lock);
-	if(dev->is_dir) 
-		goto out;
-	
-	err = ubd_file_size(dev, &size);
-	if (!err) {
-		set_capacity(disk, size / 512);
-		dev->size = size;
-	}
- out:
-	spin_unlock(&ubd_lock);
-	return err;
 }
 
 /*
diff -Nru a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
--- a/arch/um/drivers/xterm.c	Sun Nov 17 20:30:02 2002
+++ b/arch/um/drivers/xterm.c	Sun Nov 17 20:30:02 2002
@@ -19,6 +19,7 @@
 #include "user_util.h"
 #include "user.h"
 #include "os.h"
+#include "xterm.h"
 
 struct xterm_chan {
 	int pid;
@@ -28,6 +29,7 @@
 	int raw;
 	struct termios tt;
 	unsigned long stack;
+	int direct_rcv;
 };
 
 void *xterm_init(char *str, int device, struct chan_opts *opts)
@@ -40,7 +42,8 @@
 				       device :		device, 
 				       title :		opts->xterm_title,
 				       raw : 		opts->raw,
-				       stack :		opts->tramp_stack } );
+				       stack :		opts->tramp_stack,
+				       direct_rcv :	!opts->in_kernel } );
 	return(data);
 }
 
@@ -84,7 +87,7 @@
 {
 	struct xterm_chan *data = d;
 	unsigned long stack;
-	int pid, fd, new;
+	int pid, fd, new, err;
 	char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
 	char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 
 			 "/usr/lib/uml/port-helper", "-uml-socket",
@@ -105,21 +108,30 @@
 	fd = create_unix_socket(file, sizeof(file));
 	if(fd < 0){
 		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
-		       errno);
-		return(-errno);
+		       -fd);
+		return(-fd);
 	}
 
 	sprintf(title, data->title, data->device);
 	stack = data->stack;
 	pid = run_helper(NULL, NULL, argv, &stack);
 	if(pid < 0){
-		printk("xterm_open : run_helper failed\n");
-		return(-1);
+		printk("xterm_open : run_helper failed, errno = %d\n", -pid);
+		return(pid);
 	}
 
 	if(data->stack == 0) free_stack(stack, 0);
 
-	new = os_rcv_fd(fd, &data->helper_pid);
+	if(data->direct_rcv)
+		new = os_rcv_fd(fd, &data->helper_pid);
+	else {
+		if((err = os_set_fd_block(fd, 0)) != 0){
+			printk("xterm_open : failed to set descriptor "
+			       "non-blocking, errno = %d\n", err);
+			return(err);
+		}
+		new = xterm_fd(fd, &data->helper_pid);
+	}
 	if(new < 0){
 		printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
 		return(new);
diff -Nru a/arch/um/drivers/xterm.h b/arch/um/drivers/xterm.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/um/drivers/xterm.h	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,22 @@
+/* 
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __XTERM_H__
+#define __XTERM_H__
+
+extern int xterm_fd(int socket, int *pid_out);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/um/drivers/xterm_kern.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,77 @@
+/* 
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/errno.h"
+#include "linux/slab.h"
+#include "asm/semaphore.h"
+#include "asm/irq.h"
+#include "irq_user.h"
+#include "kern_util.h"
+#include "os.h"
+#include "xterm.h"
+
+struct xterm_wait {
+	struct semaphore sem;
+	int fd;
+	int pid;
+	int new_fd;
+};
+
+static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+	struct xterm_wait *xterm = data;
+
+	xterm->new_fd = os_rcv_fd(xterm->fd, &xterm->pid);
+	if(xterm->new_fd == -EAGAIN)
+		return;
+
+	up(&xterm->sem);
+}
+
+int xterm_fd(int socket, int *pid_out)
+{
+	struct xterm_wait *data;
+	int err, ret;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if(data == NULL){
+		printk(KERN_ERR "xterm_fd - failed to allocate semaphore\n");
+		return(-ENOMEM);
+	}
+	*data = ((struct xterm_wait) 
+		{ sem : 	__SEMAPHORE_INITIALIZER(data->sem, 0),
+		  fd :		socket,
+		  pid :		-1,
+		  new_fd :	-1 });
+
+	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, 
+			     SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
+			     "xterm", data);
+	if(err){
+		printk(KERN_ERR "Failed to get IRQ for xterm, err = %d\n", 
+		       err);
+		return(err);
+	}
+	down(&data->sem);
+
+	free_irq(XTERM_IRQ, data);
+
+	ret = data->new_fd;
+	*pid_out = data->pid;
+	kfree(data);
+
+	return(ret);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
--- a/arch/um/include/chan_user.h	Sun Nov 17 20:30:14 2002
+++ b/arch/um/include/chan_user.h	Sun Nov 17 20:30:14 2002
@@ -13,6 +13,7 @@
 	char *xterm_title;
 	int raw;
 	unsigned long tramp_stack;
+	int in_kernel;
 };
 
 enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
diff -Nru a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
--- a/arch/um/include/kern_util.h	Sun Nov 17 20:30:12 2002
+++ b/arch/um/include/kern_util.h	Sun Nov 17 20:30:12 2002
@@ -6,6 +6,7 @@
 #ifndef __KERN_UTIL_H__
 #define __KERN_UTIL_H__
 
+#include "linux/threads.h"
 #include "sysdep/ptrace.h"
 
 extern int ncpus;
@@ -14,6 +15,7 @@
 extern int kmalloc_ok;
 extern int timer_irq_inited;
 extern int jail;
+extern struct task_struct *idle_threads[NR_CPUS];
 
 #define ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
 #define ROUND_UP(addr) ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
diff -Nru a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
--- a/arch/um/kernel/Makefile	Sun Nov 17 20:30:14 2002
+++ b/arch/um/kernel/Makefile	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,3 @@
-
 EXTRA_TARGETS	:= unmap_fin.o
 
 obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \
@@ -50,6 +49,9 @@
 
 arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o
 	ld -r -o $@ $< -lc -L/usr/lib
+
+# This has to be separate because it needs be compiled with frame pointers
+# regardless of how the rest of the kernel is built.
 
 arch/um/kernel/frame.o: arch/um/kernel/frame.c
 	$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
diff -Nru a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
--- a/arch/um/kernel/irq_user.c	Sun Nov 17 20:30:13 2002
+++ b/arch/um/kernel/irq_user.c	Sun Nov 17 20:30:13 2002
@@ -209,7 +209,6 @@
 
  out_unlock:
 	irq_unlock(flags);
- out_free:
 	kfree(new_fd);
  out:
 	return(err);
diff -Nru a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
--- a/arch/um/kernel/ksyms.c	Sun Nov 17 20:30:02 2002
+++ b/arch/um/kernel/ksyms.c	Sun Nov 17 20:30:02 2002
@@ -1,5 +1,9 @@
+#include "linux/config.h"
 #include "linux/module.h"
 #include "linux/string.h"
+#include "linux/smp_lock.h"
+#include "linux/spinlock.h"
+#include <linux/highmem.h>
 #include "asm/current.h"
 #include "asm/delay.h"
 #include "asm/processor.h"
@@ -36,12 +40,15 @@
 EXPORT_SYMBOL(get_signals);
 EXPORT_SYMBOL(page_to_phys);
 EXPORT_SYMBOL(phys_to_page);
+EXPORT_SYMBOL(high_physmem);
 
 EXPORT_SYMBOL(os_open_file);
 EXPORT_SYMBOL(os_read_file);
 EXPORT_SYMBOL(os_write_file);
 EXPORT_SYMBOL(os_seek_file);
 EXPORT_SYMBOL(os_pipe);
+EXPORT_SYMBOL(os_file_type);
+EXPORT_SYMBOL(os_close_file);
 EXPORT_SYMBOL(helper_wait);
 EXPORT_SYMBOL(os_shutdown_socket);
 EXPORT_SYMBOL(os_connect_socket);
@@ -57,4 +64,24 @@
 EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_wait4);
+
+#ifdef CONFIG_SMP
+
+/* required for SMP */
+
+extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
+EXPORT_SYMBOL_NOVERS(__write_lock_failed);
+
+extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
+EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+
+#endif
+
+#ifdef CONFIG_HIGHMEM
+EXPORT_SYMBOL(kmap);
+EXPORT_SYMBOL(kunmap);
+EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_to_page);
+#endif
 
diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
--- a/arch/um/kernel/process_kern.c	Sun Nov 17 20:30:14 2002
+++ b/arch/um/kernel/process_kern.c	Sun Nov 17 20:30:14 2002
@@ -767,8 +767,8 @@
 
 int smp_sigio_handler(void)
 {
-	int cpu = current->thread_info->cpu;
 #ifdef CONFIG_SMP
+	int cpu = current->thread_info->cpu;
 	IPI_handler(cpu);
 	if(cpu != 0)
 		return(1);
diff -Nru a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
--- a/arch/um/kernel/reboot.c	Sun Nov 17 20:30:14 2002
+++ b/arch/um/kernel/reboot.c	Sun Nov 17 20:30:14 2002
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
@@ -9,6 +9,20 @@
 #include "kern.h"
 #include "os.h"
 
+#ifdef CONFIG_SMP
+static void kill_idlers(int me)
+{
+	struct task_struct *p;
+	int i;
+
+	for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
+		p = idle_threads[i];
+		if((p != NULL) && (p->thread.extern_pid != me))
+			os_kill_process(p->thread.extern_pid);
+	}
+}
+#endif
+
 static void kill_off_processes(void)
 {
 	struct task_struct *p;
@@ -21,6 +35,9 @@
 	}
 	if(init_task.thread.extern_pid != me) 
 		os_kill_process(init_task.thread.extern_pid);
+#ifdef CONFIG_SMP
+	kill_idlers(me);
+#endif
 }
 
 void uml_cleanup(void)
diff -Nru a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
--- a/arch/um/kernel/signal_user.c	Sun Nov 17 20:30:15 2002
+++ b/arch/um/kernel/signal_user.c	Sun Nov 17 20:30:15 2002
@@ -84,13 +84,13 @@
 #define SIGIO_BIT 0
 #define SIGVTALRM_BIT 1
 
-static int disable_mask(sigset_t *mask)
+static int enable_mask(sigset_t *mask)
 {
 	int sigs;
 
-	sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0;
-	sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0;
-	sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0;
+	sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
+	sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
+	sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
 	return(sigs);
 }
 
@@ -100,30 +100,28 @@
 	
 	if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
 		panic("Failed to get signal mask");
-	return(disable_mask(&mask));
+	return(enable_mask(&mask));
 }
 
-int set_signals(int disable)
+int set_signals(int enable)
 {
 	sigset_t mask;
 	int ret;
 
 	sigemptyset(&mask);
-	if(!(disable & (1 << SIGIO_BIT)))
+	if(enable & (1 << SIGIO_BIT)) 
 		sigaddset(&mask, SIGIO);
-	if(!(disable & (1 << SIGVTALRM_BIT))){
+	if(enable & (1 << SIGVTALRM_BIT)){
 		sigaddset(&mask, SIGVTALRM);
 		sigaddset(&mask, SIGALRM);
 	}
 	if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
 		panic("Failed to enable signals");
-
-	ret = disable_mask(&mask);
-
+	ret = enable_mask(&mask);
 	sigemptyset(&mask);
-	if(disable & (1 << SIGIO_BIT))
+	if((enable & (1 << SIGIO_BIT)) == 0) 
 		sigaddset(&mask, SIGIO);
-	if(disable & (1 << SIGVTALRM_BIT)){
+	if((enable & (1 << SIGVTALRM_BIT)) == 0){
 		sigaddset(&mask, SIGVTALRM);
 		sigaddset(&mask, SIGALRM);
 	}
diff -Nru a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
--- a/arch/um/kernel/smp.c	Sun Nov 17 20:30:12 2002
+++ b/arch/um/kernel/smp.c	Sun Nov 17 20:30:12 2002
@@ -47,6 +47,9 @@
 /* Small, random number, never changed */
 unsigned long cache_decay_ticks = 5;
 
+/* Not changed after boot */
+struct task_struct *idle_threads[NR_CPUS];
+
 void smp_send_reschedule(int cpu)
 {
 	write(cpu_data[cpu].ipi_pipe[1], "R", 1);
@@ -142,6 +145,7 @@
 	cpu_tasks[cpu] = ((struct cpu_task) 
 		          { .pid = 	new_task->thread.extern_pid,
 			    .task = 	new_task } );
+	idle_threads[cpu] = new_task;
 	write(new_task->thread.switch_pipe[1], &c, sizeof(c));
 	return(new_task);
 }
diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
--- a/arch/um/kernel/sys_call_table.c	Sun Nov 17 20:30:15 2002
+++ b/arch/um/kernel/sys_call_table.c	Sun Nov 17 20:30:15 2002
@@ -85,6 +85,7 @@
 extern syscall_handler_t sys_symlink;
 extern syscall_handler_t sys_lstat;
 extern syscall_handler_t sys_readlink;
+extern syscall_handler_t sys_swapon;
 extern syscall_handler_t sys_uselib;
 extern syscall_handler_t sys_reboot;
 extern syscall_handler_t old_readdir;
@@ -111,6 +112,7 @@
 extern syscall_handler_t sys_vhangup;
 extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_ni_syscall;
+extern syscall_handler_t sys_swapoff;
 extern syscall_handler_t sys_sysinfo;
 extern syscall_handler_t sys_ipc;
 extern syscall_handler_t sys_fsync;
@@ -229,6 +231,11 @@
 extern syscall_handler_t sys_io_submit;
 extern syscall_handler_t sys_io_cancel;
 extern syscall_handler_t sys_exit_group;
+extern syscall_handler_t sys_lookup_dcookie;
+extern syscall_handler_t sys_epoll_create;
+extern syscall_handler_t sys_epoll_ctl;
+extern syscall_handler_t sys_epoll_wait;
+extern syscall_handler_t sys_remap_file_pages;
 
 #if CONFIG_NFSD
 #define NFSSERVCTL sys_nfsserctl
@@ -240,7 +247,7 @@
 extern syscall_handler_t um_time;
 extern syscall_handler_t um_stime;
 
-#define LAST_GENERIC_SYSCALL __NR_exit_group
+#define LAST_GENERIC_SYSCALL __NR_remap_file_pages
 
 #if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
 #define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -479,6 +486,11 @@
 	[ __NR_alloc_hugepages ] = sys_ni_syscall,
 	[ __NR_free_hugepages ] = sys_ni_syscall,
 	[ __NR_exit_group ] = sys_exit_group,
+	[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
+	[ __NR_sys_epoll_create ] = sys_epoll_create,
+	[ __NR_sys_epoll_ctl ] = sys_epoll_ctl,
+	[ __NR_sys_epoll_wait ] = sys_epoll_wait,
+        [ __NR_remap_file_pages ] = sys_remap_file_pages,
 
 	ARCH_SYSCALLS
 	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
diff -Nru a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
--- a/arch/um/kernel/sysrq.c	Sun Nov 17 20:30:12 2002
+++ b/arch/um/kernel/sysrq.c	Sun Nov 17 20:30:12 2002
@@ -76,6 +76,16 @@
         printk("\n");
 }
 
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_trace(&stack);
+}
+
 void show_trace_task(struct task_struct *tsk)
 {
 	unsigned long esp = PT_REGS_SP(&tsk->thread.regs);
diff -Nru a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
--- a/arch/um/kernel/trap_kern.c	Sun Nov 17 20:30:02 2002
+++ b/arch/um/kernel/trap_kern.c	Sun Nov 17 20:30:02 2002
@@ -211,6 +211,7 @@
 	xterm_title :	"UML kernel debugger",
 	raw :		0,
 	tramp_stack :	0,
+	in_kernel : 	0,
 };
 
 /* Accessed by the tracing thread, which automatically serializes access */
diff -Nru a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
--- a/arch/um/os-Linux/Makefile	Sun Nov 17 20:30:14 2002
+++ b/arch/um/os-Linux/Makefile	Sun Nov 17 20:30:14 2002
@@ -5,9 +5,11 @@
 
 obj-y = file.o process.o tty.o
 
+USER_OBJS := $(foreach file,$(obj-y),arch/um/os-Linux/$(file))
+
 include $(TOPDIR)/Rules.make
 
-$(obj-y) : %.o: %.c
+$(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
 
 clean :
diff -Nru a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
--- a/arch/um/os-Linux/file.c	Sun Nov 17 20:30:16 2002
+++ b/arch/um/os-Linux/file.c	Sun Nov 17 20:30:16 2002
@@ -283,10 +283,9 @@
 	msg.msg_flags = 0;
 
 	n = recvmsg(fd, &msg, 0);
-	if(n < 0){
-		printk("rcv_fd : recvmsg failed - errno = %d\n", errno);
-		return(-1);
-	}
+	if(n < 0)
+		return(-errno);
+
 	else if(n != sizeof(iov.iov_len))
 		*helper_pid_out = -1;
 
diff -Nru a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
--- a/arch/um/sys-i386/Makefile	Sun Nov 17 20:30:04 2002
+++ b/arch/um/sys-i386/Makefile	Sun Nov 17 20:30:04 2002
@@ -1,19 +1,21 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o old-checksum.o \
+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o \
 	ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
 
+obj-$(CONFIG_HIGHMEM) += highmem.o
+
 export-objs = ksyms.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/sys-i386/$(file))
 
-SYMLINKS = semaphore.c old-checksum.c checksum.S extable.c
+SYMLINKS = semaphore.c checksum.S extable.c highmem.c
 
 include $(TOPDIR)/Rules.make
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
 
-arch/um/sys-i386/checksum.S arch/um/sys-i386/old-checksum.c: 
+arch/um/sys-i386/checksum.S: 
 	-rm -f $@
 	-ln -s $(TOPDIR)/arch/i386/lib/$(notdir $@) $@
 
@@ -25,6 +27,9 @@
 	-rm -f $@
 	-ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
 
+arch/um/sys-i386/highmem.c:
+	-rm -f $@
+	-ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
 clean:
 	$(MAKE) -C util clean
 
diff -Nru a/arch/um/uml.lds.S b/arch/um/uml.lds.S
--- a/arch/um/uml.lds.S	Sun Nov 17 20:30:14 2002
+++ b/arch/um/uml.lds.S	Sun Nov 17 20:30:14 2002
@@ -65,7 +65,7 @@
   .uml.postsetup.init : { *(.uml.postsetup.init) }
   __uml_postsetup_end = .;
   __setup_start = .;
-  .setup.init : { *(.setup.init) }
+  .init.setup : { *(.init.setup) }
   __setup_end = .;
   __per_cpu_start = . ; 
   .data.percpu : { *(.data.percpu) }
@@ -92,6 +92,11 @@
   .uml.exitcall : { *(.uml.exitcall.exit) }
   __uml_exitcall_end = .;
 
+   . = ALIGN(4096);
+   __initramfs_start = .;
+   .init.ramfs : { *(.init.ramfs) }
+   __initramfs_end = .;
+ 
   .data.init : { *(.data.init) }
   .data    :
   {
diff -Nru a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c
--- a/arch/v850/kernel/memcons.c	Sun Nov 17 20:30:15 2002
+++ b/arch/v850/kernel/memcons.c	Sun Nov 17 20:30:15 2002
@@ -65,11 +65,11 @@
 
 static struct console memcons =
 {
-    name:	"memcons",
-    write:	memcons_write,
-    device:	memcons_device,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
+    .name	= "memcons",
+    .write	= memcons_write,
+    .device	= memcons_device,
+    .flags	= CON_PRINTBUFFER,
+    .index	= -1,
 };
 
 void memcons_setup (void)
diff -Nru a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
--- a/arch/v850/kernel/procfs.c	Sun Nov 17 20:30:14 2002
+++ b/arch/v850/kernel/procfs.c	Sun Nov 17 20:30:14 2002
@@ -60,8 +60,8 @@
 }
 
 struct seq_operations cpuinfo_op = {
-	start:	cpuinfo_start,
-	next:	cpuinfo_next,
-	stop:	cpuinfo_stop,
-	show:	cpuinfo_print
+	.start	= cpuinfo_start,
+	.next	= cpuinfo_next,
+	.stop	= cpuinfo_stop,
+	.show	= cpuinfo_print
 };
diff -Nru a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
--- a/arch/v850/kernel/rte_cb_leds.c	Sun Nov 17 20:30:03 2002
+++ b/arch/v850/kernel/rte_cb_leds.c	Sun Nov 17 20:30:03 2002
@@ -116,15 +116,15 @@
 }
 
 static struct file_operations leds_fops = {
-	read:		leds_dev_read,
-	write:		leds_dev_write,
-	llseek:		leds_dev_lseek
+	.read		= leds_dev_read,
+	.write		= leds_dev_write,
+	.llseek		= leds_dev_lseek
 };
 
 static struct miscdevice leds_miscdev = {
-	name:		"leds",
-	minor:		LEDS_MINOR,
-	fops:		&leds_fops
+	.name		= "leds",
+	.minor		= LEDS_MINOR,
+	.fops		= &leds_fops
 };
 
 int __init leds_dev_init (void)
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/arch/x86_64/Kconfig	Sun Nov 17 20:30:15 2002
@@ -505,7 +505,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called scsi_mod.o.  If you want to compile it as
 	  a module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  However, do not compile this as a
+	  <file:Documentation/scsi/scsi.txt>.  However, do not compile this as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI device.
 
@@ -739,13 +739,13 @@
 	help
 	  Fill __init and __initdata at the end of boot. This is only for debugging.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
+#  config KALLSYMS
+#  	bool "Load all symbols for debugging/kksymoops"
+#  	depends on DEBUG_KERNEL
+#  	help
+#  	  Say Y here to let the kernel print out symbolic crash information and
+#  	  symbolic stack backtraces. This increases the size of the kernel
+#  	  somewhat, as all symbols have to be loaded into the kernel image.
 
 endmenu
 
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	Sun Nov 17 20:30:13 2002
+++ b/arch/x86_64/ia32/sys_ia32.c	Sun Nov 17 20:30:13 2002
@@ -1144,7 +1144,7 @@
 
 	/* SMP: This is fairly trivial. We grab CURRENT_TIME and 
 	   stuff it to user space. No side effects */
-	i = CURRENT_TIME;
+	i = get_seconds();
 	if (tloc) {
 		if (put_user(i,tloc))
 			i = -EFAULT;
diff -Nru a/crypto/api.c b/crypto/api.c
--- a/crypto/api.c	Sun Nov 17 20:30:15 2002
+++ b/crypto/api.c	Sun Nov 17 20:30:15 2002
@@ -263,8 +263,7 @@
 	struct crypto_alg *alg = (struct crypto_alg *)p;
 	
 	seq_printf(m, "name         : %s\n", alg->cra_name);
-	seq_printf(m, "module       : %s\n", alg->cra_module ?
-					alg->cra_module->name : "[static]");
+	seq_printf(m, "module       : %s\n", module_name(alg->cra_module));
 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 	
 	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/acorn/block/fd1772.c	Sun Nov 17 20:30:12 2002
@@ -1299,14 +1299,15 @@
 }
 
 
-static int invalidate_drive(int rdev)
+static int invalidate_drive(struct block_device *bdev)
 {
+	struct archy_floppy_struct *p = bdev->bd_disk->private_data;
 	/* invalidate the buffer track to force a reread */
 #ifdef TRACKBUFFER
 	BufferDrive = -1;
 #endif
 
-	set_bit(rdev & 3, &fake_change);
+	set_bit(p - unit, &fake_change);
 	return 0;
 }
 
@@ -1314,12 +1315,11 @@
 		    unsigned int cmd, unsigned long param)
 {
 	struct block_device *bdev = inode->i_bdev;
-	int drive = MINOR(bdev->bd_dev);
 
 	switch (cmd) {
 	case FDFMTEND:
 	case FDFLUSH:
-		invalidate_drive(drive);
+		invalidate_drive(bdev);
 		check_disk_change(bdev);
 	case FDFMTBEG:
 		return 0;
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/acorn/block/mfmhd.c	Sun Nov 17 20:30:04 2002
@@ -161,13 +161,6 @@
 /*#define DEBUG */
 #endif
 /*
- * List of card types that we recognise
- */
-static const card_ids mfm_cids[] = {
-	{ MANU_ACORN, PROD_ACORN_MFM },
-	{ 0xffff, 0xffff }
-};
-/*
  * End of configuration
  */
 
@@ -1230,8 +1223,6 @@
 	.ioctl		= mfm_ioctl,
 };
 
-static struct expansion_card *ecs;
-
 /*
  * See if there is a controller at the address presently at mfm_addr
  *
@@ -1266,44 +1257,18 @@
 	return 1;
 }
 
-/*
- * Look for a MFM controller - first check the motherboard, then the podules
- * The podules have an extra interrupt enable that needs to be played with
- *
- * The HDC is accessed at MEDIUM IOC speeds.
- */
-static int __init mfm_init (void)
+static int mfm_do_init(unsigned char irqmask)
 {
-	unsigned char irqmask;
-	int i;
-
-	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
-		mfm_addr	= ONBOARD_MFM_ADDRESS;
-		mfm_IRQPollLoc	= IOC_IRQSTATB;
-		mfm_irqenable	= 0;
-		mfm_irq		= IRQ_HARDDISK;
-		irqmask		= 0x08;			/* IL3 pin */
-	} else {
-		ecs = ecard_find(0, mfm_cids);
-		if (!ecs) {
-			mfm_addr = 0;
-			return -1;
-		}
-
-		mfm_addr	= ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800;
-		mfm_IRQPollLoc	= ioaddr(mfm_addr + 0x400);
-		mfm_irqenable	= mfm_IRQPollLoc;
-		mfm_irq		= ecs->irq;
-		irqmask		= 0x08;
-
-		ecard_claim(ecs);
-	}
+	int i, ret;
 
 	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
+
+	ret = -EBUSY;
 	if (!request_region (mfm_addr, 10, "mfm"))
 		goto out1;
 
-	if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
+	ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops);
+	if (ret) {
 		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
 		goto out2;
 	}
@@ -1319,8 +1284,10 @@
 	lastspecifieddrive = -1;
 
 	mfm_drives = mfm_initdrives();
-	if (!mfm_drives)
+	if (!mfm_drives) {
+		ret = -ENODEV;
 		goto out3;
+	}
 	
 	for (i = 0; i < mfm_drives; i++) {
 		struct gendisk *disk = alloc_disk(64);
@@ -1335,7 +1302,8 @@
 
 	printk("mfm: detected %d hard drive%s\n", mfm_drives,
 				mfm_drives == 1 ? "" : "s");
-	if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL)) {
+	ret = request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL);
+	if (ret) {
 		printk("mfm: unable to get IRQ%d\n", mfm_irq);
 		goto out4;
 	}
@@ -1359,19 +1327,17 @@
 out2:
 	release_region(mfm_addr, 10);
 out1:
-	ecard_release(ecs);
-	return -1;
+	return ret;
 Enomem:
 	while (i--)
 		put_disk(mfm_gendisk[i]);
 	goto out3;
 }
 
-static void __exit mfm_exit(void)
+static void mfm_do_exit(void)
 {
 	int i;
-	if (ecs && mfm_irqenable)
-		outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
+
 	free_irq(mfm_irq, NULL);
 	for (i = 0; i < mfm_drives; i++) {
 		del_gendisk(mfm_gendisk[i]);
@@ -1379,10 +1345,70 @@
 	}
 	blk_cleanup_queue(&mfm_queue);
 	unregister_blkdev(MAJOR_NR, "mfm");
-	if (ecs)
-		ecard_release(ecs);
 	if (mfm_addr)
 		release_region(mfm_addr, 10);
+}
+
+static int __devinit mfm_probe(struct expansion_card *ec, struct ecard_id *id)
+{
+	if (mfm_addr)
+		return -EBUSY;
+
+	mfm_addr	= ecard_address(ec, ECARD_IOC, ECARD_MEDIUM) + 0x800;
+	mfm_IRQPollLoc	= ioaddr(mfm_addr + 0x400);
+	mfm_irqenable	= mfm_IRQPollLoc;
+	mfm_irq		= ec->irq;
+
+	return mfm_do_init(0x08);
+}
+
+static void __devexit mfm_remove(struct expansion_card *ec)
+{
+	outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
+	mfm_do_exit();
+}
+
+static const struct ecard_id mfm_cids[] = {
+	{ MANU_ACORN, PROD_ACORN_MFM },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver mfm_driver = {
+	.probe		= mfm_probe,
+	.remove		= __devexit(mfm_remove),
+	.id_table	= mfm_cids,
+	.drv = {
+		.name	= "mfm",
+	},
+};
+
+/*
+ * Look for a MFM controller - first check the motherboard, then the podules
+ * The podules have an extra interrupt enable that needs to be played with
+ *
+ * The HDC is accessed at MEDIUM IOC speeds.
+ */
+static int __init mfm_init (void)
+{
+	unsigned char irqmask;
+
+	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
+		mfm_addr	= ONBOARD_MFM_ADDRESS;
+		mfm_IRQPollLoc	= IOC_IRQSTATB;
+		mfm_irqenable	= 0;
+		mfm_irq		= IRQ_HARDDISK;
+		return mfm_do_init(0x08);	/* IL3 pin */
+	} else {
+		return ecard_register_driver(&mfm_driver);
+	}
+}
+
+static void __exit mfm_exit(void)
+{
+	if (mfm_addr == ONBOARD_MFM_ADDRESS)
+		mfm_do_exit();
+	else
+		ecard_unregister_driver(&mfm_driver);
 }
 
 module_init(mfm_init)
diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
--- a/drivers/acorn/net/ether1.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acorn/net/ether1.c	Sun Nov 17 20:30:14 2002
@@ -1021,8 +1021,6 @@
 
 	ether1_banner();
 
-	ecard_claim(ec);
-
 	dev = init_etherdev(NULL, sizeof(struct ether1_priv));
 	if (!dev) {
 		ret = -ENOMEM;
@@ -1077,7 +1075,6 @@
 	unregister_netdev(dev);
 	kfree(dev);
 out:
-	ecard_release(ec);
 	return ret;
 }
 
@@ -1092,8 +1089,6 @@
 	release_region(dev->base_addr, 16);
 	release_region(dev->base_addr + 0x800, 4096);
 	kfree(dev);
-
-	ecard_release(ec);
 }
 
 static const struct ecard_id ether1_ids[] = {
diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c
--- a/drivers/acorn/net/ether3.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acorn/net/ether3.c	Sun Nov 17 20:30:15 2002
@@ -830,8 +830,6 @@
 
 	ether3_banner();
 
-	ecard_claim(ec);
-
 	dev = init_etherdev(NULL, sizeof(struct dev_priv));
 	if (!dev) {
 		ret = -ENOMEM;
@@ -855,6 +853,7 @@
 	}
 
 	priv = (struct dev_priv *) dev->priv;
+	init_timer(&priv->timer);
 
 	/* Reset card...
 	 */
@@ -917,7 +916,6 @@
 	unregister_netdev(dev);
 	kfree(dev);
 out:
-	ecard_release(ec);
 	return ret;
 }
 
@@ -930,8 +928,6 @@
 	unregister_netdev(dev);
 	release_region(dev->base_addr, 128);
 	kfree(dev);
-
-	ecard_release(ec);
 }
 
 static const struct ecard_id ether3_ids[] = {
diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c
--- a/drivers/acorn/net/etherh.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acorn/net/etherh.c	Sun Nov 17 20:30:15 2002
@@ -568,8 +568,6 @@
 
 	etherh_banner();
 
-	ecard_claim(ec);
-	
 	dev = init_etherdev(NULL, sizeof(struct etherh_priv));
 	if (!dev) {
 		ret = -ENOMEM;
@@ -725,7 +723,6 @@
 	kfree(dev->priv);
 	kfree(dev);
 out:
-	ecard_release(ec);
 	return ret;
 }
 
@@ -744,7 +741,6 @@
 
 	ec->ops = NULL;
 	kfree(ec->irq_data);
-	ecard_release(ec);
 }
 
 static const struct ecard_id etherh_ids[] = {
diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
--- a/drivers/acorn/scsi/acornscsi.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acorn/scsi/acornscsi.c	Sun Nov 17 20:30:14 2002
@@ -109,10 +109,7 @@
  * If not set, then use PIO mode (not currently supported).
  */
 #define USE_DMAC
-/*
- * List of devices that the driver will recognise
- */
-#define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI }
+
 /*
  * ====================================================================================
  */
@@ -2832,148 +2829,6 @@
 /*==============================================================================================
  * initialisation & miscellaneous support
  */
-static struct expansion_card *ecs[MAX_ECARDS];
-
-/*
- * Prototype: void acornscsi_init(AS_Host *host)
- * Purpose  : initialise the AS_Host structure for one interface & setup hardware
- * Params   : host - host to setup
- */
-static
-void acornscsi_host_init(AS_Host *host)
-{
-    memset(&host->stats, 0, sizeof (host->stats));
-    queue_initialise(&host->queues.issue);
-    queue_initialise(&host->queues.disconnected);
-    msgqueue_initialise(&host->scsi.msgs);
-
-    acornscsi_resetcard(host);
-}
-
-int acornscsi_detect(Scsi_Host_Template * tpnt)
-{
-    static const card_ids acornscsi_cids[] = { ACORNSCSI_LIST, { 0xffff, 0xffff } };
-    int i, count = 0;
-    struct Scsi_Host *instance;
-    AS_Host *host;
-
-    tpnt->proc_name = "acornscsi";
-
-    for (i = 0; i < MAX_ECARDS; i++)
-	ecs[i] = NULL;
-
-    ecard_startfind();
-
-    while(1) {
-	ecs[count] = ecard_find(0, acornscsi_cids);
-	if (!ecs[count])
-	    break;
-
-	if (ecs[count]->irq == 0xff) {
-	    printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
-	    continue;
-	}
-
-	ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */
-
-	instance = scsi_register(tpnt, sizeof(AS_Host));
-	if (!instance) {
-		ecard_release(ecs[count]);
-		break;
-	}
-
-	host = (AS_Host *)instance->hostdata;
-
-	instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
-	instance->irq = ecs[count]->irq;
-
-	host->host		= instance;
-	host->scsi.io_port	= ioaddr(instance->io_port + 0x800);
-	host->scsi.irq		= instance->irq;
-	host->card.io_intr	= POD_SPACE(instance->io_port) + 0x800;
-	host->card.io_page	= POD_SPACE(instance->io_port) + 0xc00;
-	host->card.io_ram	= ioaddr(instance->io_port);
-	host->dma.io_port	= instance->io_port + 0xc00;
-	host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
-
-	ecs[count]->irqaddr	= (char *)ioaddr(host->card.io_intr);
-	ecs[count]->irqmask	= 0x0a;
-
-	if (!request_region(instance->io_port + 0x800,  2, "acornscsi(sbic)"))
-		goto err_1;
-	if (!request_region(host->card.io_intr,  1, "acornscsi(intr)"))
-		goto err_2;
-	if (!request_region(host->card.io_page,  1, "acornscsi(page)"))
-		goto err_3;
-#ifdef USE_DMAC
-	if (!request_region(host->dma.io_port, 256, "acornscsi(dmac)"))
-		goto err_4;
-#endif
-	if (!request_region(instance->io_port, 2048, "acornscsi(ram)"))
-		goto err_5;
-
-	if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) {
-	    printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n",
-		instance->host_no, host->scsi.irq);
-	    host->scsi.irq = NO_IRQ;
-	}
-
-	acornscsi_host_init(host);
-
-	++count;
-    }
-    return count;
-    
-err_5:
-#ifdef USE_DMAC
-    release_region(host->dma.io_port, 256);
-#endif
-err_4:
-    release_region(host->card.io_page, 1);
-err_3:
-    release_region(host->card.io_intr, 1);    
-err_2:
-    release_region(instance->io_port + 0x800, 2);
-err_1:
-    scsi_unregister(instance);
-    return 0;
-}
-
-/*
- * Function: int acornscsi_release(struct Scsi_Host *host)
- * Purpose : release all resources used by this adapter
- * Params  : host - driver structure to release
- * Returns : nothing of any consequence
- */
-int acornscsi_release(struct Scsi_Host *instance)
-{
-    AS_Host *host = (AS_Host *)instance->hostdata;
-    int i;
-
-    /*
-     * Put card into RESET state
-     */
-    outb(0x80, host->card.io_page);
-
-    if (host->scsi.irq != NO_IRQ)
-	free_irq(host->scsi.irq, host);
-
-    release_region(instance->io_port + 0x800, 2);
-    release_region(host->card.io_intr, 1);
-    release_region(host->card.io_page, 1);
-    release_region(host->dma.io_port, 256);
-    release_region(instance->io_port, 2048);
-
-    for (i = 0; i < MAX_ECARDS; i++)
-	if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0))
-	    ecard_release(ecs[i]);
-
-    msgqueue_free(&host->scsi.msgs);
-    queue_free(&host->queues.disconnected);
-    queue_free(&host->queues.issue);
-
-    return 0;
-}
 
 /*
  * Function: char *acornscsi_info(struct Scsi_Host *host)
@@ -3126,10 +2981,9 @@
 	.module			= THIS_MODULE,
 	.proc_info		= acornscsi_proc_info,
 	.name			= "AcornSCSI",
-	.detect			= acornscsi_detect,
-	.release		= acornscsi_release,
 	.info			= acornscsi_info,
 	.queuecommand		= acornscsi_queuecmd,
+#warning fixme
 	.abort			= acornscsi_abort,
 	.reset			= acornscsi_reset,
 	.can_queue		= 16,
@@ -3137,22 +2991,137 @@
 	.sg_tablesize		= SG_ALL,
 	.cmd_per_lun		= 2,
 	.unchecked_isa_dma	= 0,
-	.use_clustering		= DISABLE_CLUSTERING
+	.use_clustering		= DISABLE_CLUSTERING,
+	.proc_name		= "acornscsi",
 };
 
-static int __init acornscsi_init(void)
+static int __devinit
+acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+	struct Scsi_Host *host;
+	AS_Host *ashost;
+	int ret = -ENOMEM;
+
+	host = scsi_register(&acornscsi_template, sizeof(AS_Host));
+	if (!host)
+		goto out;
+
+	ashost = (AS_Host *)host->hostdata;
+
+	host->io_port = ecard_address(ec, ECARD_MEMC, 0);
+	host->irq = ec->irq;
+
+	ashost->host		= host;
+	ashost->scsi.io_port	= ioaddr(host->io_port + 0x800);
+	ashost->scsi.irq	= host->irq;
+	ashost->card.io_intr	= POD_SPACE(host->io_port) + 0x800;
+	ashost->card.io_page	= POD_SPACE(host->io_port) + 0xc00;
+	ashost->card.io_ram	= ioaddr(host->io_port);
+	ashost->dma.io_port	= host->io_port + 0xc00;
+	ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800;
+
+	ec->irqaddr	= (char *)ioaddr(ashost->card.io_intr);
+	ec->irqmask	= 0x0a;
+
+	ret = -EBUSY;
+	if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)"))
+		goto err_1;
+	if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)"))
+		goto err_2;
+	if (!request_region(ashost->card.io_page, 1, "acornscsi(page)"))
+		goto err_3;
+#ifdef USE_DMAC
+	if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)"))
+		goto err_4;
+#endif
+	if (!request_region(host->io_port, 2048, "acornscsi(ram)"))
+		goto err_5;
+
+	ret = request_irq(host->irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", ashost);
+	if (ret) {
+		printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n",
+			host->host_no, ashost->scsi.irq, ret);
+		goto err_6;
+	}
+
+	memset(&ashost->stats, 0, sizeof (ashost->stats));
+	queue_initialise(&ashost->queues.issue);
+	queue_initialise(&ashost->queues.disconnected);
+	msgqueue_initialise(&ashost->scsi.msgs);
+
+	acornscsi_resetcard(ashost);
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
+
+	free_irq(host->irq, ashost);
+ err_6:
+	release_region(host->io_port, 2048);
+ err_5:
+#ifdef USE_DMAC
+	release_region(ashost->dma.io_port, 256);
+#endif
+ err_4:
+	release_region(ashost->card.io_page, 1);
+ err_3:
+	release_region(ashost->card.io_intr, 1);    
+ err_2:
+	release_region(host->io_port + 0x800, 2);
+ err_1:
+	scsi_unregister(host);
+ out:
+	return ret;
+}
+
+static void __devexit acornscsi_remove(struct expansion_card *ec)
 {
-	scsi_register_host(&acornscsi_template);
-	if (acornscsi_template.present)
-		return 0;
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+	AS_Host *ashost = (AS_Host *)host->hostdata;
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+
+	/*
+	 * Put card into RESET state
+	 */
+	outb(0x80, ashost->card.io_page);
 
-	scsi_unregister_host(&acornscsi_template);
-	return -ENODEV;
+	free_irq(host->irq, ashost);
+
+	release_region(host->io_port + 0x800, 2);
+	release_region(ashost->card.io_intr, 1);
+	release_region(ashost->card.io_page, 1);
+	release_region(ashost->dma.io_port, 256);
+	release_region(host->io_port, 2048);
+
+	msgqueue_free(&ashost->scsi.msgs);
+	queue_free(&ashost->queues.disconnected);
+	queue_free(&ashost->queues.issue);
+}
+
+static const struct ecard_id acornscsi_cids[] = {
+	{ MANU_ACORN, PROD_ACORN_SCSI },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver acornscsi_driver = {
+	.probe		= acornscsi_probe,
+	.remove		= __devexit_p(acornscsi_remove),
+	.id_table	= acornscsi_cids,
+	.drv = {
+		.name	= "acornscsi",
+	},
+};
+
+static int __init acornscsi_init(void)
+{
+	return ecard_register_driver(&acornscsi_driver);
 }
 
 static void __exit acornscsi_exit(void)
 {
-	scsi_unregister_host(&acornscsi_template);
+	ecard_remove_driver(&acornscsi_driver);
 }
 
 module_init(acornscsi_init);
@@ -3161,4 +3130,3 @@
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("AcornSCSI driver");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c
--- a/drivers/acorn/scsi/arxescsi.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acorn/scsi/arxescsi.c	Sun Nov 17 20:30:14 2002
@@ -37,21 +37,29 @@
 
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
-#include "arxescsi.h"
 #include "fas216.h"
 
-/* Hmm - this should go somewhere else */
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
+struct arxescsi_info {
+    FAS216_Info info;
 
-/* Configuration */
-#define ARXESCSI_XTALFREQ		24
-#define ARXESCSI_ASYNC_PERIOD		200
-#define ARXESCSI_SYNC_DEPTH		0
+    /* other info... */
+    unsigned int	cstatus;	/* card status register	*/
+    unsigned int	dmaarea;	/* Pseudo DMA area	*/
+};
+
+#define CSTATUS_IRQ	(1 << 0)
+#define CSTATUS_DRQ	(1 << 0)
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE	1
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN	1
+#endif
 
-/*
- * List of devices that the driver will recognise
- */
-#define ARXESCSI_LIST		{ MANU_ARXE, PROD_ARXE_SCSI }
+/* Hmm - this should go somewhere else */
+#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
 
 /*
  * Version
@@ -60,8 +68,6 @@
 #define VER_MINOR	1
 #define VER_PATCH	1
 
-static struct expansion_card *ecs[MAX_ECARDS];
-
 /*
  * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type)
  * Purpose : initialises DMA/PIO
@@ -85,7 +91,7 @@
 
 /* Faster transfer routines, written by SH to speed up the loops */
 
-static __inline__ unsigned char getb(unsigned int address, unsigned int reg)
+static inline unsigned char getb(unsigned int address, unsigned int reg)
 {
 	unsigned char value;
 
@@ -96,7 +102,7 @@
 	return value;
 }
 
-static __inline__ unsigned int getw(unsigned int address, unsigned int reg)
+static inline unsigned int getw(unsigned int address, unsigned int reg)
 {
 	unsigned int value;
 	
@@ -109,7 +115,7 @@
 	return value;
 }
 
-static __inline__ void putw(unsigned int address, unsigned int reg, unsigned long value)
+static inline void putw(unsigned int address, unsigned int reg, unsigned long value)
 {
 	__asm__ __volatile__(
 	"mov	%0, %0, lsl #16\n\t"
@@ -157,7 +163,7 @@
 void arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
 			fasdmadir_t direction, int transfer)
 {
-	ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata;
+	struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
 	unsigned int length, io, error=0;
 	unsigned char *addr;
 
@@ -248,106 +254,6 @@
 }
 
 /*
- * Function: int arxescsi_detect(Scsi_Host_Template * tpnt)
- * Purpose : initialises ARXE SCSI driver
- * Params  : tpnt - template for this SCSI adapter
- * Returns : >0 if host found, 0 otherwise.
- */
-int arxescsi_detect(Scsi_Host_Template *tpnt)
-{
-	static const card_ids arxescsi_cids[] = { ARXESCSI_LIST, { 0xffff, 0xffff} };
-	int count = 0;
-	struct Scsi_Host *host;
-  
-	tpnt->proc_name = "arxescsi";
-	memset(ecs, 0, sizeof (ecs));
-
-	ecard_startfind();
-
-	while (1) {
-	    	ARXEScsi_Info *info;
-
-		ecs[count] = ecard_find(0, arxescsi_cids);
-		if (!ecs[count])
-			break;
-
-		ecard_claim(ecs[count]);
-		
-		host = scsi_register(tpnt, sizeof (ARXEScsi_Info));
-		if (!host) {
-			ecard_release(ecs[count]);
-			break;
-		}
-
-		host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0) + 0x0800;
-		host->irq = NO_IRQ;
-		host->dma_channel = NO_DMA;
-		host->can_queue = 0; /* no command queueing */
-		info = (ARXEScsi_Info *)host->hostdata;
-
-		info->info.scsi.io_port		= host->io_port;
-		info->info.scsi.irq		= host->irq;
-		info->info.scsi.io_shift	= 3;
-		info->info.ifcfg.clockrate	= ARXESCSI_XTALFREQ;
-		info->info.ifcfg.select_timeout = 255;
-		info->info.ifcfg.asyncperiod	= ARXESCSI_ASYNC_PERIOD;
-		info->info.ifcfg.sync_max_depth	= ARXESCSI_SYNC_DEPTH;
-		info->info.ifcfg.cntl3		= CNTL3_FASTSCSI | CNTL3_FASTCLK;
-		info->info.ifcfg.disconnect_ok	= 0;
-		info->info.ifcfg.wide_max_size	= 0;
-		info->info.dma.setup		= arxescsi_dma_setup;
-		info->info.dma.pseudo		= arxescsi_dma_pseudo;
-		info->info.dma.stop		= arxescsi_dma_stop;
-		info->dmaarea			= host->io_port + 128;
-		info->cstatus			= host->io_port + 384;
-		
-		ecs[count]->irqaddr = (unsigned char *)BUS_ADDR(host->io_port);
-		ecs[count]->irqmask = CSTATUS_IRQ;
-
-		if (!request_region(host->io_port, 120, "arxescsi-fas")) {
-			ecard_release(ecs[count]);
-			scsi_unregister(host);
-			break;
-		}
-			
-		if (!request_region(host->io_port + 128, 384, "arxescsi-dma")) {
-			ecard_release(ecs[count]);
-			release_region(host->io_port, 120);
-			scsi_unregister(host);
-			break;
-		}
-
-		printk("scsi%d: Has no interrupts - using polling mode\n",
-		       host->host_no);
-
-		fas216_init(host);
-		++count;
-	}
-	return count;
-}
-
-/*
- * Function: int arxescsi_release(struct Scsi_Host * host)
- * Purpose : releases all resources used by this adapter
- * Params  : host - driver host structure to return info for.
- * Returns : nothing
- */
-int arxescsi_release(struct Scsi_Host *host)
-{
-	int i;
-
-	fas216_release(host);
-
-	release_region(host->io_port, 120);
-	release_region(host->io_port + 128, 384);
-
-	for (i = 0; i < MAX_ECARDS; i++)
-		if (ecs[i] && host->io_port == (ecard_address(ecs[i], ECARD_MEMC, 0) + 0x0800))
-			ecard_release(ecs[i]);
-	return 0;
-}
-
-/*
  * Function: const char *arxescsi_info(struct Scsi_Host * host)
  * Purpose : returns a descriptive string about this interface,
  * Params  : host - driver host structure to return info for.
@@ -355,7 +261,7 @@
  */
 const char *arxescsi_info(struct Scsi_Host *host)
 {
-	ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata;
+	struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
 	static char string[100], *p;
 
 	p = string;
@@ -385,14 +291,14 @@
 {
 	int pos, begin;
 	struct Scsi_Host *host;
-	ARXEScsi_Info *info;
+	struct arxescsi_info *info;
 	Scsi_Device *scd;
 
 	host = scsi_host_hn_get(host_no);
 	if (!host)
 		return 0;
 
-	info = (ARXEScsi_Info *)host->hostdata;
+	info = (struct arxescsi_info *)host->hostdata;
 	if (inout == 1)
 		return -EINVAL;
 
@@ -424,22 +330,122 @@
 	return pos;
 }
 
-static Scsi_Host_Template arxescsi_template = ARXEScsi;
+static Scsi_Host_Template arxescsi_template = {
+	.proc_info			= arxescsi_proc_info,
+	.name				= "ARXE SCSI card",
+	.info				= arxescsi_info,
+	.command			= fas216_command,
+	.queuecommand			= fas216_queue_command,
+	.eh_host_reset_handler		= fas216_eh_host_reset,
+	.eh_bus_reset_handler		= fas216_eh_bus_reset,
+	.eh_device_reset_handler	= fas216_eh_device_reset,
+	.eh_abort_handler		= fas216_eh_abort,
+	.can_queue			= 0,
+	.this_id			= 7,
+	.sg_tablesize			= SG_ALL,
+	.cmd_per_lun			= CMD_PER_LUN,
+	.use_clustering			= DISABLE_CLUSTERING,
+	.proc_name			= "arxescsi",
+};
 
-static int __init init_arxe_scsi_driver(void)
+static int __devinit
+arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-        arxescsi_template.module = THIS_MODULE;
-	scsi_register_host(&arxescsi_template);
-	if (arxescsi_template.present)
-		return 0;
+	struct Scsi_Host *host;
+      	struct arxescsi_info *info;
+      	int ret = -ENOMEM;
+
+	host = scsi_register(&arxescsi_template, sizeof(struct arxescsi_info));
+	if (!host)
+		goto out;
+
+	host->io_port = ecard_address(ec, ECARD_MEMC, 0) + 0x0800;
+	host->irq = NO_IRQ;
+	host->dma_channel = NO_DMA;
+
+	info = (struct arxescsi_info *)host->hostdata;
+	info->info.scsi.io_port		= host->io_port;
+	info->info.scsi.irq		= host->irq;
+	info->info.scsi.io_shift	= 3;
+	info->info.ifcfg.clockrate	= 24; /* MHz */
+	info->info.ifcfg.select_timeout = 255;
+	info->info.ifcfg.asyncperiod	= 200; /* ns */
+	info->info.ifcfg.sync_max_depth	= 0;
+	info->info.ifcfg.cntl3		= CNTL3_FASTSCSI | CNTL3_FASTCLK;
+	info->info.ifcfg.disconnect_ok	= 0;
+	info->info.ifcfg.wide_max_size	= 0;
+	info->info.dma.setup		= arxescsi_dma_setup;
+	info->info.dma.pseudo		= arxescsi_dma_pseudo;
+	info->info.dma.stop		= arxescsi_dma_stop;
+	info->dmaarea			= host->io_port + 128;
+	info->cstatus			= host->io_port + 384;
+		
+	ec->irqaddr = (unsigned char *)BUS_ADDR(host->io_port);
+	ec->irqmask = CSTATUS_IRQ;
+
+	if (!request_region(host->io_port, 120, "arxescsi-fas")) {
+		ret = -EBUSY;
+		goto out_free;
+	}
+			
+	if (!request_region(host->io_port + 128, 384, "arxescsi-dma")) {
+		ret = -EBUSY;
+		goto out_release;
+	}
 
-	scsi_unregister_host(&arxescsi_template);
-	return -ENODEV;
+	printk("scsi%d: Has no interrupts - using polling mode\n",
+	       host->host_no);
+
+	fas216_init(host);
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
+
+	release_region(host->io_port + 128, 384);
+ out_release:
+	release_region(host->io_port, 120);
+ out_free:
+	scsi_unregister(host);
+ out:
+	return ret;
+}
+
+static void __devexit arxescsi_release(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+	fas216_release(host);
+
+	release_region(host->io_port + 128, 384);
+	release_region(host->io_port, 120);
+	scsi_unregister(host);
+}
+
+static const struct ecard_id arxescsi_cids[] = {
+	{ MANU_ARXE, PROD_ARXE_SCSI },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver arxescsi_driver = {
+	.probe		= arxescsi_probe,
+	.remove		= __devexit_p(arxescsi_remove),
+	.id_table	= arxescsi_cids,
+	.drv = {
+		.name	= "arxescsi",
+	},
+};
+
+static int __init init_arxe_scsi_driver(void)
+{
+	return ecard_register_driver(&arxescsi_driver);
 }
 
 static void __exit exit_arxe_scsi_driver(void)
 {
-	scsi_unregister_host(&arxescsi_template);
+	ecard_remove_driver(&arxescsi_driver);
 }
 
 module_init(init_arxe_scsi_driver);
diff -Nru a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c
--- a/drivers/acorn/scsi/cumana_1.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/acorn/scsi/cumana_1.c	Sun Nov 17 20:30:03 2002
@@ -1,56 +1,13 @@
-#define AUTOSENSE
-#define PSEUDO_DMA
-
 /*
  * Generic Generic NCR5380 driver
  *
- * Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-
-/*
- * Options :
- *
- * PARITY - enable parity checking.  Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- */
-
-/*
- * $Log: cumana_1.c,v $
- * Revision 1.3  1998/05/03 20:45:32  alan
- * ARM SCSI update. This adds the eesox driver and massively updates the
- * Cumana driver. The folks who bought cumana arent anal retentive all
- * docs are secret weenies so now there are docs ..
- *
- * Revision 1.2  1998/03/08 05:49:46  davem
- * Merge to 2.1.89
- *
- * Revision 1.1  1998/02/23 02:45:22  davem
- * Merge to 2.1.88
- *
+ * Copyright 1995-2002, Russell King
  */
-
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <linux/blk.h>
 #include <linux/init.h>
 
@@ -64,28 +21,19 @@
 
 #include <scsi/scsicam.h>
 
-#define CUMANASCSI_PUBLIC_RELEASE 1
-
-static const card_ids cumanascsi_cids[] = {
-	{ MANU_CUMANA, PROD_CUMANA_SCSI_1 },
-	{ 0xffff, 0xffff }
-};
-
-#define NCR5380_implementation_fields \
-    int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
+#define AUTOSENSE
+#define PSEUDO_DMA
 
-#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
-#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
+#define CUMANASCSI_PUBLIC_RELEASE 1
 
-#define NCR5380_intr		cumanascsi_intr
-#define NCR5380_queue_command	cumanascsi_queue_command
-#define NCR5380_proc_info	cumanascsi_proc_info
+#define NCR5380_implementation_fields	int port, ctrl
+#define NCR5380_local_declare()		struct Scsi_Host *_instance
+#define NCR5380_setup(instance)		_instance = instance
+#define NCR5380_read(reg)		cumanascsi_read(_instance, reg)
+#define NCR5380_write(reg, value)	cumanascsi_write(_instance, reg, value)
+#define NCR5380_intr			cumanascsi_intr
+#define NCR5380_queue_command		cumanascsi_queue_command
+#define NCR5380_proc_info		cumanascsi_proc_info
 
 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
 		      int length, int hostno, int inout);
@@ -95,112 +43,13 @@
 
 #include "../../scsi/NCR5380.h"
 
-/*
- * Function : cumanascsi_setup(char *str, int *ints)
- *
- * Purpose : LILO command line initialization of the overrides array,
- *
- * Inputs : str - unused, ints - array of integer parameters with ints[0]
- *	equal to the number of ints.
- *
- */
-
 void cumanascsi_setup(char *str, int *ints)
 {
 }
 
-#define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
-#define CUMANA_IRQ(card)     ((card)->irq)
-/*
- * Function : int cumanascsi_detect(Scsi_Host_Template * tpnt)
- *
- * Purpose : initializes cumana NCR5380 driver based on the
- *	command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
-static struct expansion_card *ecs[4];
- 
-int cumanascsi_detect(Scsi_Host_Template * tpnt)
+const char *cumanascsi_info(struct Scsi_Host *spnt)
 {
-    int count = 0;
-    struct Scsi_Host *instance;
-
-    tpnt->proc_name = "CumanaSCSI-1";
-
-    memset (ecs, 0, sizeof (ecs));
-
-    while(1) {
-    	if((ecs[count] = ecard_find(0, cumanascsi_cids)) == NULL)
-    		break;
-
-        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-	if (!instance)
-		break;
-        instance->io_port = CUMANA_ADDRESS(ecs[count]);
-	instance->irq = CUMANA_IRQ(ecs[count]);
-
-	NCR5380_init(instance, 0);
-	ecard_claim(ecs[count]);
-
-	instance->n_io_port = 255;
-	if ( !(request_region (instance->io_port, instance->n_io_port, "CumanaSCSI-1")) ) {
-		ecard_release(ecs[count]);
-		scsi_unregister(instance);
-		break;
-	}
-
-        ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
-        outb(0x00, instance->io_port - 577);
-
-	if (instance->irq != IRQ_NONE)
-	    if (request_irq(instance->irq, cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
-		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-		    instance->host_no, instance->irq);
-		instance->irq = IRQ_NONE;
-	    }
-
-	if (instance->irq == IRQ_NONE) {
-	    printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
-	    printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
-	}
-
-	printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-	if (instance->irq == IRQ_NONE)
-	    printk ("s disabled");
-	else
-	    printk (" %d", instance->irq);
-	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-	    tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
-	printk("\nscsi%d:", instance->host_no);
-	NCR5380_print_options(instance);
-	printk("\n");
-
-	++count;
-    }
-    return count;
-}
-
-int cumanascsi_release (struct Scsi_Host *shpnt)
-{
-	int i;
-
-	if (shpnt->irq != IRQ_NONE)
-		free_irq (shpnt->irq, NULL);
-	if (shpnt->io_port)
-		release_region (shpnt->io_port, shpnt->n_io_port);
-
-	for (i = 0; i < 4; i++)
-		if (shpnt->io_port == CUMANA_ADDRESS(ecs[i]))
-			ecard_release (ecs[i]);
-	return 0;
-}
-
-const char * cumanascsi_info (struct Scsi_Host *spnt) {
-    return "";
+	return "";
 }
 
 #ifdef NOT_EFFICIENT
@@ -219,8 +68,8 @@
 #define L(v)		(((v)<<16)|((v) & 0x0000ffff))
 #define H(v)		(((v)>>16)|((v) & 0xffff0000))
 
-static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
-              int len)
+static inline int
+NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len)
 {
   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
   int oldctrl = *ctrl;
@@ -289,8 +138,8 @@
   return len;
 }
 
-static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
-              int len)
+static inline int
+NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len)
 {
   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
   int oldctrl = *ctrl;
@@ -367,25 +216,25 @@
 
 static char cumanascsi_read(struct Scsi_Host *instance, int reg)
 {
-  int iobase = instance->io_port;
-  int i;
-  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
+	unsigned int iobase = instance->io_port;
+	int i;
+	int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
 
-  CTRL(iobase, 0);
-  i = inb(iobase + 64 + reg);
-  CTRL(iobase, 0x40);
+	CTRL(iobase, 0);
+	i = inb(iobase + 64 + reg);
+	CTRL(iobase, 0x40);
 
-  return i;
+	return i;
 }
 
 static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
 {
-  int iobase = instance->io_port;
-  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
+	int iobase = instance->io_port;
+	int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
 
-  CTRL(iobase, 0);
-  outb(value, iobase + 64 + reg);
-  CTRL(iobase, 0x40);
+	CTRL(iobase, 0);
+	outb(value, iobase + 64 + reg);
+	CTRL(iobase, 0x40);
 }
 
 #undef CTRL
@@ -395,8 +244,6 @@
 static Scsi_Host_Template cumanascsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "Cumana 16-bit SCSI",
-	.detect			= cumanascsi_detect,
-	.release		= cumanascsi_release,
 	.info			= cumanascsi_info,
 	.queuecommand		= cumanascsi_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
@@ -408,26 +255,101 @@
 	.sg_tablesize		= SG_ALL,
 	.cmd_per_lun		= 2,
 	.unchecked_isa_dma	= 0,
-	.use_clustering		= DISABLE_CLUSTERING
+	.use_clustering		= DISABLE_CLUSTERING,
+	.proc_name		= "CumanaSCSI-1",
 };
 
-static int __init cumanascsi_init(void)
+static int __devinit
+cumanascsi1_probe(struct expansion_card *ec, struct ecard_ids *id)
 {
-	scsi_register_host(&cumanascsi_template);
-	if (cumanascsi_template.present)
-		return 0;
+	struct Scsi_Host *host;
+	int ret = -ENOMEM;
+
+	host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
+	if (!host)
+		goto out;
+
+        host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800;
+	host->irq = ec->irq;
+
+	NCR5380_init(host, 0);
+
+	host->n_io_port = 255;
+	if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) {
+		ret = -EBUSY;
+		goto out_free;
+	}
 
-	scsi_unregister_host(&cumanascsi_template);
-	return -ENODEV;
+        ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0;
+        outb(0x00, host->io_port - 577);
+
+	ret = request_irq(host->irq, cumanascsi_intr, SA_INTERRUPT,
+			  "CumanaSCSI-1", host);
+	if (ret) {
+		printk("scsi%d: IRQ%d not free: %d\n",
+		    host->host_no, host->irq, ret);
+		goto out_release;
+	}
+
+	printk("scsi%d: at port 0x%08lx irq %d",
+		host->host_no, host->io_port, host->irq);
+	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
+	    tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
+	printk("\nscsi%d:", host->host_no);
+	NCR5380_print_options(host);
+	printk("\n");
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
+
+	free_irq(host->irq, host);
+ out_release:
+	release_region(host->io_port, host->n_io_port);
+ out_free:
+	scsi_unregister(host);
+ out:
+	return ret;
+}
+
+static void __devexit cumanascsi1_remove(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+
+	scsi_remove_host(host);
+	free_irq(host->irq, host);
+	release_region(host->io_port, host->n_io_port);
+	scsi_remove(host);
+}
+
+static const struct ecard_ids cumanascsi1_cids[] = {
+	{ MANU_CUMANA, PROD_CUMANA_SCSI_1 },
+	{ 0xffff, 0xffff }
+};
+
+static struct ecard_driver cumanascsi1_driver = {
+	.probe		= cumanascsi1_probe,
+	.remove		= __devexit_p(cumanascsi1_remove),
+	.id_table	= cumanascsi1_cids,
+	.drv = {
+		.name	= "cumanascsi1",
+	},
+};
+
+static int __init cumanascsi_init(void)
+{
+	return ecard_register_driver(&cumanascsi1_driver);
 }
 
 static void __exit cumanascsi_exit(void)
 {
-	scsi_unregister_host(&cumanascsi_template);
+	ecard_remove_driver(&cumanascsi1_driver);
 }
 
 module_init(cumanascsi_init);
 module_exit(cumanascsi_exit);
 
+MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
--- a/drivers/acorn/scsi/cumana_2.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acorn/scsi/cumana_2.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/scsi/cumana_2.c
  *
- *  Copyright (C) 1997-2000 Russell King
+ *  Copyright (C) 1997-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -42,16 +42,6 @@
 
 #include <scsi/scsicam.h>
 
-/* Configuration */
-#define CUMANASCSI2_XTALFREQ		40
-#define CUMANASCSI2_ASYNC_PERIOD	200
-#define CUMANASCSI2_SYNC_DEPTH		7
-
-/*
- * List of devices that the driver will recognise
- */
-#define CUMANASCSI2_LIST		{ MANU_CUMANA, PROD_CUMANA_SCSI_2 }
-
 #define CUMANASCSI2_STATUS		(0)
 #define STATUS_INT			(1 << 0)
 #define STATUS_DRQ			(1 << 1)
@@ -73,15 +63,12 @@
 
 #define CUMANASCSI2_FAS216_OFFSET	(0xc0)
 #define CUMANASCSI2_FAS216_SHIFT	0
+#define CUMANASCSI2_FAS216_SIZE		(16)
 
 /*
  * Version
  */
-#define VER_MAJOR	0
-#define VER_MINOR	0
-#define VER_PATCH	4
-
-static struct expansion_card *ecs[MAX_ECARDS];
+#define VERSION "1.00 (13/11/2002 2.5.47)"
 
 /*
  * Use term=0,1,0,0,0 to turn terminators on/off
@@ -90,16 +77,15 @@
 
 #define NR_SG	256
 
-typedef struct {
+struct cumanascsi2_info {
 	FAS216_Info info;
 
-	/* other info... */
 	unsigned int	status;		/* card status register	*/
 	unsigned int	alatch;		/* Control register	*/
 	unsigned int	terms;		/* Terminator state	*/
 	unsigned int	dmaarea;	/* Pseudo DMA area	*/
 	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} CumanaScsi2_Info;
+};
 
 #define CSTATUS_IRQ	(1 << 0)
 #define CSTATUS_DRQ	(1 << 1)
@@ -129,12 +115,8 @@
 }
 
 static const expansioncard_ops_t cumanascsi_2_ops = {
-	cumanascsi_2_irqenable,
-	cumanascsi_2_irqdisable,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	.irqenable	= cumanascsi_2_irqenable,
+	.irqdisable	= cumanascsi_2_irqdisable,
 };
 
 /* Prototype: void cumanascsi_2_terminator_ctl(host, on_off)
@@ -145,7 +127,7 @@
 static void
 cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off)
 {
-	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 
 	if (on_off) {
 		info->terms = 1;
@@ -182,7 +164,7 @@
 cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
-	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 	int dmach = host->dma_channel;
 
 	outb(ALATCH_DIS_DMA, info->alatch);
@@ -233,7 +215,7 @@
 cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
 			fasdmadir_t direction, int transfer)
 {
-	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 	unsigned int length;
 	unsigned char *addr;
 
@@ -307,129 +289,13 @@
 static void
 cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
 {
-	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 	if (host->dma_channel != NO_DMA) {
 		outb(ALATCH_DIS_DMA, info->alatch);
 		disable_dma(host->dma_channel);
 	}
 }
 
-/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt)
- * Purpose  : initialises Cumana SCSI 2 driver
- * Params   : tpnt - template for this SCSI adapter
- * Returns  : >0 if host found, 0 otherwise.
- */
-int
-cumanascsi_2_detect(Scsi_Host_Template *tpnt)
-{
-	static const card_ids cumanascsi_2_cids[] =
-			{ CUMANASCSI2_LIST, { 0xffff, 0xffff} };
-	int count = 0;
-	struct Scsi_Host *host;
-  
-	tpnt->proc_name = "cumanascs2";
-	memset(ecs, 0, sizeof (ecs));
-
-	ecard_startfind();
-
-	while (1) {
-	    	CumanaScsi2_Info *info;
-
-		ecs[count] = ecard_find(0, cumanascsi_2_cids);
-		if (!ecs[count])
-			break;
-
-		ecard_claim(ecs[count]);
-
-		host = scsi_register(tpnt, sizeof (CumanaScsi2_Info));
-		if (!host) {
-			ecard_release(ecs[count]);
-			break;
-		}
-
-		host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
-		host->irq = ecs[count]->irq;
-		host->dma_channel = ecs[count]->dma;
-		info = (CumanaScsi2_Info *)host->hostdata;
-
-		info->terms			= term[count] ? 1 : 0;
-		cumanascsi_2_terminator_ctl(host, info->terms);
-
-		info->info.scsi.io_port		= host->io_port + CUMANASCSI2_FAS216_OFFSET;
-		info->info.scsi.io_shift	= CUMANASCSI2_FAS216_SHIFT;
-		info->info.scsi.irq		= host->irq;
-		info->info.ifcfg.clockrate	= CUMANASCSI2_XTALFREQ;
-		info->info.ifcfg.select_timeout	= 255;
-		info->info.ifcfg.asyncperiod	= CUMANASCSI2_ASYNC_PERIOD;
-		info->info.ifcfg.sync_max_depth	= CUMANASCSI2_SYNC_DEPTH;
-		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
-		info->info.ifcfg.disconnect_ok	= 1;
-		info->info.ifcfg.wide_max_size	= 0;
-		info->info.dma.setup		= cumanascsi_2_dma_setup;
-		info->info.dma.pseudo		= cumanascsi_2_dma_pseudo;
-		info->info.dma.stop		= cumanascsi_2_dma_stop;
-		info->dmaarea			= host->io_port + CUMANASCSI2_PSEUDODMA;
-		info->status			= host->io_port + CUMANASCSI2_STATUS;
-		info->alatch			= host->io_port + CUMANASCSI2_ALATCH;
-
-		ecs[count]->irqaddr	= (unsigned char *)ioaddr(info->status);
-		ecs[count]->irqmask	= STATUS_INT;
-		ecs[count]->irq_data	= (void *)info->alatch;
-		ecs[count]->ops		= (expansioncard_ops_t *)&cumanascsi_2_ops;
-
-		if (!request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
-			       16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas")) {
-			scsi_unregister(host);
-			ecard_release(ecs[count]);
-			break;
-		}
-			
-
-		if (host->irq != NO_IRQ &&
-		    request_irq(host->irq, cumanascsi_2_intr,
-				SA_INTERRUPT, "cumanascsi2", host)) {
-			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-			       host->host_no, host->irq);
-			host->irq = NO_IRQ;
-			info->info.scsi.irq = NO_IRQ;
-		}
-
-		if (host->dma_channel != NO_DMA &&
-		    request_dma(host->dma_channel, "cumanascsi2")) {
-			printk("scsi%d: DMA%d not free, DMA disabled\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
-		}
-
-		fas216_init(host);
-		++count;
-	}
-	return count;
-}
-
-/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host)
- * Purpose  : releases all resources used by this adapter
- * Params   : host - driver host structure to return info for.
- */
-int cumanascsi_2_release(struct Scsi_Host *host)
-{
-	int i;
-
-	fas216_release(host);
-
-	if (host->irq != NO_IRQ)
-		free_irq(host->irq, host);
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
-		       16 << CUMANASCSI2_FAS216_SHIFT);
-
-	for (i = 0; i < MAX_ECARDS; i++)
-		if (ecs[i] && host->io_port == ecard_address (ecs[i], ECARD_MEMC, 0))
-			ecard_release (ecs[i]);
-	return 0;
-}
-
 /* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host)
  * Purpose  : returns a descriptive string about this interface,
  * Params   : host - driver host structure to return info for.
@@ -437,15 +303,14 @@
  */
 const char *cumanascsi_2_info(struct Scsi_Host *host)
 {
-	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 	static char string[100], *p;
 
 	p = string;
 	p += sprintf(p, "%s ", host->hostt->name);
 	p += fas216_info(&info->info, p);
-	p += sprintf(p, "v%d.%d.%d terminators o%s",
-		     VER_MAJOR, VER_MINOR, VER_PATCH,
-		     info->terms ? "n" : "ff");
+	p += sprintf(p, "v%s terminators o%s",
+		     VERSION, info->terms ? "n" : "ff");
 
 	return string;
 }
@@ -499,7 +364,7 @@
 {
 	int pos, begin;
 	struct Scsi_Host *host;
-	CumanaScsi2_Info *info;
+	struct cumanascsi2_info *info;
 	Scsi_Device *scd;
 
 	host = scsi_host_hn_get(host_no);
@@ -509,12 +374,12 @@
 	if (inout == 1)
 		return cumanascsi_2_set_proc_info(host, buffer, length);
 
-	info = (CumanaScsi2_Info *)host->hostdata;
+	info = (struct cumanascsi2_info *)host->hostdata;
 
 	begin = 0;
 	pos = sprintf(buffer,
-			"Cumana SCSI II driver version %d.%d.%d\n",
-			VER_MAJOR, VER_MINOR, VER_PATCH);
+			"Cumana SCSI II driver version v%s\n",
+			VERSION);
 
 	pos += fas216_print_host(&info->info, buffer + pos);
 	pos += sprintf(buffer + pos, "Term    : o%s\n",
@@ -556,35 +421,148 @@
 	.module				= THIS_MODULE,
 	.proc_info			= cumanascsi_2_proc_info,
 	.name				= "Cumana SCSI II",
-	.detect				= cumanascsi_2_detect,
-	.release			= cumanascsi_2_release,
 	.info				= cumanascsi_2_info,
-	.can_queue			= 1,
-	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
-	.cmd_per_lun			= 1,
-	.use_clustering			= DISABLE_CLUSTERING,
 	.command			= fas216_command,
 	.queuecommand			= fas216_queue_command,
 	.eh_host_reset_handler		= fas216_eh_host_reset,
 	.eh_bus_reset_handler		= fas216_eh_bus_reset,
 	.eh_device_reset_handler	= fas216_eh_device_reset,
 	.eh_abort_handler		= fas216_eh_abort,
+	.can_queue			= 1,
+	.this_id			= 7,
+	.sg_tablesize			= SG_ALL,
+	.cmd_per_lun			= 1,
+	.use_clustering			= DISABLE_CLUSTERING,
+	.proc_name			= "cumanascsi2",
 };
 
-static int __init cumanascsi2_init(void)
+static int __devinit
+cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-	scsi_register_host(&cumanascsi2_template);
-	if (cumanascsi2_template.present)
-		return 0;
+	struct Scsi_Host *host;
+    	struct cumanascsi2_info *info;
+    	int ret = -ENOMEM;
+
+	host = scsi_register(&cumanascsi2_template, sizeof (struct cumanascsi2_info));
+	if (!host)
+		goto out;
+
+	host->io_port = ecard_address(ec, ECARD_MEMC, 0);
+	host->irq = ec->irq;
+	host->dma_channel = ec->dma;
+
+	if (!request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
+			    CUMANASCSI2_FAS216_SIZE, "cumanascsi2-fas")) {
+		ret = -EBUSY;
+		goto out_free;
+	}
+
+	ecard_set_drvdata(ec, host);
+
+	info = (struct cumanascsi2_info *)host->hostdata;
+	info->dmaarea	= host->io_port + CUMANASCSI2_PSEUDODMA;
+	info->status	= host->io_port + CUMANASCSI2_STATUS;
+	info->alatch	= host->io_port + CUMANASCSI2_ALATCH;
+
+	ec->irqaddr	= (unsigned char *)ioaddr(info->status);
+	ec->irqmask	= STATUS_INT;
+	ec->irq_data	= (void *)info->alatch;
+	ec->ops		= (expansioncard_ops_t *)&cumanascsi_2_ops;
+
+	cumanascsi_2_terminator_ctl(host, term[ec->slot_no]);
+
+	info->info.scsi.io_port		= host->io_port + CUMANASCSI2_FAS216_OFFSET;
+	info->info.scsi.io_shift	= CUMANASCSI2_FAS216_SHIFT;
+	info->info.scsi.irq		= host->irq;
+	info->info.ifcfg.clockrate	= 40; /* MHz */
+	info->info.ifcfg.select_timeout	= 255;
+	info->info.ifcfg.asyncperiod	= 200; /* ns */
+	info->info.ifcfg.sync_max_depth	= 7;
+	info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+	info->info.ifcfg.disconnect_ok	= 1;
+	info->info.ifcfg.wide_max_size	= 0;
+	info->info.dma.setup		= cumanascsi_2_dma_setup;
+	info->info.dma.pseudo		= cumanascsi_2_dma_pseudo;
+	info->info.dma.stop		= cumanascsi_2_dma_stop;
+
+	ret = request_irq(host->irq, cumanascsi_2_intr,
+			  SA_INTERRUPT, "cumanascsi2", host);
+	if (ret) {
+		printk("scsi%d: IRQ%d not free: %d\n",
+		       host->host_no, host->irq, ret);
+		goto out_region;
+	}
+
+	if (host->dma_channel != NO_DMA) {
+		if (request_dma(host->dma_channel, "cumanascsi2")) {
+			printk("scsi%d: DMA%d not free, using PIO\n",
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
+		} else {
+			set_dma_speed(host->dma_channel, 180);
+		}
+	}
+
+	fas216_init(host);
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
 
-	scsi_unregister_host(&cumanascsi2_template);
-	return -ENODEV;
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+ out_region:
+	release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
+		       CUMANASCSI2_FAS216_SIZE);
+ out_free:
+	scsi_unregister(host);
+
+ out:
+	return ret;
+}
+
+static void __devexit cumanascsi2_remove(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+	release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
+		       CUMANASCSI2_FAS216_SIZE);
+
+	scsi_unregister(host);
+}
+
+static const struct ecard_id cumanascsi2_cids[] = {
+	{ MANU_CUMANA, PROD_CUMANA_SCSI_2 },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver cumanascsi2_driver = {
+	.probe		= cumanascsi2_probe,
+	.remove		= __devexit_p(cumanascsi2_remove),
+	.id_table	= cumanascsi2_cids,
+	.drv = {
+		.name	= "cumanascsi2",
+	},
+};
+
+static int __init cumanascsi2_init(void)
+{
+	return ecard_register_driver(&cumanascsi2_driver);
 }
 
 static void __exit cumanascsi2_exit(void)
 {
-	scsi_unregister_host(&cumanascsi2_template);
+	ecard_remove_driver(&cumanascsi2_driver);
 }
 
 module_init(cumanascsi2_init);
@@ -595,4 +573,3 @@
 MODULE_PARM(term, "1-8i");
 MODULE_PARM_DESC(term, "SCSI bus termination");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c
--- a/drivers/acorn/scsi/ecoscsi.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acorn/scsi/ecoscsi.c	Sun Nov 17 20:30:15 2002
@@ -45,6 +45,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/blk.h>
 
diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
--- a/drivers/acorn/scsi/eesox.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acorn/scsi/eesox.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/scsi/eesox.c
  *
- *  Copyright (C) 1997-2000 Russell King
+ *  Copyright (C) 1997-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -48,18 +48,9 @@
 
 #include <scsi/scsicam.h>
 
-/* Configuration */
-#define EESOX_XTALFREQ		40
-#define EESOX_ASYNC_PERIOD	200
-#define EESOX_SYNC_DEPTH	7
-
-/*
- * List of devices that the driver will recognise
- */
-#define EESOXSCSI_LIST	{ MANU_EESOX, PROD_EESOX_SCSI2 }
-
 #define EESOX_FAS216_OFFSET	0xc00
 #define EESOX_FAS216_SHIFT	3
+#define EESOX_FAS216_SIZE	(16 << EESOX_FAS216_SHIFT)
 
 #define EESOX_STATUS		0xa00
 #define EESOX_STAT_INTR		0x01
@@ -75,11 +66,7 @@
 /*
  * Version
  */
-#define VER_MAJOR	0
-#define VER_MINOR	0
-#define VER_PATCH	3
-
-static struct expansion_card *ecs[MAX_ECARDS];
+#define VERSION "1.00 (13/11/2002 2.5.47)"
 
 /*
  * Use term=0,1,0,0,0 to turn terminators on/off
@@ -88,19 +75,14 @@
 
 #define NR_SG	256
 
-struct control {
-	unsigned int	io_port;
-	unsigned int	control;
-};
-
-typedef struct {
+struct eesoxscsi_info {
 	FAS216_Info info;
 
-	struct control control;
-
+	unsigned int	ctl_port;
+	unsigned int	control;
 	unsigned int	dmaarea;	/* Pseudo DMA area	*/
 	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} EESOXScsi_Info;
+};
 
 /* Prototype: void eesoxscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on EESOX SCSI card
@@ -110,11 +92,11 @@
 static void
 eesoxscsi_irqenable(struct expansion_card *ec, int irqnr)
 {
-	struct control *control = (struct control *)ec->irq_data;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data;
 
-	control->control |= EESOX_INTR_ENABLE;
+	info->control |= EESOX_INTR_ENABLE;
 
-	outb(control->control, control->io_port);
+	outb(info->control, info->ctl_port);
 }
 
 /* Prototype: void eesoxscsi_irqdisable(ec, irqnr)
@@ -125,20 +107,16 @@
 static void
 eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr)
 {
-	struct control *control = (struct control *)ec->irq_data;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data;
 
-	control->control &= ~EESOX_INTR_ENABLE;
+	info->control &= ~EESOX_INTR_ENABLE;
 
-	outb(control->control, control->io_port);
+	outb(info->control, info->ctl_port);
 }
 
 static const expansioncard_ops_t eesoxscsi_ops = {
-	eesoxscsi_irqenable,
-	eesoxscsi_irqdisable,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	.irqenable	= eesoxscsi_irqenable,
+	.irqdisable	= eesoxscsi_irqdisable,
 };
 
 /* Prototype: void eesoxscsi_terminator_ctl(*host, on_off)
@@ -149,16 +127,16 @@
 static void
 eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
 {
-	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	unsigned long flags;
 
 	spin_lock_irqsave(host->host_lock, flags);
 	if (on_off)
-		info->control.control |= EESOX_TERM_ENABLE;
+		info->control |= EESOX_TERM_ENABLE;
 	else
-		info->control.control &= ~EESOX_TERM_ENABLE;
+		info->control &= ~EESOX_TERM_ENABLE;
 
-	outb(info->control.control, info->control.io_port);
+	outb(info->control, info->ctl_port);
 	spin_unlock_irqrestore(host->host_lock, flags);
 }
 
@@ -188,7 +166,7 @@
 eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
-	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	int dmach = host->dma_channel;
 
 	if (dmach != NO_DMA &&
@@ -224,7 +202,7 @@
 eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
 		     fasdmadir_t dir, int transfer_size)
 {
-	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	unsigned int status;
 	unsigned int length = SCp->this_residual;
 	union {
@@ -321,116 +299,6 @@
 		disable_dma(host->dma_channel);
 }
 
-/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt)
- * Purpose  : initialises EESOX SCSI driver
- * Params   : tpnt - template for this SCSI adapter
- * Returns  : >0 if host found, 0 otherwise.
- */
-int
-eesoxscsi_detect(Scsi_Host_Template *tpnt)
-{
-	static const card_ids eesoxscsi_cids[] =
-			{ EESOXSCSI_LIST, { 0xffff, 0xffff} };
-	int count = 0;
-	struct Scsi_Host *host;
-  
-	tpnt->proc_name = "eesox";
-	memset(ecs, 0, sizeof (ecs));
-
-	ecard_startfind();
-
-	while(1) {
-	    	EESOXScsi_Info *info;
-
-		ecs[count] = ecard_find(0, eesoxscsi_cids);
-		if (!ecs[count])
-			break;
-
-		ecard_claim(ecs[count]);
-
-		host = scsi_register(tpnt, sizeof (EESOXScsi_Info));
-		if (!host) {
-			ecard_release(ecs[count]);
-			break;
-		}
-
-		host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST);
-		host->irq = ecs[count]->irq;
-		host->dma_channel = ecs[count]->dma;
-		info = (EESOXScsi_Info *)host->hostdata;
-
-		info->control.io_port = host->io_port + EESOX_CONTROL;
-		info->control.control = term[count] ? EESOX_TERM_ENABLE : 0;
-		outb(info->control.control, info->control.io_port);
-
-		ecs[count]->irqaddr = (unsigned char *)
-			    ioaddr(host->io_port + EESOX_STATUS);
-		ecs[count]->irqmask = EESOX_STAT_INTR;
-		ecs[count]->irq_data = &info->control;
-		ecs[count]->ops = (expansioncard_ops_t *)&eesoxscsi_ops;
-
-		info->info.scsi.io_port		= host->io_port + EESOX_FAS216_OFFSET;
-		info->info.scsi.io_shift	= EESOX_FAS216_SHIFT;
-		info->info.scsi.irq		= host->irq;
-		info->info.ifcfg.clockrate	= EESOX_XTALFREQ;
-		info->info.ifcfg.select_timeout	= 255;
-		info->info.ifcfg.asyncperiod	= EESOX_ASYNC_PERIOD;
-		info->info.ifcfg.sync_max_depth	= EESOX_SYNC_DEPTH;
-		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
-		info->info.ifcfg.disconnect_ok	= 1;
-		info->info.ifcfg.wide_max_size	= 0;
-		info->info.dma.setup		= eesoxscsi_dma_setup;
-		info->info.dma.pseudo		= eesoxscsi_dma_pseudo;
-		info->info.dma.stop		= eesoxscsi_dma_stop;
-		info->dmaarea			= host->io_port + EESOX_DMA_OFFSET;
-
-		request_region(host->io_port + EESOX_FAS216_OFFSET,
-				16 << EESOX_FAS216_SHIFT, "eesox2-fas");
-
-		if (host->irq != NO_IRQ &&
-		    request_irq(host->irq, eesoxscsi_intr,
-				SA_INTERRUPT, "eesox", host)) {
-			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-			       host->host_no, host->irq);
-			host->irq = NO_IRQ;
-		}
-
-		if (host->dma_channel != NO_DMA &&
-		    request_dma(host->dma_channel, "eesox")) {
-			printk("scsi%d: DMA%d not free, DMA disabled\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
-		}
-
-		fas216_init(host);
-		++count;
-	}
-	return count;
-}
-
-/* Prototype: int eesoxscsi_release(struct Scsi_Host * host)
- * Purpose  : releases all resources used by this adapter
- * Params   : host - driver host structure to return info for.
- */
-int eesoxscsi_release(struct Scsi_Host *host)
-{
-	int i;
-
-	fas216_release(host);
-
-	if (host->irq != NO_IRQ)
-		free_irq(host->irq, host);
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT);
-
-	for (i = 0; i < MAX_ECARDS; i++)
-		if (ecs[i] &&
-		    host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST))
-			ecard_release(ecs[i]);
-	return 0;
-}
-
 /* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host)
  * Purpose  : returns a descriptive string about this interface,
  * Params   : host - driver host structure to return info for.
@@ -438,15 +306,15 @@
  */
 const char *eesoxscsi_info(struct Scsi_Host *host)
 {
-	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	static char string[100], *p;
 
 	p = string;
 	p += sprintf(p, "%s ", host->hostt->name);
 	p += fas216_info(&info->info, p);
-	p += sprintf(p, "v%d.%d.%d terminators o%s",
-		     VER_MAJOR, VER_MINOR, VER_PATCH,
-		     info->control.control & EESOX_TERM_ENABLE ? "n" : "ff");
+	p += sprintf(p, "v%s terminators o%s",
+		     VERSION,
+		     info->control & EESOX_TERM_ENABLE ? "n" : "ff");
 
 	return string;
 }
@@ -500,7 +368,7 @@
 {
 	int pos, begin;
 	struct Scsi_Host *host;
-	EESOXScsi_Info *info;
+	struct eesoxscsi_info *info;
 	Scsi_Device *scd;
 
 	host = scsi_host_hn_get(host_no);
@@ -510,28 +378,28 @@
 	if (inout == 1)
 		return eesoxscsi_set_proc_info(host, buffer, length);
 
-	info = (EESOXScsi_Info *)host->hostdata;
+	info = (struct eesoxscsi_info *)host->hostdata;
 
 	begin = 0;
 	pos = sprintf(buffer,
-			"EESOX SCSI driver version %d.%d.%d\n",
-			VER_MAJOR, VER_MINOR, VER_PATCH);
+			"EESOX SCSI driver version v%s\n",
+			VERSION);
 	pos += fas216_print_host(&info->info, buffer + pos);
 	pos += sprintf(buffer + pos, "Term    : o%s\n",
-			info->control.control & EESOX_TERM_ENABLE ? "n" : "ff");
+			info->control & EESOX_TERM_ENABLE ? "n" : "ff");
 
 	pos += fas216_print_stats(&info->info, buffer + pos);
 
-	pos += sprintf (buffer+pos, "\nAttached devices:\n");
+	pos += sprintf(buffer+pos, "\nAttached devices:\n");
 
 	for (scd = host->host_queue; scd; scd = scd->next) {
 		int len;
 
-		proc_print_scsidevice (scd, buffer, &len, pos);
+		proc_print_scsidevice(scd, buffer, &len, pos);
 		pos += len;
-		pos += sprintf (buffer+pos, "Extensions: ");
+		pos += sprintf(buffer+pos, "Extensions: ");
 		if (scd->tagged_supported)
-			pos += sprintf (buffer+pos, "TAG %sabled [%d] ",
+			pos += sprintf(buffer+pos, "TAG %sabled [%d] ",
 					scd->tagged_queue ? "en" : "dis",
 					scd->current_tag);
 		pos += sprintf (buffer+pos, "\n");
@@ -553,35 +421,144 @@
 	.module				= THIS_MODULE,
 	.proc_info			= eesoxscsi_proc_info,
 	.name				= "EESOX SCSI",
-	.detect				= eesoxscsi_detect,
-	.release			= eesoxscsi_release,
 	.info				= eesoxscsi_info,
-	.can_queue			= 1,
-	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
-	.cmd_per_lun			= 1,
-	.use_clustering			= DISABLE_CLUSTERING,
 	.command			= fas216_command,
 	.queuecommand			= fas216_queue_command,
 	.eh_host_reset_handler		= fas216_eh_host_reset,
 	.eh_bus_reset_handler		= fas216_eh_bus_reset,
 	.eh_device_reset_handler	= fas216_eh_device_reset,
 	.eh_abort_handler		= fas216_eh_abort,
+	.can_queue			= 1,
+	.this_id			= 7,
+	.sg_tablesize			= SG_ALL,
+	.cmd_per_lun			= 1,
+	.use_clustering			= DISABLE_CLUSTERING,
+	.proc_name			= "eesox",
 };
 
-static int __init eesox_init(void)
+static int __devinit
+eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-	scsi_register_host(&eesox_template);
-	if (eesox_template.present)
-		return 0;
+	struct Scsi_Host *host;
+    	struct eesoxscsi_info *info;
+    	int ret = -ENOMEM;
+
+	host = scsi_register(&eesox_template,
+			     sizeof(struct eesoxscsi_info));
+	if (!host)
+		goto out;
+
+	host->io_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
+	host->irq = ec->irq;
+	host->dma_channel = ec->dma;
+
+	if (!request_region(host->io_port + EESOX_FAS216_OFFSET,
+			    EESOX_FAS216_SIZE, "eesox2-fas")) {
+		ret = -EBUSY;
+		goto out_free;
+	}
+
+	ecard_set_drvdata(ec, host);
+
+	info = (struct eesoxscsi_info *)host->hostdata;
+	info->ctl_port = host->io_port + EESOX_CONTROL;
+	info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0;
+	outb(info->control, info->ctl_port);
+
+	ec->irqaddr = (unsigned char *)ioaddr(host->io_port + EESOX_STATUS);
+	ec->irqmask = EESOX_STAT_INTR;
+	ec->irq_data = info;
+	ec->ops = (expansioncard_ops_t *)&eesoxscsi_ops;
+
+	info->info.scsi.io_port		= host->io_port + EESOX_FAS216_OFFSET;
+	info->info.scsi.io_shift	= EESOX_FAS216_SHIFT;
+	info->info.scsi.irq		= host->irq;
+	info->info.ifcfg.clockrate	= 40; /* MHz */
+	info->info.ifcfg.select_timeout	= 255;
+	info->info.ifcfg.asyncperiod	= 200; /* ns */
+	info->info.ifcfg.sync_max_depth	= 7;
+	info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+	info->info.ifcfg.disconnect_ok	= 1;
+	info->info.ifcfg.wide_max_size	= 0;
+	info->info.dma.setup		= eesoxscsi_dma_setup;
+	info->info.dma.pseudo		= eesoxscsi_dma_pseudo;
+	info->info.dma.stop		= eesoxscsi_dma_stop;
+	info->dmaarea			= host->io_port + EESOX_DMA_OFFSET;
+
+	ret = request_irq(host->irq, eesoxscsi_intr,
+			  SA_INTERRUPT, "eesox", host);
+	if (ret) {
+		printk("scsi%d: IRQ%d not free: %d\n",
+		       host->host_no, host->irq, ret);
+		goto out_region;
+	}
+
+	if (host->dma_channel != NO_DMA) {
+		if (request_dma(host->dma_channel, "eesox")) {
+			printk("scsi%d: DMA%d not free, DMA disabled\n",
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
+		} else {
+			set_dma_speed(host->dma_channel, 180);
+		}
+	}
 
-	scsi_unregister_host(&eesox_template);
-	return -ENODEV;
+	fas216_init(host);
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
+
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+ out_region:
+	release_region(host->io_port + EESOX_FAS216_OFFSET,
+		       EESOX_FAS216_SIZE);
+ out_free:
+	scsi_unregister(host);
+ out:
+	return ret;
+}
+
+static void __devexit eesoxscsi_remove(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+	release_region(host->io_port + EESOX_FAS216_OFFSET, EESOX_FAS216_SIZE);
+	scsi_unregister(host);
+}
+
+static const struct ecard_id eesoxscsi_cids[] = {
+	{ MANU_EESOX, PROD_EESOX_SCSI2 },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver eesoxscsi_driver = {
+	.probe		= eesoxscsi_probe,
+	.remove		= __devexit_p(eesoxscsi_remove),
+	.id_table	= eesoxscsi_cids,
+	.drv = {
+		.name	= "eesoxscsi",
+	},
+};
+
+static int __init eesox_init(void)
+{
+	return ecard_register_driver(&eesoxscsi_driver);
 }
 
 static void __exit eesox_exit(void)
 {
-	scsi_unregister_host(&eesox_template);
+	ecard_remove_driver(&eesoxscsi_driver);
 }
 
 module_init(eesox_init);
diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c
--- a/drivers/acorn/scsi/fas216.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acorn/scsi/fas216.c	Sun Nov 17 20:30:13 2002
@@ -93,14 +93,18 @@
 #undef  SCSI2_TAG
 
 #undef DEBUG_CONNECT
-#undef DEBUG_BUSSERVICE
-#undef DEBUG_FUNCTIONDONE
 #undef DEBUG_MESSAGES
 
 #undef CHECK_STRUCTURE
 
-static struct { int stat, ssr, isr, ph; } list[8];
-static int ptr;
+#define LOG_CONNECT		(1 << 0)
+#define LOG_BUSSERVICE		(1 << 1)
+#define LOG_FUNCTIONDONE	(1 << 2)
+#define LOG_MESSAGES		(1 << 3)
+#define LOG_BUFFER		(1 << 4)
+#define LOG_ERROR		(1 << 8)
+
+static int level_mask = LOG_ERROR;
 
 static void fas216_dumpstate(FAS216_Info *info)
 {
@@ -120,6 +124,13 @@
 		inb(REG_CNTL3(info)), inb(REG_CTCH(info)));
 }
 
+static void print_SCp(Scsi_Pointer *SCp, const char *prefix, const char *suffix)
+{
+	printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s",
+		prefix, SCp->ptr, SCp->this_residual, SCp->buffer,
+		SCp->buffers_residual, suffix);
+}
+
 static void fas216_dumpinfo(FAS216_Info *info)
 {
 	static int used = 0;
@@ -140,9 +151,7 @@
 		info->scsi.type, info->scsi.phase,
 		info->scsi.reconnected.target,
 		info->scsi.reconnected.lun, info->scsi.reconnected.tag);
-	printk("           SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
-		info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
-		info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual);
+	print_SCp(&info->scsi.SCp, "           SCp={ ", " }\n");
 	printk("      msgs async_stp=%X disconnectable=%d aborting=%d }\n",
 		info->scsi.async_stp,
 		info->scsi.disconnectable, info->scsi.aborting);
@@ -156,7 +165,7 @@
 		info->ifcfg.clockrate, info->ifcfg.select_timeout,
 		info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
 	for (i = 0; i < 8; i++) {
-		printk("    busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
+		printk("    busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
 			i, info->busyluns[i], i,
 			info->device[i].disconnect_ok, info->device[i].stp,
 			info->device[i].sof, info->device[i].sync_state);
@@ -229,29 +238,73 @@
 		return 'H';
 }
 
+static void fas216_log(FAS216_Info *info, int level, char *fmt, ...)
+{
+	va_list args;
+	static char buf[1024];
+
+	if (level != 0 && !(level & level_mask))
+		return;
+
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+
+	printk("scsi%d.%c: %s\n", info->host->host_no, fas216_target(info), buf);
+}
+
+#define PH_SIZE	32
+
+static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE];
+static int ph_ptr;
+
 static void add_debug_list(int stat, int ssr, int isr, int ph)
 {
-	list[ptr].stat = stat;
-	list[ptr].ssr = ssr;
-	list[ptr].isr = isr;
-	list[ptr].ph = ph;
+	ph_list[ph_ptr].stat = stat;
+	ph_list[ph_ptr].ssr = ssr;
+	ph_list[ph_ptr].isr = isr;
+	ph_list[ph_ptr].ph = ph;
 
-	ptr = (ptr + 1) & 7;
+	ph_ptr = (ph_ptr + 1) & (PH_SIZE-1);
+}
+
+static struct { int command; void *from; } cmd_list[8];
+static int cmd_ptr;
+
+static void fas216_cmd(FAS216_Info *info, unsigned int command)
+{
+	cmd_list[cmd_ptr].command = command;
+	cmd_list[cmd_ptr].from = __builtin_return_address(0);
+
+	cmd_ptr = (cmd_ptr + 1) & 7;
+
+	outb(command, REG_CMD(info));
 }
 
 static void print_debug_list(void)
 {
 	int i;
 
-	i = ptr;
+	i = ph_ptr;
 
-	printk(KERN_ERR "SCSI IRQ trail: ");
+	printk(KERN_ERR "SCSI IRQ trail\n");
 	do {
-		printk("%02X:%02X:%02X:%1X ",
-			list[i].stat, list[i].ssr,
-			list[i].isr, list[i].ph);
+		printk(" %02x:%02x:%02x:%1x",
+			ph_list[i].stat, ph_list[i].ssr,
+			ph_list[i].isr, ph_list[i].ph);
+		i = (i + 1) & (PH_SIZE - 1);
+		if (((i ^ ph_ptr) & 7) == 0)
+			printk("\n");
+	} while (i != ph_ptr);
+	if ((i ^ ph_ptr) & 7)
+		printk("\n");
+
+	i = cmd_ptr;
+	printk(KERN_ERR "FAS216 commands: ");
+	do {
+		printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from);
 		i = (i + 1) & 7;
-	} while (i != ptr);
+	} while (i != cmd_ptr);
 	printk("\n");
 }
 
@@ -299,10 +352,9 @@
 			packed_msg = msg->msg[0];
 	}
 
-#ifdef DEBUG_MESSAGES
-	printk("Message: %04X found at position %02X\n",
-		packed_msg, pos);
-#endif
+	fas216_log(info, LOG_MESSAGES,
+		"Message: %04x found at position %02x\n", packed_msg, pos);
+
 	return packed_msg;
 }
 
@@ -313,8 +365,7 @@
  *         : ns   - period in ns (between subsequent bytes)
  * Returns : Value suitable for REG_STP
  */
-static int
-fas216_syncperiod(FAS216_Info *info, int ns)
+static int fas216_syncperiod(FAS216_Info *info, int ns)
 {
 	int value = (info->ifcfg.clockrate * ns) / 1000;
 
@@ -336,8 +387,7 @@
  *           a transfer period >= 200ns - otherwise the chip will violate
  *           the SCSI timings.
  */
-static void
-fas216_set_sync(FAS216_Info *info, int target)
+static void fas216_set_sync(FAS216_Info *info, int target)
 {
 	outb(info->device[target].sof, REG_SOF(info));
 	outb(info->device[target].stp, REG_STP(info));
@@ -365,9 +415,9 @@
  *  Using the correct method assures compatibility with wide data
  *  transfers and future enhancements.
  *
- * We will always initiate a synchronous transfer negociation request on
+ * We will always initiate a synchronous transfer negotiation request on
  * every INQUIRY or REQUEST SENSE message, unless the target itself has
- * at some point performed a synchronous transfer negociation request, or
+ * at some point performed a synchronous transfer negotiation request, or
  * we have synchronous transfers disabled for this device.
  */
 
@@ -376,8 +426,7 @@
  * Params  : info - state structure for interface
  *         : msg  - message from target
  */
-static void
-fas216_handlesync(FAS216_Info *info, char *msg)
+static void fas216_handlesync(FAS216_Info *info, char *msg)
 {
 	struct fas216_device *dev = &info->device[info->SCpnt->target];
 	enum { sync, async, none, reject } res = none;
@@ -393,7 +442,7 @@
 		 *  message with a MESSAGE REJECT message.
 		 *
 		 * Hence, if we get this condition, we disable
-		 * negociation for this device.
+		 * negotiation for this device.
 		 */
 		if (dev->sync_state == neg_inprogress) {
 			dev->sync_state = neg_invalid;
@@ -411,14 +460,14 @@
 			res = reject;
 			break;
 
-		/* We were not negociating a synchronous transfer,
-		 * but the device sent us a negociation request.
+		/* We were not negotiating a synchronous transfer,
+		 * but the device sent us a negotiation request.
 		 * Honour the request by sending back a SDTR
 		 * message containing our capability, limited by
 		 * the targets capability.
 		 */
 		default:
-			outb(CMD_SETATN, REG_CMD(info));
+			fas216_cmd(info, CMD_SETATN);
 			if (msg[4] > info->ifcfg.sync_max_depth)
 				msg[4] = info->ifcfg.sync_max_depth;
 			if (msg[3] < 1000 / info->ifcfg.clockrate)
@@ -437,7 +486,7 @@
 			res = sync;
 			break;
 
-		/* We initiated the synchronous transfer negociation,
+		/* We initiated the synchronous transfer negotiation,
 		 * and have successfully received a response from the
 		 * target.  The synchronous transfer agreement has been
 		 * reached.  Note: if the values returned are out of our
@@ -466,7 +515,7 @@
 		break;
 
 	case reject:
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_flush(&info->scsi.msgs);
 		msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
@@ -488,8 +537,7 @@
  * Params  : info - state structure for interface
  *         : msg  - message from target
  */
-static void
-fas216_handlewide(FAS216_Info *info, char *msg)
+static void fas216_handlewide(FAS216_Info *info, char *msg)
 {
 	struct fas216_device *dev = &info->device[info->SCpnt->target];
 	enum { wide, bit8, none, reject } res = none;
@@ -505,7 +553,7 @@
 		 *  WDTR message with a MESSAGE REJECT message.
 		 *
 		 * Hence, if we get this condition, we never
-		 * reattempt negociation for this device.
+		 * reattempt negotiation for this device.
 		 */
 		if (dev->wide_state == neg_inprogress) {
 			dev->wide_state = neg_invalid;
@@ -523,14 +571,14 @@
 			res = reject;
 			break;
 
-		/* We were not negociating a wide data transfer,
-		 * but the device sent is a negociation request.
+		/* We were not negotiating a wide data transfer,
+		 * but the device sent is a negotiation request.
 		 * Honour the request by sending back a WDTR
 		 * message containing our capability, limited by
 		 * the targets capability.
 		 */
 		default:
-			outb(CMD_SETATN, REG_CMD(info));
+			fas216_cmd(info, CMD_SETATN);
 			if (msg[3] > info->ifcfg.wide_max_size)
 				msg[3] = info->ifcfg.wide_max_size;
 
@@ -542,7 +590,7 @@
 			res = wide;
 			break;
 
-		/* We initiated the wide data transfer negociation,
+		/* We initiated the wide data transfer negotiation,
 		 * and have successfully received a response from the
 		 * target.  The synchronous transfer agreement has been
 		 * reached.  Note: if the values returned are out of our
@@ -567,7 +615,7 @@
 		break;
 
 	case reject:
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_flush(&info->scsi.msgs);
 		msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
@@ -586,13 +634,14 @@
  * Params  : info              - interface's local pointer to update
  *           bytes_transferred - number of bytes transferred
  */
-static void
-fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
+static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
 {
 	Scsi_Pointer *SCp = &info->scsi.SCp;
 
 	fas216_checkmagic(info);
 
+	BUG_ON(bytes_transferred < 0);
+
 	info->SCpnt->request_bufflen -= bytes_transferred;
 
 	while (bytes_transferred != 0) {
@@ -623,8 +672,7 @@
  *           direction - direction to transfer data (DMA_OUT/DMA_IN)
  * Notes   : this is incredibly slow
  */
-static void
-fas216_pio(FAS216_Info *info, fasdmadir_t direction)
+static void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
 {
 	fas216_checkmagic(info);
 
@@ -634,53 +682,94 @@
 		put_next_SCp_byte(&info->scsi.SCp, inb(REG_FF(info)));
 }
 
+static void fas216_cleanuptransfer(FAS216_Info *info)
+{
+	unsigned long total, residual, fifo;
+
+	if (info->dma.transfer_type == fasdma_real_all)
+		total = info->SCpnt->request_bufflen;
+	else
+		total = info->scsi.SCp.this_residual;
+
+	residual = inb(REG_CTCL(info)) + (inb(REG_CTCM(info)) << 8) +
+		   (inb(REG_CTCH(info)) << 16);
+
+	fifo = inb(REG_CFIS(info)) & CFIS_CF;
+
+	fas216_log(info, LOG_BUFFER, "cleaning up from previous "
+		   "transfer: length 0x%06x, residual 0x%x, fifo %d",
+		   total, residual, fifo);
+
+	/*
+	 * If we were performing Data-Out, the transfer counter
+	 * counts down each time a byte is transferred by the
+	 * host to the FIFO.  This means we must include the
+	 * bytes left in the FIFO from the transfer counter.
+	 */
+	if (info->scsi.phase == PHASE_DATAOUT) {
+		residual += fifo;
+		fifo = 0;
+	}
+
+	if (info->dma.transfer_type != fasdma_none &&
+	    info->dma.transfer_type != fasdma_pio) {
+		fas216_updateptrs(info, total - residual);
+	}
+
+	/*
+	 * If we were performing Data-In, then the FIFO counter
+	 * contains the number of bytes not transferred via DMA
+	 * from the on-board FIFO.  Read them manually.
+	 */
+	if (info->scsi.phase == PHASE_DATAIN) {
+		while (fifo && info->scsi.SCp.ptr) {
+			*info->scsi.SCp.ptr = inb(REG_FF(info));
+			fas216_updateptrs(info, 1);
+			fifo--;
+		}
+	}
+
+	info->dma.transfer_type = fasdma_none;
+}
+
 /* Function: void fas216_starttransfer(FAS216_Info *info,
  *				       fasdmadir_t direction)
  * Purpose : Start a DMA/PIO transfer off of/on to card
  * Params  : info      - interface from which device disconnected from
  *           direction - transfer direction (DMA_OUT/DMA_IN)
  */
-static void
-fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo)
+static void fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction)
 {
 	fasdmatype_t dmatype;
+	int phase = (direction == DMA_OUT) ? PHASE_DATAOUT : PHASE_DATAIN;
 
 	fas216_checkmagic(info);
 
-	info->scsi.phase = (direction == DMA_OUT) ?
-				PHASE_DATAOUT : PHASE_DATAIN;
+	if (phase != info->scsi.phase) {
+		info->scsi.phase = phase;
 
-	if (info->dma.transfer_type != fasdma_none &&
-	    info->dma.transfer_type != fasdma_pio) {
-		unsigned long total, residual;
-
-		if (info->dma.transfer_type == fasdma_real_all)
-			total = info->SCpnt->request_bufflen;
-		else
-			total = info->scsi.SCp.this_residual;
-
-		residual = (inb(REG_CFIS(info)) & CFIS_CF) +
-			    inb(REG_CTCL(info)) +
-			    (inb(REG_CTCM(info)) << 8) +
-			    (inb(REG_CTCH(info)) << 16);
-		fas216_updateptrs(info, total - residual);
+		if (direction == DMA_OUT)
+			fas216_cmd(info, CMD_FLUSHFIFO);
+	} else {
+		fas216_cleanuptransfer(info);
 	}
-	info->dma.transfer_type = fasdma_none;
+
+	fas216_log(info, LOG_BUFFER,
+		   "starttransfer: buffer %p length 0x%06x reqlen 0x%06x",
+		   info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
+		   info->SCpnt->request_bufflen);
 
 	if (!info->scsi.SCp.ptr) {
-		printk("scsi%d.%c: null buffer passed to "
-			"fas216_starttransfer\n", info->host->host_no,
-			fas216_target(info));
+		fas216_log(info, LOG_ERROR, "null buffer passed to "
+			   "fas216_starttransfer");
+		print_SCp(&info->scsi.SCp, "SCp: ", "\n");
+		print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n");
 		return;
 	}
 
-	/* flush FIFO */
-	if (flush_fifo)
-		outb(CMD_FLUSHFIFO, REG_CMD(info));
-
 	/*
-	 * Default to PIO mode or DMA mode if we have a synchronous
-	 * transfer agreement.
+	 * Default to PIO mode or DMA mode if we have
+	 * a synchronous transfer agreement.
 	 */
 	if (info->device[info->SCpnt->target].sof && info->dma.setup)
 		dmatype = fasdma_real_all;
@@ -694,41 +783,45 @@
 
 	switch (dmatype) {
 	case fasdma_pio:
+		fas216_log(info, LOG_BUFFER, "PIO transfer");
 		outb(0, REG_SOF(info));
 		outb(info->scsi.async_stp, REG_STP(info));
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO);
 		fas216_pio(info, direction);
 		break;
 
 	case fasdma_pseudo:
+		fas216_log(info, LOG_BUFFER, "pseudo transfer");
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
 		info->dma.pseudo(info->host, &info->scsi.SCp,
 				 direction, info->SCpnt->transfersize);
 		break;
 
 	case fasdma_real_block:
+		fas216_log(info, LOG_BUFFER, "block dma transfer");
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
 		break;
 
 	case fasdma_real_all:
+		fas216_log(info, LOG_BUFFER, "total dma transfer");
 		outb(info->SCpnt->request_bufflen, REG_STCL(info));
 		outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info));
 		outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info));
-		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
 		break;
 
 	default:
-		printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n",
-		       info->host->host_no, fas216_target(info));
+		fas216_log(info, LOG_BUFFER | LOG_ERROR,
+			   "invalid FAS216 DMA type");
 		break;
 	}
 }
@@ -737,51 +830,49 @@
  * Purpose : Stop a DMA transfer onto / off of the card
  * Params  : info      - interface from which device disconnected from
  */
-static void
-fas216_stoptransfer(FAS216_Info *info)
+static void fas216_stoptransfer(FAS216_Info *info)
 {
 	fas216_checkmagic(info);
 
-	if (info->dma.transfer_type != fasdma_none &&
-	    info->dma.transfer_type != fasdma_pio) {
-		unsigned long total, residual;
+	if ((info->dma.transfer_type == fasdma_real_all ||
+	     info->dma.transfer_type == fasdma_real_block) &&
+	    info->dma.stop)
+		info->dma.stop(info->host, &info->scsi.SCp);
 
-		if ((info->dma.transfer_type == fasdma_real_all ||
-		     info->dma.transfer_type == fasdma_real_block) &&
-		    info->dma.stop)
-			info->dma.stop(info->host, &info->scsi.SCp);
+	fas216_cleanuptransfer(info);
 
-		if (info->dma.transfer_type == fasdma_real_all)
-			total = info->SCpnt->request_bufflen;
-		else
-			total = info->scsi.SCp.this_residual;
-
-		residual = (inb(REG_CFIS(info)) & CFIS_CF) +
-			    inb(REG_CTCL(info)) +
-			    (inb(REG_CTCM(info)) << 8) +
-			    (inb(REG_CTCH(info)) << 16);
-		fas216_updateptrs(info, total - residual);
-		info->dma.transfer_type = fasdma_none;
-	}
 	if (info->scsi.phase == PHASE_DATAOUT)
-		outb(CMD_FLUSHFIFO, REG_CMD(info));
+		fas216_cmd(info, CMD_FLUSHFIFO);
+}
+
+static void fas216_aborttransfer(FAS216_Info *info)
+{
+	fas216_checkmagic(info);
+
+	if ((info->dma.transfer_type == fasdma_real_all ||
+	     info->dma.transfer_type == fasdma_real_block) &&
+	    info->dma.stop)
+		info->dma.stop(info->host, &info->scsi.SCp);
+
+	info->dma.transfer_type = fasdma_none;
+	fas216_cmd(info, CMD_FLUSHFIFO);
 }
 
 /* Function: void fas216_disconnected_intr(FAS216_Info *info)
  * Purpose : handle device disconnection
  * Params  : info - interface from which device disconnected from
  */
-static void
-fas216_disconnect_intr(FAS216_Info *info)
+static void fas216_disconnect_intr(FAS216_Info *info)
 {
 	fas216_checkmagic(info);
 
-#ifdef DEBUG_CONNECT
-	printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no,
-		fas216_target(info), info->scsi.phase);
-#endif
+	fas216_log(info, LOG_CONNECT, "disconnect phase=%02x",
+		   info->scsi.phase);
+
 	msgqueue_flush(&info->scsi.msgs);
 
+	fas216_cmd(info, CMD_ENABLESEL);
+
 	switch (info->scsi.phase) {
 	case PHASE_SELECTION:			/* while selecting - no target		*/
 	case PHASE_SELSTEPS:
@@ -789,7 +880,6 @@
 		break;
 
 	case PHASE_MSGIN_DISCONNECT:		/* message in - disconnecting		*/
-		outb(CMD_ENABLESEL, REG_CMD(info));
 		info->scsi.disconnectable = 1;
 		info->scsi.reconnected.tag = 0;
 		info->scsi.phase = PHASE_IDLE;
@@ -841,19 +931,16 @@
 			info->device[SCpnt->target].sync_state = neg_wait;
 	}
 
-#ifdef DEBUG_CONNECT
-	printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no,
-		fas216_target(info), info->scsi.phase);
-#endif
+	fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase);
 
 	if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) {
 		printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
 			info->host->host_no);
-		outb(CMD_SETATN, REG_CMD(info));
-		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_flush(&info->scsi.msgs);
 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
+		fas216_cmd(info, CMD_MSGACCEPTED);
 		return;
 	}
 
@@ -877,11 +964,11 @@
 		 * Something went wrong - send an initiator error to
 		 * the target.
 		 */
-		outb(CMD_SETATN, REG_CMD(info));
-		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_flush(&info->scsi.msgs);
 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
+		fas216_cmd(info, CMD_MSGACCEPTED);
 		return;
 	}
 
@@ -903,6 +990,9 @@
 	info->scsi.reconnected.lun    = identify_msg;
 	info->scsi.reconnected.tag    = 0;
 
+	/* set up for synchronous transfers */
+	fas216_set_sync(info, target);
+
 	ok = 0;
 	if (info->scsi.disconnectable && info->SCpnt &&
 	    info->SCpnt->target == target && info->SCpnt->lun == identify_msg)
@@ -922,12 +1012,12 @@
 		 * record of this command, we can't send
 		 * an INITIATOR DETECTED ERROR message.
 		 */
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
 	}
 
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
+	fas216_cmd(info, CMD_MSGACCEPTED);
 }
 
 /* Function: void fas216_finish_reconnect(FAS216_Info *info)
@@ -939,28 +1029,20 @@
 {
 	fas216_checkmagic(info);
 
-#ifdef DEBUG_CONNECT
-	printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n",
+	fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x",
 		info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,
 		info->scsi.reconnected.target, info->scsi.reconnected.lun,
 		info->scsi.reconnected.tag);
-#endif
 
 	if (info->scsi.disconnectable && info->SCpnt) {
 		info->scsi.disconnectable = 0;
 		if (info->SCpnt->target == info->scsi.reconnected.target &&
 		    info->SCpnt->lun    == info->scsi.reconnected.lun &&
 		    info->SCpnt->tag    == info->scsi.reconnected.tag) {
-#ifdef DEBUG_CONNECT
-			printk("scsi%d.%c: reconnected",
-				info->host->host_no, fas216_target(info));
-#endif
+			fas216_log(info, LOG_CONNECT, "reconnected");
 		} else {
 			queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
-#ifdef DEBUG_CONNECT
-			printk("scsi%d.%c: had to move command to disconnected queue\n",
-				info->host->host_no, fas216_target(info));
-#endif
+			fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue");
 			info->SCpnt = NULL;
 		}
 	}
@@ -969,20 +1051,19 @@
 					info->scsi.reconnected.target,
 					info->scsi.reconnected.lun,
 					info->scsi.reconnected.tag);
-#ifdef DEBUG_CONNECT
-		printk("scsi%d.%c: had to get command",
-			info->host->host_no, fas216_target(info));
-#endif
+		fas216_log(info, LOG_CONNECT, "had to get command");
 	}
 	if (!info->SCpnt) {
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_flush(&info->scsi.msgs);
+
 #if 0
 		if (info->scsi.reconnected.tag)
 			msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag);
 		else
 #endif
 			msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
+
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
 		info->scsi.aborting = 1;
 	} else {
@@ -990,122 +1071,14 @@
 		 * Restore data pointer from SAVED data pointer
 		 */
 		info->scsi.SCp = info->SCpnt->SCp;
-#ifdef DEBUG_CONNECT
-		printk(", data pointers: [%p, %X]",
+		fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]",
 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
-#endif
 	}
-#ifdef DEBUG_CONNECT
-	printk("\n");
-#endif
 }
 
-static int fas216_wait_cmd(FAS216_Info *info, int cmd)
-{
-	int tout;
-	int stat;
-
-	outb(cmd, REG_CMD(info));
-
-	for (tout = 1000; tout; tout -= 1) {
-		stat = inb(REG_STAT(info));
-		if (stat & STAT_INT)
-			break;
-		udelay(1);
-	}
-
-	return stat;
-}
-
-static int fas216_get_msg_byte(FAS216_Info *info)
+static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen)
 {
-	int stat;
-
-	stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
-
-	if ((stat & STAT_INT) == 0)
-		goto timedout;
-
-	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
-		goto unexpected_phase_change;
-
-	inb(REG_INST(info));
-
-	stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
-
-	if ((stat & STAT_INT) == 0)
-		goto timedout;
-
-	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
-		goto unexpected_phase_change;
-
-	inb(REG_INST(info));
-
-	return inb(REG_FF(info));
-
-timedout:
-	printk("scsi%d.%c: timed out waiting for message byte\n",
-		info->host->host_no, fas216_target(info));
-	return -1;
-
-unexpected_phase_change:
-	printk("scsi%d.%c: unexpected phase change: status = %02X\n",
-		info->host->host_no, fas216_target(info), stat);
-
-	return -2;
-}
-
-/* Function: void fas216_message(FAS216_Info *info)
- * Purpose : handle a function done interrupt from FAS216 chip
- * Params  : info - interface which caused function done interrupt
- */
-static void fas216_message(FAS216_Info *info)
-{
-	unsigned char *message = info->scsi.message;
-	unsigned int msglen = 1, i;
-	int msgbyte = 0;
-
-	fas216_checkmagic(info);
-
-	message[0] = inb(REG_FF(info));
-
-	if (message[0] == EXTENDED_MESSAGE) {
-		msgbyte = fas216_get_msg_byte(info);
-
-		if (msgbyte >= 0) {
-			message[1] = msgbyte;
-
-			for (msglen = 2; msglen < message[1] + 2; msglen++) {
-				msgbyte = fas216_get_msg_byte(info);
-
-				if (msgbyte >= 0)
-					message[msglen] = msgbyte;
-				else
-					break;
-			}
-		}
-	}
-
-	info->scsi.msglen = msglen;
-
-#ifdef DEBUG_MESSAGES
-	{
-		int i;
-
-		printk("scsi%d.%c: message in: ",
-			info->host->host_no, fas216_target(info));
-		for (i = 0; i < msglen; i++)
-			printk("%02X ", message[i]);
-		printk("\n");
-	}
-#endif
-
-	if (info->scsi.phase == PHASE_RECONNECTED) {
-		if (message[0] == SIMPLE_QUEUE_TAG)
-			info->scsi.reconnected.tag = message[1];
-		fas216_finish_reconnect(info);
-		info->scsi.phase = PHASE_MSGIN;
-	}
+	int i;
 
 	switch (message[0]) {
 	case COMMAND_COMPLETE:
@@ -1131,11 +1104,9 @@
 		 */
 		info->SCpnt->SCp = info->scsi.SCp;
 		info->SCpnt->SCp.sent_command = 0;
-#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
-		printk("scsi%d.%c: save data pointers: [%p, %X]\n",
-			info->host->host_no, fas216_target(info),
+		fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
+			"save data pointers: [%p, %X]",
 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
-#endif
 		break;
 
 	case RESTORE_POINTERS:
@@ -1146,11 +1117,9 @@
 		 * Restore current data pointer from SAVED data pointer
 		 */
 		info->scsi.SCp = info->SCpnt->SCp;
-#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
-		printk("scsi%d.%c: restore data pointers: [%p, %X]\n",
-			info->host->host_no, fas216_target(info),
+		fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
+			"restore data pointers: [%p, 0x%x]",
 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
-#endif
 		break;
 
 	case DISCONNECT:
@@ -1174,8 +1143,7 @@
 			break;
 
 		default:
-			printk("scsi%d.%c: reject, last message %04X\n",
-				info->host->host_no, fas216_target(info),
+			fas216_log(info, 0, "reject, last message 0x%04x",
 				fas216_get_last_msg(info, info->scsi.msgin_fifo));
 		}
 		break;
@@ -1188,9 +1156,7 @@
 			goto unrecognised;
 
 		/* handled above - print a warning since this is untested */
-		printk("scsi%d.%c: reconnect queue tag %02X\n",
-			info->host->host_no, fas216_target(info),
-			message[1]);
+		fas216_log(info, 0, "reconnect queue tag 0x%02x", message[1]);
 		break;
 
 	case EXTENDED_MESSAGE:
@@ -1198,11 +1164,11 @@
 			goto unrecognised;
 
 		switch (message[2]) {
-		case EXTENDED_SDTR:	/* Sync transfer negociation request/reply */
+		case EXTENDED_SDTR:	/* Sync transfer negotiation request/reply */
 			fas216_handlesync(info, message);
 			break;
 
-		case EXTENDED_WDTR:	/* Wide transfer negociation request/reply */
+		case EXTENDED_WDTR:	/* Wide transfer negotiation request/reply */
 			fas216_handlewide(info, message);
 			break;
 
@@ -1214,12 +1180,10 @@
 	default:
 		goto unrecognised;
 	}
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
 	return;
 
 unrecognised:
-	printk("scsi%d.%c: unrecognised message, rejecting\n",
-		info->host->host_no, fas216_target(info));
+	fas216_log(info, 0, "unrecognised message, rejecting");
 	printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));
 	for (i = 0; i < msglen; i++)
 		printk("%s%02X", i & 31 ? " " : "\n  ", message[i]);
@@ -1230,14 +1194,138 @@
 	 * I can't use SETATN since the chip gives me an
 	 * invalid command interrupt when I do.  Weird.
 	 */
-outb(CMD_NOP, REG_CMD(info));
+fas216_cmd(info, CMD_NOP);
 fas216_dumpstate(info);
-	outb(CMD_SETATN, REG_CMD(info));
+	fas216_cmd(info, CMD_SETATN);
 	msgqueue_flush(&info->scsi.msgs);
 	msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
 	info->scsi.phase = PHASE_MSGOUT_EXPECT;
 fas216_dumpstate(info);
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
+}
+
+static int fas216_wait_cmd(FAS216_Info *info, int cmd)
+{
+	int tout;
+	int stat;
+
+	fas216_cmd(info, cmd);
+
+	for (tout = 1000; tout; tout -= 1) {
+		stat = inb(REG_STAT(info));
+		if (stat & (STAT_INT|STAT_PARITYERROR))
+			break;
+		udelay(1);
+	}
+
+	return stat;
+}
+
+static int fas216_get_msg_byte(FAS216_Info *info)
+{
+	unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
+
+	if ((stat & STAT_INT) == 0)
+		goto timedout;
+
+	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
+		goto unexpected_phase_change;
+
+	inb(REG_INST(info));
+
+	stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
+
+	if ((stat & STAT_INT) == 0)
+		goto timedout;
+
+	if (stat & STAT_PARITYERROR)
+		goto parity_error;
+
+	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
+		goto unexpected_phase_change;
+
+	inb(REG_INST(info));
+
+	return inb(REG_FF(info));
+
+timedout:
+	fas216_log(info, LOG_ERROR, "timed out waiting for message byte");
+	return -1;
+
+unexpected_phase_change:
+	fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat);
+	return -2;
+
+parity_error:
+	fas216_log(info, LOG_ERROR, "parity error during message in phase");
+	return -3;
+}
+
+/* Function: void fas216_message(FAS216_Info *info)
+ * Purpose : handle a function done interrupt from FAS216 chip
+ * Params  : info - interface which caused function done interrupt
+ */
+static void fas216_message(FAS216_Info *info)
+{
+	unsigned char *message = info->scsi.message;
+	unsigned int msglen = 1;
+	int msgbyte = 0;
+
+	fas216_checkmagic(info);
+
+	message[0] = inb(REG_FF(info));
+
+	if (message[0] == EXTENDED_MESSAGE) {
+		msgbyte = fas216_get_msg_byte(info);
+
+		if (msgbyte >= 0) {
+			message[1] = msgbyte;
+
+			for (msglen = 2; msglen < message[1] + 2; msglen++) {
+				msgbyte = fas216_get_msg_byte(info);
+
+				if (msgbyte >= 0)
+					message[msglen] = msgbyte;
+				else
+					break;
+			}
+		}
+	}
+
+	if (msgbyte == -3)
+		goto parity_error;
+
+	info->scsi.msglen = msglen;
+
+#ifdef DEBUG_MESSAGES
+	{
+		int i;
+
+		printk("scsi%d.%c: message in: ",
+			info->host->host_no, fas216_target(info));
+		for (i = 0; i < msglen; i++)
+			printk("%02X ", message[i]);
+		printk("\n");
+	}
+#endif
+
+	if (info->scsi.phase == PHASE_RECONNECTED) {
+		if (message[0] == SIMPLE_QUEUE_TAG)
+			info->scsi.reconnected.tag = message[1];
+		fas216_finish_reconnect(info);
+		info->scsi.phase = PHASE_MSGIN;
+	}
+
+	fas216_parse_message(info, message, msglen);
+	fas216_cmd(info, CMD_MSGACCEPTED);
+	return;
+
+parity_error:
+	fas216_cmd(info, CMD_SETATN);
+	msgqueue_flush(&info->scsi.msgs);
+	msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR);
+	info->scsi.phase = PHASE_MSGOUT_EXPECT;
+	fas216_cmd(info, CMD_MSGACCEPTED);
+	return;
 }
 
 /* Function: void fas216_send_command(FAS216_Info *info)
@@ -1250,14 +1338,14 @@
 
 	fas216_checkmagic(info);
 
-	outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info));
-	outb(CMD_FLUSHFIFO, REG_CMD(info));
+	fas216_cmd(info, CMD_NOP|CMD_WITHDMA);
+	fas216_cmd(info, CMD_FLUSHFIFO);
 
 	/* load command */
 	for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)
 		outb(info->SCpnt->cmnd[i], REG_FF(info));
 
-	outb(CMD_TRANSFERINFO, REG_CMD(info));
+	fas216_cmd(info, CMD_TRANSFERINFO);
 
 	info->scsi.phase = PHASE_COMMAND;
 }
@@ -1273,7 +1361,7 @@
 
 	fas216_checkmagic(info);
 
-	outb(CMD_FLUSHFIFO, REG_CMD(info));
+	fas216_cmd(info, CMD_FLUSHFIFO);
 
 	if (tot_msglen) {
 		struct message *msg;
@@ -1291,7 +1379,7 @@
 	} else
 		outb(NOP, REG_FF(info));
 
-	outb(CMD_TRANSFERINFO, REG_CMD(info));
+	fas216_cmd(info, CMD_TRANSFERINFO);
 
 	info->scsi.phase = PHASE_MSGOUT;
 }
@@ -1306,10 +1394,9 @@
 {
 	fas216_checkmagic(info);
 
-#ifdef DEBUG_BUSSERVICE
-	printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",
-		info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
-#endif
+	fas216_log(info, LOG_BUSSERVICE,
+		   "bus service: stat=%02x ssr=%02x phase=%02x",
+		   stat, ssr, info->scsi.phase);
 
 	switch (info->scsi.phase) {
 	case PHASE_SELECTION:
@@ -1337,7 +1424,7 @@
 		break;
 	}
 
-	outb(CMD_NOP, REG_CMD(info));
+	fas216_cmd(info, CMD_NOP);
 
 #define STATE(st,ph) ((ph) << 3 | (st))
 	/* This table describes the legal SCSI state transitions,
@@ -1352,11 +1439,11 @@
 	case STATE(STAT_DATAIN, PHASE_MSGOUT):  /* Message Out  -> Data In      */
 	case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command      -> Data In      */
 	case STATE(STAT_DATAIN, PHASE_MSGIN):   /* Message In   -> Data In      */
-		fas216_starttransfer(info, DMA_IN, 0);
+		fas216_starttransfer(info, DMA_IN);
 		return;
 
 	case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out     -> Data Out     */
-		fas216_starttransfer(info, DMA_OUT, 0);
+		fas216_starttransfer(info, DMA_OUT);
 		return;
 
 						/* Reselmsgin   -> Data Out     */
@@ -1366,7 +1453,7 @@
 	case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out  -> Data Out     */
 	case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command      -> Data Out     */
 	case STATE(STAT_DATAOUT, PHASE_MSGIN):  /* Message In   -> Data Out     */
-		fas216_starttransfer(info, DMA_OUT, 1);
+		fas216_starttransfer(info, DMA_OUT);
 		return;
 
 						/* Reselmsgin   -> Status       */
@@ -1381,7 +1468,7 @@
 	case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
 	case STATE(STAT_STATUS, PHASE_MSGIN):   /* Message In   -> Status       */
 	status:
-		outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
+		fas216_cmd(info, CMD_INITCMDCOMPLETE);
 		info->scsi.phase = PHASE_STATUS;
 		return;
 
@@ -1392,8 +1479,8 @@
 	case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
 	case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
 		info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
-		outb(CMD_FLUSHFIFO, REG_CMD(info));
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		fas216_cmd(info, CMD_FLUSHFIFO);
+		fas216_cmd(info, CMD_TRANSFERINFO);
 		info->scsi.phase = PHASE_MSGIN;
 		return;
 
@@ -1401,7 +1488,7 @@
 	case STATE(STAT_MESGIN, PHASE_RECONNECTED):
 	case STATE(STAT_MESGIN, PHASE_MSGIN):
 		info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO);
 		return;
 
 						/* Reselmsgin   -> Command      */
@@ -1412,11 +1499,43 @@
 		fas216_send_command(info);
 		info->scsi.phase = PHASE_COMMAND;
 		return;
-						/* Selection    -> Message Out  */
+
+
+	/*
+	 * Selection    -> Message Out
+	 */
 	case STATE(STAT_MESGOUT, PHASE_SELECTION):
 		fas216_send_messageout(info, 1);
 		return;
-						/* Any          -> Message Out  */
+
+	/*
+	 * Message Out  -> Message Out
+	 */
+	case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
+	case STATE(STAT_MESGOUT, PHASE_MSGOUT):
+		/*
+		 * If we get another message out phase, this usually
+		 * means some parity error occurred.  Resend complete
+		 * set of messages.  If we have more than one byte to
+		 * send, we need to assert ATN again.
+		 */
+		if (info->device[info->SCpnt->target].parity_check) {
+			/*
+			 * We were testing... good, the device
+			 * supports parity checking.
+			 */
+			info->device[info->SCpnt->target].parity_check = 0;
+			info->device[info->SCpnt->target].parity_enabled = 1;
+			outb(info->scsi.cfg[0], REG_CNTL1(info));
+		}
+
+		if (msgqueue_msglength(&info->scsi.msgs) > 1)
+			fas216_cmd(info, CMD_SETATN);
+		/*FALLTHROUGH*/
+
+	/*
+	 * Any          -> Message Out
+	 */
 	case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
 		fas216_send_messageout(info, 0);
 		return;
@@ -1435,30 +1554,15 @@
 		printk(KERN_ERR "scsi%d.%c: "
 			"target trying to receive more command bytes\n",
 			info->host->host_no, fas216_target(info));
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		outb(15, REG_STCL(info));
 		outb(0, REG_STCM(info));
 		outb(0, REG_STCH(info));
-		outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info));
+		fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA);
 		msgqueue_flush(&info->scsi.msgs);
 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
 		return;
-
-						/* Selection    -> Message Out  */
-	case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
-	case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out  -> Message Out  */
-		/* If we get another message out phase, this
-		 * usually means some parity error occurred.
-		 * Resend complete set of messages.  If we have
-		 * more than 1 byte to send, we need to assert
-		 * ATN again.
-		 */
-		if (msgqueue_msglength(&info->scsi.msgs) > 1)
-			outb(CMD_SETATN, REG_CMD(info));
-
-		fas216_send_messageout(info, 0);
-		return;
 	}
 
 	if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
@@ -1466,11 +1570,11 @@
 			info->host->host_no, fas216_target(info),
 			fas216_bus_phase(stat));
 		msgqueue_flush(&info->scsi.msgs);
-		outb(CMD_SETATN, REG_CMD(info));
+		fas216_cmd(info, CMD_SETATN);
 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
 		info->scsi.aborting = 1;
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		fas216_cmd(info, CMD_TRANSFERINFO);
 		return;
 	}
 	printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
@@ -1481,9 +1585,7 @@
 	return;
 
 bad_is:
-	printk("scsi%d.%c: bus service at step %d?\n",
-		info->host->host_no, fas216_target(info),
-		ssr & IS_BITS);
+	fas216_log(info, 0, "bus service at step %d?", ssr & IS_BITS);
 	print_debug_list();
 
 	fas216_done(info, DID_ERROR);
@@ -1497,41 +1599,90 @@
  */
 static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
 {
-	int status, message;
+	unsigned int fifo_len = inb(REG_CFIS(info)) & CFIS_CF;
+	unsigned int status, message;
 
 	fas216_checkmagic(info);
 
-#ifdef DEBUG_FUNCTIONDONE
-	printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n",
-		info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
-#endif
+	fas216_log(info, LOG_FUNCTIONDONE,
+		   "function done: stat=%02x ssr=%02x phase=%02x",
+		   stat, ssr, info->scsi.phase);
+
 	switch (info->scsi.phase) {
 	case PHASE_STATUS:			/* status phase - read status and msg	*/
+		if (fifo_len != 2) {
+			fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len);
+		}
 		status = inb(REG_FF(info));
 		message = inb(REG_FF(info));
 		info->scsi.SCp.Message = message;
 		info->scsi.SCp.Status = status;
 		info->scsi.phase = PHASE_DONE;
-		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		fas216_cmd(info, CMD_MSGACCEPTED);
 		break;
 
 	case PHASE_IDLE:			/* reselected?				*/
 	case PHASE_MSGIN:			/* message in phase			*/
 	case PHASE_RECONNECTED:			/* reconnected command			*/
 		if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
-			info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
+			info->scsi.msgin_fifo = fifo_len;
 			fas216_message(info);
 			break;
 		}
 
 	default:
-		printk("scsi%d.%c: internal phase %s for function done?"
-			"  What do I do with this?\n",
-			info->host->host_no, fas216_target(info),
-			fas216_drv_phase(info));
+		fas216_log(info, 0, "internal phase %s for function done?"
+			"  What do I do with this?",
+			fas216_target(info), fas216_drv_phase(info));
 	}
 }
 
+static void fas216_bus_reset(FAS216_Info *info)
+{
+	neg_t sync_state, wide_state;
+	int i;
+
+	msgqueue_flush(&info->scsi.msgs);
+
+	info->scsi.reconnected.target = 0;
+	info->scsi.reconnected.lun = 0;
+	info->scsi.reconnected.tag = 0;
+
+	if (info->ifcfg.wide_max_size == 0)
+		wide_state = neg_invalid;
+	else
+#ifdef SCSI2_WIDE
+		wide_state = neg_wait;
+#else
+		wide_state = neg_invalid;
+#endif
+
+	if (info->host->dma_channel == NO_DMA || !info->dma.setup)
+		sync_state = neg_invalid;
+	else
+#ifdef SCSI2_SYNC
+		sync_state = neg_wait;
+#else
+		sync_state = neg_invalid;
+#endif
+
+	info->scsi.phase = PHASE_IDLE;
+	info->SCpnt = NULL; /* bug! */
+
+	for (i = 0; i < 8; i++) {
+		info->device[i].disconnect_ok	= info->ifcfg.disconnect_ok;
+		info->device[i].sync_state	= sync_state;
+		info->device[i].wide_state	= wide_state;
+		info->device[i].period		= info->ifcfg.asyncperiod / 4;
+		info->device[i].stp		= info->scsi.async_stp;
+		info->device[i].sof		= 0;
+		info->device[i].wide_xfer	= 0;
+	}
+
+	info->rst_bus_status = 1;
+	wake_up(&info->eh_wait);
+}
+
 /* Function: void fas216_intr(struct Scsi_Host *instance)
  * Purpose : handle interrupts from the interface to progress a command
  * Params  : instance - interface to service
@@ -1551,11 +1702,13 @@
 
 	if (stat & STAT_INT) {
 		if (isr & INST_BUSRESET) {
-			printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no);
-			scsi_report_bus_reset(instance, 0);
+			fas216_log(info, 0, "bus reset detected");
+			fas216_bus_reset(info);
+			scsi_report_bus_reset(info->host, 0);
 		} else if (isr & INST_ILLEGALCMD) {
-			printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no);
+			fas216_log(info, LOG_ERROR, "illegal command given\n");
 			fas216_dumpstate(info);
+			print_debug_list();
 		} else if (isr & INST_DISCONNECT)
 			fas216_disconnect_intr(info);
 		else if (isr & INST_RESELECTED)		/* reselected			*/
@@ -1565,108 +1718,123 @@
 		else if (isr & INST_FUNCDONE)		/* function done		*/
 			fas216_funcdone_intr(info, stat, ssr);
 		else
-		    	printk("scsi%d.%c: unknown interrupt received:"
-				" phase %s isr %02X ssr %02X stat %02X\n",
-				instance->host_no, fas216_target(info),
+		    	fas216_log(info, 0, "unknown interrupt received:"
+				" phase %s isr %02X ssr %02X stat %02X",
 				fas216_drv_phase(info), isr, ssr, stat);
 	}
 }
 
-/* Function: void fas216_kick(FAS216_Info *info)
- * Purpose : kick a command to the interface - interface should be idle
- * Params  : info - our host interface to kick
- * Notes   : Interrupts are always disabled!
- */
-static void fas216_kick(FAS216_Info *info)
+static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
 {
-	Scsi_Cmnd *SCpnt = NULL;
-	int tot_msglen, from_queue = 0, disconnect_ok;
+	int tot_msglen;
 
-	fas216_checkmagic(info);
+	/* following what the ESP driver says */
+	outb(0, REG_STCL(info));
+	outb(0, REG_STCM(info));
+	outb(0, REG_STCH(info));
+	fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
 
-	/*
-	 * Obtain the next command to process.
-	 */
-	do {
-		if (info->reqSCpnt) {
-			SCpnt = info->reqSCpnt;
-			info->reqSCpnt = NULL;
-			break;
-		}
+	/* flush FIFO */
+	fas216_cmd(info, CMD_FLUSHFIFO);
 
-		if (info->origSCpnt) {
-			SCpnt = info->origSCpnt;
-			info->origSCpnt = NULL;
-			break;
+	/* load bus-id and timeout */
+	outb(BUSID(SCpnt->target), REG_SDID(info));
+	outb(info->ifcfg.select_timeout, REG_STIM(info));
+
+	/* synchronous transfers */
+	fas216_set_sync(info, SCpnt->target);
+
+	tot_msglen = msgqueue_msglength(&info->scsi.msgs);
+
+#ifdef DEBUG_MESSAGES
+	{
+		struct message *msg;
+		int msgnr = 0, i;
+
+		printk("scsi%d.%c: message out: ",
+			info->host->host_no, '0' + SCpnt->target);
+		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+			printk("{ ");
+			for (i = 0; i < msg->length; i++)
+				printk("%02x ", msg->msg[i]);
+			printk("} ");
 		}
+		printk("\n");
+	}
+#endif
 
-		/* retrieve next command */
-		if (!SCpnt) {
-			SCpnt = queue_remove_exclude(&info->queues.issue,
-						     info->busyluns);
-			from_queue = 1;
-			break;
+	if (tot_msglen == 1 || tot_msglen == 3) {
+		/*
+		 * We have an easy message length to send...
+		 */
+		struct message *msg;
+		int msgnr = 0, i;
+
+		info->scsi.phase = PHASE_SELSTEPS;
+
+		/* load message bytes */
+		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+			for (i = 0; i < msg->length; i++)
+				outb(msg->msg[i], REG_FF(info));
+			msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
 		}
-	} while (0);
 
-	if (!SCpnt) /* no command pending - just exit */
-		return;
+		/* load command */
+		for (i = 0; i < SCpnt->cmd_len; i++)
+			outb(SCpnt->cmnd[i], REG_FF(info));
 
-	if (info->scsi.disconnectable && info->SCpnt) {
-		queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
-		info->scsi.disconnectable = 0;
-		info->SCpnt = NULL;
-		printk("scsi%d.%c: moved command to disconnected queue\n",
-			info->host->host_no, fas216_target(info));
+		if (tot_msglen == 1)
+			fas216_cmd(info, CMD_SELECTATN);
+		else
+			fas216_cmd(info, CMD_SELECTATN3);
+	} else {
+		/*
+		 * We have an unusual number of message bytes to send.
+		 *  Load first byte into fifo, and issue SELECT with ATN and
+		 *  stop steps.
+		 */
+		struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
+
+		outb(msg->msg[0], REG_FF(info));
+		msg->fifo = 1;
+
+		fas216_cmd(info, CMD_SELECTATNSTOP);
+	}
+}
+
+/*
+ * Decide whether we need to perform a parity test on this device.
+ * Can also be used to force parity error conditions during initial
+ * information transfer phase (message out) for test purposes.
+ */
+static int parity_test(FAS216_Info *info, int target)
+{
+#if 0
+	if (target == 3) {
+		info->device[3].parity_check = 0;
+		return 1;
 	}
+#endif
+	return info->device[target].parity_check;
+}
+
+static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+{
+	int disconnect_ok;
+
+	if (parity_test(info, SCpnt->target))
+		outb(info->scsi.cfg[0] | CNTL1_PTE, REG_CNTL1(info));
+	else
+		outb(info->scsi.cfg[0], REG_CNTL1(info));
 
 	/*
 	 * claim host busy
 	 */
 	info->scsi.phase = PHASE_SELECTION;
-	info->SCpnt = SCpnt;
 	info->scsi.SCp = SCpnt->SCp;
+	info->SCpnt = SCpnt;
 	info->dma.transfer_type = fasdma_none;
 
-#ifdef DEBUG_CONNECT
-	printk("scsi%d.%c: starting cmd %02X",
-		info->host->host_no, '0' + SCpnt->target,
-		SCpnt->cmnd[0]);
-#endif
-
-	if (from_queue) {
-#ifdef SCSI2_TAG
-		/*
-		 * tagged queuing - allocate a new tag to this command
-		 */
-		if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE &&
-		    SCpnt->cmnd[0] != INQUIRY) {
-		    SCpnt->device->current_tag += 1;
-			if (SCpnt->device->current_tag == 0)
-			    SCpnt->device->current_tag = 1;
-				SCpnt->tag = SCpnt->device->current_tag;
-		} else
-#endif
-			set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
-
-		info->stats.removes += 1;
-		switch (SCpnt->cmnd[0]) {
-		case WRITE_6:
-		case WRITE_10:
-		case WRITE_12:
-			info->stats.writes += 1;
-			break;
-		case READ_6:
-		case READ_10:
-		case READ_12:
-			info->stats.reads += 1;
-			break;
-		default:
-			info->stats.miscs += 1;
-			break;
-		}
-	}
-
 	/*
 	 * Don't allow request sense commands to disconnect.
 	 */
@@ -1710,14 +1878,68 @@
 #endif
 	} while (0);
 
+	__fas216_start_command(info, SCpnt);
+}
+
+static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+{
+#ifdef SCSI2_TAG
+	/*
+	 * tagged queuing - allocate a new tag to this command
+	 */
+	if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE &&
+	    SCpnt->cmnd[0] != INQUIRY) {
+	    SCpnt->device->current_tag += 1;
+		if (SCpnt->device->current_tag == 0)
+		    SCpnt->device->current_tag = 1;
+			SCpnt->tag = SCpnt->device->current_tag;
+	} else
+#endif
+		set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+
+	info->stats.removes += 1;
+	switch (SCpnt->cmnd[0]) {
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_12:
+		info->stats.writes += 1;
+		break;
+	case READ_6:
+	case READ_10:
+	case READ_12:
+		info->stats.reads += 1;
+		break;
+	default:
+		info->stats.miscs += 1;
+		break;
+	}
+}
+
+static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+{
+	struct message *msg;
+
+	/*
+	 * claim host busy
+	 */
+	info->scsi.phase = PHASE_SELECTION;
+	info->scsi.SCp = SCpnt->SCp;
+	info->SCpnt = SCpnt;
+	info->dma.transfer_type = fasdma_none;
+
+	fas216_log(info, LOG_ERROR, "sending bus device reset");
+
+	msgqueue_flush(&info->scsi.msgs);
+	msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET);
+
 	/* following what the ESP driver says */
 	outb(0, REG_STCL(info));
 	outb(0, REG_STCM(info));
 	outb(0, REG_STCH(info));
-	outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
+	fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
 
 	/* flush FIFO */
-	outb(CMD_FLUSHFIFO, REG_CMD(info));
+	fas216_cmd(info, CMD_FLUSHFIFO);
 
 	/* load bus-id and timeout */
 	outb(BUSID(SCpnt->target), REG_SDID(info));
@@ -1726,68 +1948,110 @@
 	/* synchronous transfers */
 	fas216_set_sync(info, SCpnt->target);
 
-	tot_msglen = msgqueue_msglength(&info->scsi.msgs);
+	msg = msgqueue_getmsg(&info->scsi.msgs, 0);
 
-#ifdef DEBUG_MESSAGES
-	{
-		struct message *msg;
-		int msgnr = 0, i;
+	outb(BUS_DEVICE_RESET, REG_FF(info));
+	msg->fifo = 1;
 
-		printk("scsi%d.%c: message out: ",
-			info->host->host_no, '0' + SCpnt->target);
-		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
-			printk("{ ");
-			for (i = 0; i < msg->length; i++)
-				printk("%02x ", msg->msg[i]);
-			printk("} ");
+	fas216_cmd(info, CMD_SELECTATNSTOP);
+}
+
+/* Function: void fas216_kick(FAS216_Info *info)
+ * Purpose : kick a command to the interface - interface should be idle
+ * Params  : info - our host interface to kick
+ * Notes   : Interrupts are always disabled!
+ */
+static void fas216_kick(FAS216_Info *info)
+{
+	Scsi_Cmnd *SCpnt = NULL;
+#define TYPE_OTHER	0
+#define TYPE_RESET	1
+#define TYPE_QUEUE	2
+	int where_from = TYPE_OTHER;
+
+	fas216_checkmagic(info);
+
+	/*
+	 * Obtain the next command to process.
+	 */
+	do {
+		if (info->rstSCpnt) {
+			SCpnt = info->rstSCpnt;
+			/* don't remove it */
+			where_from = TYPE_RESET;
+			break;
 		}
-		printk("\n");
-	}
-#endif
 
-	if (tot_msglen == 1 || tot_msglen == 3) {
-		/*
-		 * We have an easy message length to send...
-		 */
-		struct message *msg;
-		int msgnr = 0, i;
+		if (info->reqSCpnt) {
+			SCpnt = info->reqSCpnt;
+			info->reqSCpnt = NULL;
+			break;
+		}
 
-		info->scsi.phase = PHASE_SELSTEPS;
+		if (info->origSCpnt) {
+			SCpnt = info->origSCpnt;
+			info->origSCpnt = NULL;
+			break;
+		}
 
-		/* load message bytes */
-		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
-			for (i = 0; i < msg->length; i++)
-				outb(msg->msg[i], REG_FF(info));
-			msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
+		/* retrieve next command */
+		if (!SCpnt) {
+			SCpnt = queue_remove_exclude(&info->queues.issue,
+						     info->busyluns);
+			where_from = TYPE_QUEUE;
+			break;
 		}
+	} while (0);
 
-		/* load command */
-		for (i = 0; i < SCpnt->cmd_len; i++)
-			outb(SCpnt->cmnd[i], REG_FF(info));
+	if (!SCpnt) /* no command pending - just exit */
+		return;
 
-		if (tot_msglen == 1)
-			outb(CMD_SELECTATN, REG_CMD(info));
-		else
-			outb(CMD_SELECTATN3, REG_CMD(info));
-	} else {
-		/*
-		 * We have an unusual number of message bytes to send.
-		 *  Load first byte into fifo, and issue SELECT with ATN and
-		 *  stop steps.
-		 */
-		struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
+	if (info->scsi.disconnectable && info->SCpnt) {
+		fas216_log(info, LOG_CONNECT,
+			"moved command for %d to disconnected queue",
+			info->SCpnt->target);
+		queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
+		info->scsi.disconnectable = 0;
+		info->SCpnt = NULL;
+	}
 
-		outb(msg->msg[0], REG_FF(info));
-		msg->fifo = 1;
+#if defined(DEBUG_CONNECT) || defined(DEBUG_MESSAGES)
+	printk("scsi%d.%c: starting ",
+		info->host->host_no, '0' + SCpnt->target);
+	print_command(SCpnt->cmnd);
+#endif
 
-		outb(CMD_SELECTATNSTOP, REG_CMD(info));
+	switch (where_from) {
+	case TYPE_QUEUE:
+		fas216_allocate_tag(info, SCpnt);
+	case TYPE_OTHER:
+		fas216_start_command(info, SCpnt);
+		break;
+	case TYPE_RESET:
+		fas216_do_bus_device_reset(info, SCpnt);
+		break;
 	}
 
-#ifdef DEBUG_CONNECT
-	printk(", data pointers [%p, %X]\n",
+	fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]",
 		info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
-#endif
-	/* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */
+
+	/*
+	 * should now get either DISCONNECT or
+	 * (FUNCTION DONE with BUS SERVICE) interrupt
+	 */
+}
+
+/*
+ * Clean up from issuing a BUS DEVICE RESET message to a device.
+ */
+static void
+fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
+{
+	fas216_log(info, LOG_ERROR, "fas216 device reset complete");
+
+	info->rstSCpnt = NULL;
+	info->rst_dev_status = 1;
+	wake_up(&info->eh_wait);
 }
 
 /* Function: void fas216_rq_sns_done(info, SCpnt, result)
@@ -1799,11 +2063,9 @@
 static void
 fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
 {
-#ifdef DEBUG_CONNECT
-	printk("scsi%d.%c: request sense complete, result=%04X%02X%02X\n",
-		info->host->host_no, '0' + SCpnt->target, result,
-		SCpnt->SCp.Message, SCpnt->SCp.Status);
-#endif
+	fas216_log(info, LOG_CONNECT,
+		   "request sense complete, result=0x%04x%02x%02x",
+		   result, SCpnt->SCp.Message, SCpnt->SCp.Status);
 
 	if (result != DID_OK || SCpnt->SCp.Status != GOOD)
 		/*
@@ -1812,7 +2074,8 @@
 		 * confuse the higher levels.
 		 */
 		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-
+//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->target);
+//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
 	/*
 	 * Note that we don't set SCpnt->result, since that should
 	 * reflect the status of the command that we were asked by
@@ -1850,10 +2113,11 @@
 		goto done;
 
 	/*
-	 * If the command returned CHECK_CONDITION status,
-	 * request the sense information.
+	 * If the command returned CHECK_CONDITION or COMMAND_TERMINATED
+	 * status, request the sense information.
 	 */
-	if (info->scsi.SCp.Status == CHECK_CONDITION)
+	if (status_byte(SCpnt->result) == CHECK_CONDITION ||
+	    status_byte(SCpnt->result) == COMMAND_TERMINATED)
 		goto request_sense;
 
 	/*
@@ -1888,8 +2152,15 @@
 		}
 	}
 
-done:	SCpnt->scsi_done(SCpnt);
-	return;
+done:
+	if (SCpnt->scsi_done) {
+		SCpnt->scsi_done(SCpnt);
+		return;
+	}
+
+	panic("scsi%d.H: null scsi_done function in fas216_done",
+		info->host->host_no);
+
 
 request_sense:
 	memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd));
@@ -1928,6 +2199,7 @@
 {
 	void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int);
 	Scsi_Cmnd *SCpnt;
+	unsigned long flags;
 
 	fas216_checkmagic(info);
 
@@ -1938,12 +2210,8 @@
 	info->SCpnt = NULL;
     	info->scsi.phase = PHASE_IDLE;
 
-	if (!SCpnt->scsi_done)
-		goto no_done;
-
 	if (info->scsi.aborting) {
-		printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n",
-			info->host->host_no, fas216_target(info));
+		fas216_log(info, 0, "uncaught abort - returning DID_ABORT");
 		result = DID_ABORT;
 		info->scsi.aborting = 0;
 	}
@@ -1966,21 +2234,23 @@
 	 * the sense information, fas216_kick will re-assert the busy
 	 * status.
 	 */
+	info->device[SCpnt->target].parity_check = 0;
 	clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
 
 	fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;
 	fn(info, SCpnt, result);
 
-	if (info->scsi.irq != NO_IRQ)
-		fas216_kick(info);
+	if (info->scsi.irq != NO_IRQ) {
+		spin_lock_irqsave(&info->host_lock, flags);
+		if (info->scsi.phase == PHASE_IDLE)
+			fas216_kick(info);
+		spin_unlock_irqrestore(&info->host_lock, flags);
+	}
 	return;
 
 no_command:
 	panic("scsi%d.H: null command in fas216_done",
 		info->host->host_no);
-no_done:
-	panic("scsi%d.H: null scsi_done function in fas216_done",
-		info->host->host_no);
 }
 
 /* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
@@ -1998,9 +2268,9 @@
 	fas216_checkmagic(info);
 
 #ifdef DEBUG_CONNECT
-	printk("scsi%d.%c: received queuable command (%p) %02X\n",
-		SCpnt->host->host_no, '0' + SCpnt->target,
-		SCpnt, SCpnt->cmnd[0]);
+	printk("scsi%d.H: received command for id %d (%p) ",
+		SCpnt->host->host_no, SCpnt->target, SCpnt);
+	print_command(SCpnt->cmnd);
 #endif
 
 	SCpnt->scsi_done = done;
@@ -2012,6 +2282,8 @@
 	info->stats.queues += 1;
 	SCpnt->tag = 0;
 
+	spin_lock(&info->host_lock);
+
 	/*
 	 * Add command into execute queue and let it complete under
 	 * whatever scheme we're using.
@@ -2022,8 +2294,14 @@
 	 * If we successfully added the command,
 	 * kick the interface to get it moving.
 	 */
-	if (result == 0 && (!info->SCpnt || info->scsi.disconnectable))
+	if (result == 0 && info->scsi.phase == PHASE_IDLE)
 		fas216_kick(info);
+	spin_unlock(&info->host_lock);
+
+#ifdef DEBUG_CONNECT
+	printk("scsi%d.H: queue %s\n", info->host->host_no,
+		result ? "failure" : "success");
+#endif
 
 	return result;
 }
@@ -2092,23 +2370,41 @@
 	return SCpnt->result;
 }
 
-enum res_abort {
-	res_failed,		/* unable to abort		*/
+/*
+ * Error handler timeout function.  Indicate that we timed out,
+ * and wake up any error handler process so it can continue.
+ */
+static void fas216_eh_timer(unsigned long data)
+{
+	FAS216_Info *info = (FAS216_Info *)data;
+
+	fas216_log(info, LOG_ERROR, "error handling timed out\n");
+
+	del_timer(&info->eh_timer);
+
+	if (info->rst_bus_status == 0)
+		info->rst_bus_status = -1;
+	if (info->rst_dev_status == 0)
+		info->rst_dev_status = -1;
+
+	wake_up(&info->eh_wait);
+}
+
+enum res_find {
+	res_failed,		/* not found			*/
 	res_success,		/* command on issue queue	*/
-	res_success_clear,	/* command marked tgt/lun busy	*/
 	res_hw_abort		/* command on disconnected dev	*/
 };
 
 /*
- * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+ * Prototype: enum res_find fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt)
  * Purpose  : decide how to abort a command
  * Params   : SCpnt - command to abort
  * Returns  : abort status
  */
-static enum res_abort
-fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
 {
-	enum res_abort res = res_failed;
+	enum res_find res = res_failed;
 
 	if (queue_remove_cmd(&info->queues.issue, SCpnt)) {
 		/*
@@ -2156,8 +2452,9 @@
 		 * been set.
 		 */
 		info->origSCpnt = NULL;
+		clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
 		printk("waiting for execution ");
-		res = res_success_clear;
+		res = res_success;
 	} else
 		printk("unknown ");
 
@@ -2179,22 +2476,15 @@
 
 	info->stats.aborts += 1;
 
+	printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no);
+	print_command(SCpnt->data_cmnd);
+
 	print_debug_list();
 	fas216_dumpstate(info);
-	fas216_dumpinfo(info);
 
-	printk(KERN_WARNING "scsi%d: abort ", info->host->host_no);
-
-	switch (fas216_do_abort(info, SCpnt)) {
-	/*
-	 * We managed to find the command and cleared it out.
-	 * We do not expect the command to be executing on the
-	 * target, but we have set the busylun bit.
-	 */
-	case res_success_clear:
-		printk("clear ");
-		clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+	printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt);
 
+	switch (fas216_find_command(info, SCpnt)) {
 	/*
 	 * We found the command, and cleared it out.  Either
 	 * the command is still known to be executing on the
@@ -2225,132 +2515,161 @@
 	return result;
 }
 
-/* Function: void fas216_reset_state(FAS216_Info *info)
- * Purpose : Initialise driver internal state
- * Params  : info - state to initialise
+/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the device associated with this command
+ * Params  : SCpnt - command specifing device to reset
+ * Returns : FAILED if unable to reset
+ * Notes   : We won't be re-entered, so we'll only have one device
+ *           reset on the go at one time.
  */
-static void fas216_reset_state(FAS216_Info *info)
+int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
 {
-	neg_t sync_state, wide_state;
-	int i;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	unsigned long flags;
+	int i, res = FAILED, target = SCpnt->target;
 
-	fas216_checkmagic(info);
+	fas216_log(info, LOG_ERROR, "device reset for target %d", target);
 
-	/*
-	 * Clear out all stale info in our state structure
-	 */
-	memset(info->busyluns, 0, sizeof(info->busyluns));
-	msgqueue_flush(&info->scsi.msgs);
-	info->scsi.reconnected.target = 0;
-	info->scsi.reconnected.lun = 0;
-	info->scsi.reconnected.tag = 0;
-	info->scsi.disconnectable = 0;
-	info->scsi.aborting = 0;
-	info->scsi.phase = PHASE_IDLE;
-	info->scsi.async_stp =
-			fas216_syncperiod(info, info->ifcfg.asyncperiod);
+	spin_lock_irqsave(&info->host_lock, flags);
 
-	if (info->ifcfg.wide_max_size == 0)
-		wide_state = neg_invalid;
-	else
-#ifdef SCSI2_WIDE
-		wide_state = neg_wait;
-#else
-		wide_state = neg_invalid;
-#endif
+	do {
+		/*
+		 * If we are currently connected to a device, and
+		 * it is the device we want to reset, there is
+		 * nothing we can do here.  Chances are it is stuck,
+		 * and we need a bus reset.
+		 */
+		if (info->SCpnt && !info->scsi.disconnectable &&
+		    info->SCpnt->target == SCpnt->target)
+			break;
 
-	if (info->host->dma_channel == NO_DMA || !info->dma.setup)
-		sync_state = neg_invalid;
-	else
-#ifdef SCSI2_SYNC
-		sync_state = neg_wait;
-#else
-		sync_state = neg_invalid;
-#endif
+		/*
+		 * We're going to be resetting this device.  Remove
+		 * all pending commands from the driver.  By doing
+		 * so, we guarantee that we won't touch the command
+		 * structures except to process the reset request.
+		 */
+		queue_remove_all_target(&info->queues.issue, target);
+		queue_remove_all_target(&info->queues.disconnected, target);
+		if (info->origSCpnt && info->origSCpnt->target == target)
+			info->origSCpnt = NULL;
+		if (info->reqSCpnt && info->reqSCpnt->target == target)
+			info->reqSCpnt = NULL;
+		for (i = 0; i < 8; i++)
+			clear_bit(target * 8 + i, info->busyluns);
 
-	for (i = 0; i < 8; i++) {
-		info->device[i].disconnect_ok	= info->ifcfg.disconnect_ok;
-		info->device[i].sync_state	= sync_state;
-		info->device[i].wide_state	= wide_state;
-		info->device[i].period		= info->ifcfg.asyncperiod / 4;
-		info->device[i].stp		= info->scsi.async_stp;
-		info->device[i].sof		= 0;
-		info->device[i].wide_xfer	= 0;
-	}
+		/*
+		 * Hijack this SCSI command structure to send
+		 * a bus device reset message to this device.
+		 */
+		SCpnt->host_scribble = (void *)fas216_devicereset_done;
 
-	/*
-	 * Drain all commands on disconnected queue
-	 */
-	while (queue_remove(&info->queues.disconnected) != NULL);
+		info->rst_dev_status = 0;
+		info->rstSCpnt = SCpnt;
 
-	/*
-	 * Remove executing commands.
-	 */
-	info->SCpnt     = NULL;
-	info->reqSCpnt  = NULL;
-	info->origSCpnt = NULL;
-}
+		if (info->scsi.phase == PHASE_IDLE)
+			fas216_kick(info);
 
-/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
- * Purpose : Reset the device associated with this command
- * Params  : SCpnt - command specifing device to reset
- * Returns : FAILED if unable to reset
- */
-int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
-{
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+		mod_timer(&info->eh_timer, 30 * HZ);
+		spin_unlock_irqrestore(&info->host_lock, flags);
 
-	printk("scsi%d.%c: %s: called\n",
-		info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
-	return FAILED;
+		/*
+		 * Wait up to 30 seconds for the reset to complete.
+		 */
+		wait_event(info->eh_wait, info->rst_dev_status);
+
+		del_timer_sync(&info->eh_timer);
+		spin_lock_irqsave(&info->host_lock, flags);
+		info->rstSCpnt = NULL;
+
+		if (info->rst_dev_status == 1)
+			res = SUCCESS;
+	} while (0);
+
+	SCpnt->host_scribble = NULL;
+	spin_unlock_irqrestore(&info->host_lock, flags);
+
+	fas216_log(info, LOG_ERROR, "device reset complete: %s\n",
+		   res == SUCCESS ? "success" : "failed");
+
+	return res;
 }
 
 /* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
  * Purpose : Reset the bus associated with the command
  * Params  : SCpnt - command specifing bus to reset
  * Returns : FAILED if unable to reset
- * Notes   : io_request_lock is taken, and irqs are disabled
+ * Notes   : Further commands are blocked.
  */
 int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
-	int result = FAILED;
+	unsigned long flags;
+	Scsi_Device *SDpnt;
 
 	fas216_checkmagic(info);
+	fas216_log(info, LOG_ERROR, "resetting bus");
 
 	info->stats.bus_resets += 1;
 
-	printk("scsi%d.%c: %s: resetting bus\n",
-		info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
+	spin_lock_irqsave(&info->host_lock, flags);
 
 	/*
-	 * Attempt to stop all activity on this interface.
+	 * Stop all activity on this interface.
 	 */
+	fas216_aborttransfer(info);
 	outb(info->scsi.cfg[2], REG_CNTL3(info));
-	fas216_stoptransfer(info);
 
 	/*
-	 * Clear any pending interrupts
+	 * Clear any pending interrupts.
 	 */
 	while (inb(REG_STAT(info)) & STAT_INT)
 		inb(REG_INST(info));
 
+	info->rst_bus_status = 0;
+
 	/*
-	 * Reset the SCSI bus
+	 * For each attached hard-reset device, clear out
+	 * all command structures.  Leave the running
+	 * command in place.
 	 */
-	outb(CMD_RESETSCSI, REG_CMD(info));
-	udelay(5);
+	for (SDpnt = info->host->host_queue; SDpnt; SDpnt = SDpnt->next) {
+		int i;
+
+		if (SDpnt->soft_reset)
+			continue;
+
+		queue_remove_all_target(&info->queues.issue, SDpnt->id);
+		queue_remove_all_target(&info->queues.disconnected, SDpnt->id);
+		if (info->origSCpnt && info->origSCpnt->target == SDpnt->id)
+			info->origSCpnt = NULL;
+		if (info->reqSCpnt && info->reqSCpnt->target == SDpnt->id)
+			info->reqSCpnt = NULL;
+		info->SCpnt = NULL;
+
+		for (i = 0; i < 8; i++)
+			clear_bit(SDpnt->id * 8 + i, info->busyluns);
+	}
 
 	/*
-	 * Clear reset interrupt
+	 * Reset the SCSI bus.  Device cleanup happens in
+	 * the interrupt handler.
 	 */
-	if (inb(REG_STAT(info)) & STAT_INT &&
-	    inb(REG_INST(info)) & INST_BUSRESET)
-		result = SUCCESS;
+	fas216_cmd(info, CMD_RESETSCSI);
 
-	fas216_reset_state(info);
+	mod_timer(&info->eh_timer, jiffies + HZ);
+	spin_unlock_irqrestore(&info->host_lock, flags);
 
-	return result;
+	/*
+	 * Wait one second for the interrupt.
+	 */
+	wait_event(info->eh_wait, info->rst_bus_status);
+	del_timer_sync(&info->eh_timer);
+
+	fas216_log(info, LOG_ERROR, "bus reset complete: %s\n",
+		   info->rst_bus_status == 1 ? "success" : "failed");
+
+	return info->rst_bus_status == 1 ? SUCCESS : FAILED;
 }
 
 /* Function: void fas216_init_chip(FAS216_Info *info)
@@ -2387,7 +2706,7 @@
 	/*
 	 * Reset the SCSI chip.
 	 */
-	outb(CMD_RESETCHIP, REG_CMD(info));
+	fas216_cmd(info, CMD_RESETCHIP);
 
 	/*
 	 * Ugly ugly ugly!
@@ -2396,13 +2715,13 @@
 	 * IRQs after the sleep.
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(25*HZ/100);
+	scsi_sleep(50 * HZ/100);
 	spin_lock_irq(info->host->host_lock);
 
 	/*
 	 * Release the SCSI reset.
 	 */
-	outb(CMD_NOP, REG_CMD(info));
+	fas216_cmd(info, CMD_NOP);
 
 	fas216_init_chip(info);
 
@@ -2509,6 +2828,44 @@
 	return TYPE_NCR53C9x;
 }
 
+/* Function: void fas216_reset_state(FAS216_Info *info)
+ * Purpose : Initialise driver internal state
+ * Params  : info - state to initialise
+ */
+static void fas216_reset_state(FAS216_Info *info)
+{
+	int i;
+
+	fas216_checkmagic(info);
+
+	fas216_bus_reset(info);
+
+	/*
+	 * Clear out all stale info in our state structure
+	 */
+	memset(info->busyluns, 0, sizeof(info->busyluns));
+	info->scsi.disconnectable = 0;
+	info->scsi.aborting = 0;
+
+	for (i = 0; i < 8; i++) {
+		info->device[i].parity_enabled	= 0;
+		info->device[i].parity_check	= 1;
+	}
+
+	/*
+	 * Drain all commands on disconnected queue
+	 */
+	while (queue_remove(&info->queues.disconnected) != NULL);
+
+	/*
+	 * Remove executing commands.
+	 */
+	info->SCpnt     = NULL;
+	info->reqSCpnt  = NULL;
+	info->rstSCpnt  = NULL;
+	info->origSCpnt = NULL;
+}
+
 /* Function: int fas216_init(struct Scsi_Host *instance)
  * Purpose : initialise FAS/NCR/AMD SCSI ic.
  * Params  : instance - a driver-specific filled-out structure
@@ -2519,12 +2876,22 @@
 	FAS216_Info *info = (FAS216_Info *)instance->hostdata;
 	int type;
 
-	info->magic_start = MAGIC;
-	info->magic_end   = MAGIC;
-	info->host        = instance;
-	info->scsi.cfg[0] = instance->this_id;
-	info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
-	info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB;
+	info->magic_start    = MAGIC;
+	info->magic_end      = MAGIC;
+	info->host           = instance;
+	info->scsi.cfg[0]    = instance->this_id | CNTL1_PERE;
+	info->scsi.cfg[1]    = CNTL2_ENF | CNTL2_S2FE;
+	info->scsi.cfg[2]    = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB;
+	info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
+
+	info->rst_dev_status = -1;
+	info->rst_bus_status = -1;
+	init_waitqueue_head(&info->eh_wait);
+	init_timer(&info->eh_timer);
+	info->eh_timer.data  = (unsigned long)info;
+	info->eh_timer.function = fas216_eh_timer;
+	
+	spin_lock_init(&info->host_lock);
 
 	memset(&info->stats, 0, sizeof(info->stats));
 
@@ -2561,7 +2928,7 @@
 	 * scsi standard says wait 250ms
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(25*HZ/100);
+	scsi_sleep(100*HZ/100);
 	spin_lock_irq(info->host->host_lock);
 
 	outb(info->scsi.cfg[0], REG_CNTL1(info));
@@ -2621,7 +2988,6 @@
 
 int fas216_print_host(FAS216_Info *info, char *buffer)
 {
-	
 	return sprintf(buffer,
 			"\n"
 			"Chip    : %s\n"
@@ -2634,8 +3000,9 @@
 
 int fas216_print_stats(FAS216_Info *info, char *buffer)
 {
-	return sprintf(buffer,
-			"\n"
+	char *p = buffer;
+
+	p += sprintf(p, "\n"
 			"Command Statistics:\n"
 			" Queued     : %u\n"
 			" Issued     : %u\n"
@@ -2652,6 +3019,8 @@
 			info->stats.writes,	 info->stats.miscs,
 			info->stats.disconnects, info->stats.aborts,
 			info->stats.bus_resets,	 info->stats.host_resets);
+
+	return p - buffer;
 }
 
 int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer)
@@ -2670,7 +3039,9 @@
 			     scd->tagged_queue ? "en" : "dis",
 			     scd->current_tag);
 
-	p += sprintf(p, "\n  Transfers : %d-bit ",
+	p += sprintf(p, "%s\n", dev->parity_enabled ? "parity" : "");
+
+	p += sprintf(p, "  Transfers : %d-bit ",
 		     8 << dev->wide_xfer);
 
 	if (dev->sof)
diff -Nru a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h
--- a/drivers/acorn/scsi/fas216.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/acorn/scsi/fas216.h	Sun Nov 17 20:30:16 2002
@@ -214,10 +214,22 @@
 
 typedef struct {
 	unsigned long		magic_start;
+	spinlock_t		host_lock;
 	struct Scsi_Host	*host;			/* host					*/
 	Scsi_Cmnd		*SCpnt;			/* currently processing command		*/
 	Scsi_Cmnd		*origSCpnt;		/* original connecting command		*/
 	Scsi_Cmnd		*reqSCpnt;		/* request sense command		*/
+	Scsi_Cmnd		*rstSCpnt;		/* reset command			*/
+	Scsi_Cmnd		*pending_SCpnt[8];	/* per-device pending commands		*/
+	int			next_pending;		/* next pending device			*/
+
+	/*
+	 * Error recovery
+	 */
+	wait_queue_head_t	eh_wait;
+	struct timer_list	eh_timer;
+	unsigned int		rst_dev_status;
+	unsigned int		rst_bus_status;
 
 	/* driver information */
 	struct {
@@ -281,6 +293,8 @@
 	/* per-device info */
 	struct fas216_device {
 		unsigned char	disconnect_ok:1;	/* device can disconnect		*/
+		unsigned char	parity_enabled:1;	/* parity checking enabled		*/
+		unsigned char	parity_check:1;		/* need to check parity checking	*/
 		unsigned char	period;			/* sync xfer period in (*4ns)		*/
 		unsigned char	stp;			/* synchronous transfer period		*/
 		unsigned char	sof;			/* synchronous offset register		*/
diff -Nru a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c
--- a/drivers/acorn/scsi/oak.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/acorn/scsi/oak.c	Sun Nov 17 20:30:02 2002
@@ -1,55 +1,14 @@
-#define AUTOSENSE
-/*#define PSEUDO_DMA*/
-
 /*
  * Oak Generic NCR5380 driver
  *
- * Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/*
- * Options :
- *
- * PARITY - enable parity checking.  Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- */
-
-/*
- * $Log: oak.c,v $
- * Revision 1.3  1998/05/03 20:45:37  alan
- * ARM SCSI update. This adds the eesox driver and massively updates the
- * Cumana driver. The folks who bought cumana arent anal retentive all
- * docs are secret weenies so now there are docs ..
- *
- * Revision 1.2  1998/03/08 05:49:48  davem
- * Merge to 2.1.89
- *
- * Revision 1.1  1998/02/23 02:45:27  davem
- * Merge to 2.1.88
- *
+ * Copyright 1995-2002, Russell King
  */
 
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <linux/blk.h>
 #include <linux/init.h>
 
@@ -60,6 +19,9 @@
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
 
+#define AUTOSENSE
+/*#define PSEUDO_DMA*/
+
 #define OAKSCSI_PUBLIC_RELEASE 1
 
 #define NCR5380_read(reg)		oakscsi_read(_instance, reg)
@@ -71,14 +33,9 @@
 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
 		      int length, int hostno, int inout);
 
-#define NCR5380_implementation_fields \
-	int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
+#define NCR5380_implementation_fields	int port, ctrl
+#define NCR5380_local_declare()		struct Scsi_Host *_instance
+#define NCR5380_setup(instance)		_instance = instance
 
 #define BOARD_NORMAL	0
 #define BOARD_NCR53C400	1
@@ -88,106 +45,9 @@
 #undef START_DMA_INITIATOR_RECEIVE_REG
 #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
 
-static const card_ids oakscsi_cids[] = {
-	{ MANU_OAK, PROD_OAK_SCSI },
-	{ 0xffff, 0xffff }
-};
-
-#define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
-#define OAK_IRQ(card)	  (IRQ_NONE)
-/*
- * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
- *
- * Purpose : initializes oak NCR5380 driver based on the
- *	command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
-static struct expansion_card *ecs[4];
-
-int oakscsi_detect(Scsi_Host_Template * tpnt)
+const char * oakscsi_info (struct Scsi_Host *spnt)
 {
-    int count = 0;
-    struct Scsi_Host *instance;
-
-    tpnt->proc_name = "oakscsi";
-
-    memset (ecs, 0, sizeof (ecs));
-
-    ecard_startfind ();
-
-    while(1) {
-        if ((ecs[count] = ecard_find(0, oakscsi_cids)) == NULL)
-            break;
-
-        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-	if (!instance)
-		break;
-        instance->io_port = OAK_ADDRESS(ecs[count]);
-        instance->irq = OAK_IRQ(ecs[count]);
-
-	NCR5380_init(instance, 0);
-	ecard_claim(ecs[count]);
-
-	instance->n_io_port = 255;
-	if (!request_region (instance->io_port, instance->n_io_port, "Oak SCSI")) {
-		ecard_release(ecs[count]);
-		scsi_unregister(instance);
-		break;
-	}
-
-	if (instance->irq != IRQ_NONE)
-	    if (request_irq(instance->irq, oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
-		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-		    instance->host_no, instance->irq);
-		instance->irq = IRQ_NONE;
-	    }
-
-	if (instance->irq != IRQ_NONE) {
-	    printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
-	    printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
-	}
-
-	printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-	if (instance->irq == IRQ_NONE)
-	    printk ("s disabled");
-	else
-	    printk (" %d", instance->irq);
-	printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-	    tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
-	printk("\nscsi%d:", instance->host_no);
-	NCR5380_print_options(instance);
-	printk("\n");
-
-	++count;
-    }
-#ifdef MODULE
-    if(count == 0)
-        printk("No oak scsi devices found\n");
-#endif
-    return count;
-}
-
-int oakscsi_release (struct Scsi_Host *shpnt)
-{
-	int i;
-
-	if (shpnt->irq != IRQ_NONE)
-		free_irq (shpnt->irq, NULL);
-	if (shpnt->io_port)
-		release_region (shpnt->io_port, shpnt->n_io_port);
-
-	for (i = 0; i < 4; i++)
-		if (shpnt->io_port == OAK_ADDRESS(ecs[i]))
-			ecard_release (ecs[i]);
-	return 0;
-}
-
-const char * oakscsi_info (struct Scsi_Host *spnt) {
-    return "";
+	return "";
 }
 
 #define STAT(p)   inw(p + 144)
@@ -255,37 +115,95 @@
 #include "../../scsi/NCR5380.c"
 
 static Scsi_Host_Template oakscsi_template = {
-	.module		= THIS_MODULE,
-	.proc_info	= oakscsi_proc_info,
-	.name		= "Oak 16-bit SCSI",
-	.detect		= oakscsi_detect,
-	.release	= oakscsi_release,
-	.info		= oakscsi_info,
-	.queuecommand	= oakscsi_queue_command,
+	.module			= THIS_MODULE,
+	.proc_info		= oakscsi_proc_info,
+	.name			= "Oak 16-bit SCSI",
+	.info			= oakscsi_info,
+	.queuecommand		= oakscsi_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
 	.eh_device_reset_handler= NCR5380_device_reset,
 	.eh_bus_reset_handler	= NCR5380_bus_reset,
 	.eh_host_reset_handler	= NCR5380_host_reset,
-	.can_queue	= 16,
-	.this_id	= 7,
-	.sg_tablesize	= SG_ALL,
-	.cmd_per_lun	= 2,
-	.use_clustering	= DISABLE_CLUSTERING
+	.can_queue		= 16,
+	.this_id		= 7,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 2,
+	.use_clustering		= DISABLE_CLUSTERING,
+	.proc_name		= "oakscsi",
 };
 
-static int __init oakscsi_init(void)
+static int __devinit
+oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-	scsi_register_host(&oakscsi_template);
-	if (oakscsi_template.present)
-		return 0;
+	struct Scsi_Host *host;
+	int ret = -ENOMEM;
+
+        host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
+	if (!host)
+		goto out;
+
+        host->io_port = ecard_address(ec, ECARD_MEMC, 0)
+        host->irq = IRQ_NONE;
+	host->n_io_port = 255;
 
-	scsi_unregister_host(&oakscsi_template);
-	return -ENODEV;
+	ret = -EBUSY;
+	if (!request_region (host->io_port, host->n_io_port, "Oak SCSI"))
+		goto unreg;
+
+	NCR5380_init(host, 0);
+
+	printk("scsi%d: at port 0x%08lx irqs disabled",
+		host->host_no, host->io_port);
+	printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
+	    tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
+	printk("\nscsi%d:", host->host_no);
+	NCR5380_print_options(host);
+	printk("\n");
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
+
+	release_region(host->io_port, host->n_io_port);
+ unreg:
+	scsi_unregister(host);
+ out:
+	return ret;
+}
+
+static void __devexit oakscsi_remove(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+
+	release_region(host->io_port, host->n_io_port);
+	scsi_unregister(host);
+}
+
+static const struct ecard_id oakscsi_cids[] = {
+	{ MANU_OAK, PROD_OAK_SCSI },
+	{ 0xffff, 0xffff }
+};
+
+static struct ecard_driver oakscsi_driver = {
+	.probe		= oakscsi_probe,
+	.remove		= __devexit_p(oakscsi_remove),
+	.id_table	= oakscsi_cids,
+	.drv = {
+		.name	= "oakscsi",
+	},
+};
+
+static int __init oakscsi_init(void)
+{
+	return ecard_register_driver(&oakscsi_driver);
 }
 
 static void __exit oakscsi_exit(void)
 {
-	scsi_unregister_host(&oakscsi_template);
+	ecard_remove_driver(&oakscsi_driver);
 }
 
 module_init(oakscsi_init);
diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
--- a/drivers/acorn/scsi/powertec.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acorn/scsi/powertec.c	Sun Nov 17 20:30:14 2002
@@ -1,23 +1,11 @@
 /*
  *  linux/drivers/acorn/scsi/powertec.c
  *
- *  Copyright (C) 1997-2000 Russell King
+ *  Copyright (C) 1997-2002 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * This driver is based on experimentation.  Hence, it may have made
- * assumptions about the particular card that I have available, and
- * may not be reliable!
- *
- * Changelog:
- *  01-10-1997	RMK	Created, READONLY version.
- *  15-02-1998	RMK	Added DMA support and hardware definitions.
- *  15-04-1998	RMK	Only do PIO if FAS216 will allow it.
- *  02-05-1998	RMK	Moved DMA sg list into per-interface structure.
- *  27-06-1998	RMK	Changed asm/delay.h to linux/delay.h
- *  02-04-2000	RMK	Updated for new error handling code.
  */
 #include <linux/module.h>
 #include <linux/blk.h>
@@ -45,18 +33,9 @@
 
 #include <scsi/scsicam.h>
 
-/* Configuration */
-#define POWERTEC_XTALFREQ	40
-#define POWERTEC_ASYNC_PERIOD	200
-#define POWERTEC_SYNC_DEPTH	7
-
-/*
- * List of devices that the driver will recognise
- */
-#define POWERTECSCSI_LIST	{ MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI }
-
 #define POWERTEC_FAS216_OFFSET	0xc00
 #define POWERTEC_FAS216_SHIFT	4
+#define POWERTEC_FAS216_SIZE	(16 << POWERTEC_FAS216_SHIFT)
 
 #define POWERTEC_INTR_STATUS	0x800
 #define POWERTEC_INTR_BIT	0x80
@@ -71,33 +50,22 @@
 #define POWERTEC_INTR_ENABLE	1
 #define POWERTEC_INTR_DISABLE	0
 
-/*
- * Version
- */
-#define VER_MAJOR	0
-#define VER_MINOR	0
-#define VER_PATCH	5
-
-static struct expansion_card *ecs[MAX_ECARDS];
+#define VERSION	"1.00 (13/11/2002 2.5.47)"
 
 /*
- * Use term=0,1,0,0,0 to turn terminators on/off
+ * Use term=0,1,0,0,0 to turn terminators on/off.
+ * One entry per slot.
  */
 static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
 #define NR_SG	256
 
-typedef struct {
-	FAS216_Info info;
-
-	struct {
-		unsigned int term_port;
-		unsigned int terms;
-	} control;
-
-	/* other info... */
-	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} PowerTecScsi_Info;
+struct powertec_info {
+	FAS216_Info	info;
+	unsigned int	term_port;
+	unsigned int	term_ctl;
+	struct scatterlist sg[NR_SG];
+};
 
 /* Prototype: void powertecscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on Powertec SCSI card
@@ -124,12 +92,8 @@
 }
 
 static const expansioncard_ops_t powertecscsi_ops = {
-	powertecscsi_irqenable,
-	powertecscsi_irqdisable,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	.irqenable	= powertecscsi_irqenable,
+	.irqdisable	= powertecscsi_irqdisable,
 };
 
 /* Prototype: void powertecscsi_terminator_ctl(host, on_off)
@@ -140,14 +104,10 @@
 static void
 powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
 {
-	PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata;
-
-	if (on_off)
-		info->control.terms = POWERTEC_TERM_ENABLE;
-	else
-		info->control.terms = 0;
+	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 
-	outb(info->control.terms, info->control.term_port);
+	info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0;
+	outb(info->term_ctl, info->term_port);
 }
 
 /* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
@@ -176,7 +136,7 @@
 powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
 		       fasdmadir_t direction, fasdmatype_t min_type)
 {
-	PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata;
+	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 	int dmach = host->dma_channel;
 
 	if (dmach != NO_DMA &&
@@ -220,122 +180,6 @@
 		disable_dma(host->dma_channel);
 }
 
-/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt)
- * Purpose  : initialises PowerTec SCSI driver
- * Params   : tpnt - template for this SCSI adapter
- * Returns  : >0 if host found, 0 otherwise.
- */
-int
-powertecscsi_detect(Scsi_Host_Template *tpnt)
-{
-	static const card_ids powertecscsi_cids[] =
-			{ POWERTECSCSI_LIST, { 0xffff, 0xffff} };
-	int count = 0;
-	struct Scsi_Host *host;
-  
-	tpnt->proc_name = "powertec";
-	memset(ecs, 0, sizeof (ecs));
-
-	ecard_startfind();
-
-	while (1) {
-	    	PowerTecScsi_Info *info;
-
-		ecs[count] = ecard_find(0, powertecscsi_cids);
-		if (!ecs[count])
-			break;
-
-		ecard_claim(ecs[count]);
-
-		host = scsi_register(tpnt, sizeof (PowerTecScsi_Info));
-		if (!host) {
-			ecard_release(ecs[count]);
-			break;
-		}
-
-		host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST);
-		host->irq = ecs[count]->irq;
-		host->dma_channel = ecs[count]->dma;
-		info = (PowerTecScsi_Info *)host->hostdata;
-
-		if (host->dma_channel != NO_DMA)
-			set_dma_speed(host->dma_channel, 180);
-
-		info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL;
-		info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0;
-		powertecscsi_terminator_ctl(host, info->control.terms);
-
-		info->info.scsi.io_port	=
-				host->io_port + POWERTEC_FAS216_OFFSET;
-		info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT;
-		info->info.scsi.irq		= host->irq;
-		info->info.ifcfg.clockrate	= POWERTEC_XTALFREQ;
-		info->info.ifcfg.select_timeout	= 255;
-		info->info.ifcfg.asyncperiod	= POWERTEC_ASYNC_PERIOD;
-		info->info.ifcfg.sync_max_depth	= POWERTEC_SYNC_DEPTH;
-		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
-		info->info.ifcfg.disconnect_ok	= 1;
-		info->info.ifcfg.wide_max_size	= 0;
-		info->info.dma.setup		= powertecscsi_dma_setup;
-		info->info.dma.pseudo		= NULL;
-		info->info.dma.stop		= powertecscsi_dma_stop;
-
-		ecs[count]->irqaddr	= (unsigned char *)
-			    ioaddr(host->io_port + POWERTEC_INTR_STATUS);
-		ecs[count]->irqmask	= POWERTEC_INTR_BIT;
-		ecs[count]->irq_data	= (void *)
-			    (host->io_port + POWERTEC_INTR_CONTROL);
-		ecs[count]->ops		= (expansioncard_ops_t *)&powertecscsi_ops;
-
-		request_region(host->io_port + POWERTEC_FAS216_OFFSET,
-			       16 << POWERTEC_FAS216_SHIFT, "powertec2-fas");
-
-		if (host->irq != NO_IRQ &&
-		    request_irq(host->irq, powertecscsi_intr,
-				SA_INTERRUPT, "powertec", host)) {
-			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-			       host->host_no, host->irq);
-			host->irq = NO_IRQ;
-			info->info.scsi.irq = NO_IRQ;
-		}
-
-		if (host->dma_channel != NO_DMA &&
-		    request_dma(host->dma_channel, "powertec")) {
-			printk("scsi%d: DMA%d not free, DMA disabled\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
-		}
-
-		fas216_init(host);
-		++count;
-	}
-	return count;
-}
-
-/* Prototype: int powertecscsi_release(struct Scsi_Host * host)
- * Purpose  : releases all resources used by this adapter
- * Params   : host - driver host structure to return info for.
- */
-int powertecscsi_release(struct Scsi_Host *host)
-{
-	int i;
-
-	fas216_release(host);
-
-	if (host->irq != NO_IRQ)
-		free_irq(host->irq, host);
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	release_region(host->io_port + POWERTEC_FAS216_OFFSET,
-		       16 << POWERTEC_FAS216_SHIFT);
-
-	for (i = 0; i < MAX_ECARDS; i++)
-		if (ecs[i] &&
-		    host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST))
-			ecard_release(ecs[i]);
-	return 0;
-}
-
 /* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
  * Purpose  : returns a descriptive string about this interface,
  * Params   : host - driver host structure to return info for.
@@ -343,15 +187,14 @@
  */
 const char *powertecscsi_info(struct Scsi_Host *host)
 {
-	PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata;
+	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 	static char string[100], *p;
 
 	p = string;
 	p += sprintf(p, "%s ", host->hostt->name);
 	p += fas216_info(&info->info, p);
-	p += sprintf(p, "v%d.%d.%d terminators o%s",
-		     VER_MAJOR, VER_MINOR, VER_PATCH,
-		     info->control.terms ? "n" : "ff");
+	p += sprintf(p, "v%s terminators o%s",
+		     VERSION, info->term_ctl ? "n" : "ff");
 
 	return string;
 }
@@ -405,7 +248,7 @@
 {
 	int pos, begin;
 	struct Scsi_Host *host;
-	PowerTecScsi_Info *info;
+	struct powertec_info *info;
 	Scsi_Device *scd;
 
 	host = scsi_host_hn_get(host_no);
@@ -415,16 +258,14 @@
 	if (inout == 1)
 		return powertecscsi_set_proc_info(host, buffer, length);
 
-	info = (PowerTecScsi_Info *)host->hostdata;
+	info = (struct powertec_info *)host->hostdata;
 
 	begin = 0;
-	pos = sprintf(buffer,
-			"PowerTec SCSI driver version %d.%d.%d\n",
-			VER_MAJOR, VER_MINOR, VER_PATCH);
+	pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION);
 
 	pos += fas216_print_host(&info->info, buffer + pos);
 	pos += sprintf(buffer + pos, "Term    : o%s\n",
-			info->control.terms ? "n" : "ff");
+			info->term_ctl ? "n" : "ff");
 
 	pos += fas216_print_stats(&info->info, buffer + pos);
 
@@ -453,35 +294,147 @@
 	.module				= THIS_MODULE,
 	.proc_info			= powertecscsi_proc_info,
 	.name				= "PowerTec SCSI",
-	.detect				= powertecscsi_detect,
-	.release			= powertecscsi_release,
 	.info				= powertecscsi_info,
-	.can_queue			= 1,
-	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
-	.cmd_per_lun			= 1,
-	.use_clustering			= ENABLE_CLUSTERING,
 	.command			= fas216_command,
 	.queuecommand			= fas216_queue_command,
 	.eh_host_reset_handler		= fas216_eh_host_reset,
 	.eh_bus_reset_handler		= fas216_eh_bus_reset,
 	.eh_device_reset_handler	= fas216_eh_device_reset,
 	.eh_abort_handler		= fas216_eh_abort,
+
+	.can_queue			= 1,
+	.this_id			= 7,
+	.sg_tablesize			= SG_ALL,
+	.cmd_per_lun			= 1,
+	.use_clustering			= ENABLE_CLUSTERING,
+	.proc_name			= "powertec",
 };
 
-static int __init powertecscsi_init(void)
+static int __devinit
+powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-	scsi_register_host(&powertecscsi_template);
-	if (powertecscsi_template.present)
-		return 0;
+	struct Scsi_Host *host;
+    	struct powertec_info *info;
+    	int ret = -ENOMEM;
+
+	host = scsi_register(&powertecscsi_template,
+			     sizeof (struct powertec_info));
+	if (!host)
+		goto out;
+
+	host->io_port	  = ecard_address(ec, ECARD_IOC, ECARD_FAST);
+	host->irq	  = ec->irq;
+	host->dma_channel = ec->dma;
+
+	if (!request_region(host->io_port + POWERTEC_FAS216_OFFSET,
+			    POWERTEC_FAS216_SIZE, "powertec2-fas")) {
+		ret = -EBUSY;
+		goto out_free;
+	}
+
+	ec->irqaddr	= (unsigned char *)
+			    ioaddr(host->io_port + POWERTEC_INTR_STATUS);
+	ec->irqmask	= POWERTEC_INTR_BIT;
+	ec->irq_data	= (void *)(host->io_port + POWERTEC_INTR_CONTROL);
+	ec->ops		= (expansioncard_ops_t *)&powertecscsi_ops;
+
+	ecard_set_drvdata(ec, host);
+
+	info = (struct powertec_info *)host->hostdata;
+	info->term_port = host->io_port + POWERTEC_TERM_CONTROL;
+	powertecscsi_terminator_ctl(host, term[ec->slot_no]);
+
+	info->info.scsi.io_port		= host->io_port + POWERTEC_FAS216_OFFSET;
+	info->info.scsi.io_shift	= POWERTEC_FAS216_SHIFT;
+	info->info.scsi.irq		= host->irq;
+	info->info.ifcfg.clockrate	= 40; /* MHz */
+	info->info.ifcfg.select_timeout	= 255;
+	info->info.ifcfg.asyncperiod	= 200; /* ns */
+	info->info.ifcfg.sync_max_depth	= 7;
+	info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+	info->info.ifcfg.disconnect_ok	= 1;
+	info->info.ifcfg.wide_max_size	= 0;
+	info->info.dma.setup		= powertecscsi_dma_setup;
+	info->info.dma.pseudo		= NULL;
+	info->info.dma.stop		= powertecscsi_dma_stop;
+
+	ret = request_irq(host->irq, powertecscsi_intr,
+			  SA_INTERRUPT, "powertec", host);
+	if (ret) {
+		printk("scsi%d: IRQ%d not free: %d\n",
+		       host->host_no, host->irq, ret);
+		goto out_region;
+	}
+
+	if (host->dma_channel != NO_DMA) {
+		if (request_dma(host->dma_channel, "powertec")) {
+			printk("scsi%d: DMA%d not free, using PIO\n",
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
+		} else {
+			set_dma_speed(host->dma_channel, 180);
+		}
+	}
+
+	fas216_init(host);
+
+	ret = scsi_add_host(host);
+	if (ret == 0)
+		goto out;
 
-	scsi_unregister_host(&powertecscsi_template);
-	return -ENODEV;
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+ out_region:
+	release_region(host->io_port + POWERTEC_FAS216_OFFSET,
+		       POWERTEC_FAS216_SIZE);
+ out_free:
+	scsi_unregister(host);
+
+ out:
+	return ret;
+}
+
+static void __devexit powertecscsi_remove(struct expansion_card *ec)
+{
+	struct Scsi_Host *host = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+	scsi_remove_host(host);
+	fas216_release(host);
+
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	free_irq(host->irq, host);
+	release_region(host->io_port + POWERTEC_FAS216_OFFSET,
+		       POWERTEC_FAS216_SIZE);
+	scsi_unregister(host);
+}
+
+static const struct ecard_id powertecscsi_cids[] = {
+	{ MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI },
+	{ 0xffff, 0xffff },
+};
+
+static struct ecard_driver powertecscsi_driver = {
+	.probe		= powertecscsi_probe,
+	.remove		= __devexit_p(powertecscsi_remove),
+	.id_table	= powertecscsi_cids,
+	.drv = {
+		.name	= "powertecscsi",
+	},
+};
+
+static int __init powertecscsi_init(void)
+{
+	return ecard_register_driver(&powertecscsi_driver);
 }
 
 static void __exit powertecscsi_exit(void)
 {
-	scsi_unregister_host(&powertecscsi_template);
+	ecard_remove_driver(&powertecscsi_driver);
 }
 
 module_init(powertecscsi_init);
@@ -492,4 +445,3 @@
 MODULE_PARM(term, "1-8i");
 MODULE_PARM_DESC(term, "SCSI bus termination");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c
--- a/drivers/acorn/scsi/queue.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/acorn/scsi/queue.c	Sun Nov 17 20:30:03 2002
@@ -229,6 +229,27 @@
 }
 
 /*
+ * Function: queue_remove_all_target(queue, target)
+ * Purpose : remove all SCSI commands from the queue for a specified target
+ * Params  : queue  - queue to remove command from
+ *           target - target device id
+ * Returns : nothing
+ */
+void queue_remove_all_target(Queue_t *queue, int target)
+{
+	unsigned long flags;
+	struct list_head *l;
+
+	spin_lock_irqsave(&queue->queue_lock, flags);
+	list_for_each(l, &queue->head) {
+		QE_t *q = list_entry(l, QE_t, list);
+		if (q->SCpnt->target == target)
+			__queue_remove(queue, l);
+	}
+	spin_unlock_irqrestore(&queue->queue_lock, flags);
+}
+
+/*
  * Function: int queue_probetgtlun (queue, target, lun)
  * Purpose : check to see if we have a command in the queue for the specified
  *	     target/lun.
@@ -290,6 +311,7 @@
 EXPORT_SYMBOL(queue_remove_exclude);
 EXPORT_SYMBOL(queue_remove_tgtluntag);
 EXPORT_SYMBOL(queue_remove_cmd);
+EXPORT_SYMBOL(queue_remove_all_target);
 EXPORT_SYMBOL(queue_probetgtlun);
 
 MODULE_AUTHOR("Russell King");
diff -Nru a/drivers/acorn/scsi/queue.h b/drivers/acorn/scsi/queue.h
--- a/drivers/acorn/scsi/queue.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/acorn/scsi/queue.h	Sun Nov 17 20:30:14 2002
@@ -74,6 +74,15 @@
 extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag);
 
 /*
+ * Function: queue_remove_all_target(queue, target)
+ * Purpose : remove all SCSI commands from the queue for a specified target
+ * Params  : queue  - queue to remove command from
+ *           target - target device id
+ * Returns : nothing
+ */
+extern void queue_remove_all_target(Queue_t *queue, int target);
+
+/*
  * Function: int queue_probetgtlun (queue, target, lun)
  * Purpose : check to see if we have a command in the queue for the specified
  *	     target/lun.
diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c
--- a/drivers/acpi/ac.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acpi/ac.c	Sun Nov 17 20:30:13 2002
@@ -159,12 +159,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_ac_add_fs");
 
-	if (!acpi_ac_dir) {
-		acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
-		if (!acpi_ac_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_ac_dir);
@@ -194,9 +188,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
 
-	if (!acpi_ac_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
 
@@ -330,6 +321,10 @@
 
 	ACPI_FUNCTION_TRACE("acpi_ac_init");
 
+	acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
+	if (!acpi_ac_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_ac_driver);
 	if (result < 0) {
 		remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
@@ -343,13 +338,11 @@
 void __exit
 acpi_ac_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_ac_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_ac_driver);
-	if (!result)
-		remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_ac_driver);
+
+	remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/battery.c b/drivers/acpi/battery.c
--- a/drivers/acpi/battery.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/battery.c	Sun Nov 17 20:30:15 2002
@@ -615,12 +615,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
 
-	if (!acpi_battery_dir) {
-		acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
-		if (!acpi_battery_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_battery_dir);
@@ -675,9 +669,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
 
-	if (!acpi_battery_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
 
@@ -812,6 +803,10 @@
 
 	ACPI_FUNCTION_TRACE("acpi_battery_init");
 
+	acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
+	if (!acpi_battery_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_battery_driver);
 	if (result < 0) {
 		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
@@ -825,13 +820,11 @@
 static void __exit
 acpi_battery_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_battery_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_battery_driver);
-	if (!result)
-		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_battery_driver);
+
+	remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c
--- a/drivers/acpi/bus.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/bus.c	Sun Nov 17 20:30:14 2002
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/pm.h>
+#include <linux/device.h>
 #include <linux/proc_fs.h>
 #ifdef CONFIG_X86
 #include <asm/mpspec.h>
diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c
--- a/drivers/acpi/button.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/button.c	Sun Nov 17 20:30:02 2002
@@ -141,12 +141,6 @@
 
 	button = acpi_driver_data(device);
 
-	if (!acpi_button_dir) {
-		acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
-		if (!acpi_button_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	switch (button->type) {
 	case ACPI_BUTTON_TYPE_POWER:
 	case ACPI_BUTTON_TYPE_POWERF:
@@ -190,9 +184,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
 
-	if (!acpi_button_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_button_dir);
 
@@ -446,9 +437,15 @@
 
 	ACPI_FUNCTION_TRACE("acpi_button_init");
 
+	acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+	if (!acpi_button_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_button_driver);
-	if (result < 0)
+	if (result < 0) {
+		remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
 		return_VALUE(-ENODEV);
+	}
 
 	return_VALUE(0);
 }
@@ -460,6 +457,8 @@
 	ACPI_FUNCTION_TRACE("acpi_button_exit");
 
 	acpi_bus_unregister_driver(&acpi_button_driver);
+
+	remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
--- a/drivers/acpi/dispatcher/dsmethod.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/dispatcher/dsmethod.c	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
- *              $Revision: 88 $
+ *              $Revision: 89 $
  *
  *****************************************************************************/
 
@@ -216,7 +216,7 @@
 		 * interpreter if we block
 		 */
 		status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
-				 WAIT_FOREVER);
+				 ACPI_WAIT_FOREVER);
 	}
 
 	/*
diff -Nru a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
--- a/drivers/acpi/dispatcher/dswstate.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/dispatcher/dswstate.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dswstate - Dispatcher parse tree walk management routines
- *              $Revision: 69 $
+ *              $Revision: 70 $
  *
  *****************************************************************************/
 
@@ -345,7 +345,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Push an object onto the Walk_state result stack.
  *
  ******************************************************************************/
 
@@ -381,7 +381,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Pop an object off of the Walk_state result stack.
  *
  ******************************************************************************/
 
diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c
--- a/drivers/acpi/ec.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/ec.c	Sun Nov 17 20:30:14 2002
@@ -477,12 +477,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
 
-	if (!acpi_ec_dir) {
-		acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
-		if (!acpi_ec_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_ec_dir);
@@ -508,12 +502,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
 
-	if (!acpi_ec_dir)
-		return_VALUE(-ENODEV);
-
-	if (acpi_device_dir(device))
-		remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
-
 	return_VALUE(0);
 }
 
@@ -789,13 +777,24 @@
 	if (acpi_disabled)
 		return_VALUE(0);
 
+	acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
+	if (!acpi_ec_dir)
+		return_VALUE(-ENODEV);
+
 	/* Now register the driver for the EC */
 	result = acpi_bus_register_driver(&acpi_ec_driver);
+	if (result < 0) {
+		remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
+		return_VALUE(-ENODEV);
+	}
+
 	return_VALUE(result);
 }
 
 subsys_initcall(acpi_ec_init);
 
+/* EC driver currently not unloadable */
+#if 0
 static void __exit
 acpi_ec_ecdt_exit (void)
 {
@@ -813,17 +812,15 @@
 static void __exit
 acpi_ec_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_ec_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_ec_driver);
-	if (!result)
-		remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_ec_driver);
 
+	remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
 
 	acpi_ec_ecdt_exit();
 
 	return_VOID;
 }
+#endif /* 0 */
 
diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
--- a/drivers/acpi/events/evevent.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/events/evevent.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evevent - Fixed and General Purpose Even handling and dispatch
- *              $Revision: 95 $
+ *              $Revision: 96 $
  *
  *****************************************************************************/
 
@@ -503,9 +503,9 @@
 
 			ACPI_REPORT_INFO (("GPE Block%d defined as GPE%d to GPE%d\n",
 				(s32) gpe_block,
-				acpi_gbl_gpe_block_info[gpe_block].block_base_number,
-				acpi_gbl_gpe_block_info[gpe_block].block_base_number +
-					((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1)));
+				(u32) acpi_gbl_gpe_block_info[gpe_block].block_base_number,
+				(u32) (acpi_gbl_gpe_block_info[gpe_block].block_base_number +
+					((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1))));
 		}
 	}
 
diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
--- a/drivers/acpi/events/evmisc.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/events/evmisc.c	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evmisc - Miscellaneous event manager support functions
- *              $Revision: 57 $
+ *              $Revision: 58 $
  *
  *****************************************************************************/
 
@@ -433,7 +433,7 @@
 
 acpi_status
 acpi_ev_acquire_global_lock (
-	u32                     timeout)
+	u16                     timeout)
 {
 	acpi_status             status = AE_OK;
 	u8                      acquired = FALSE;
diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
--- a/drivers/acpi/events/evxface.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/events/evxface.c	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evxface - External interfaces for ACPI events
- *              $Revision: 131 $
+ *              $Revision: 132 $
  *
  *****************************************************************************/
 
@@ -612,7 +612,7 @@
 
 acpi_status
 acpi_acquire_global_lock (
-	u32                     timeout,
+	u16                     timeout,
 	u32                     *handle)
 {
 	acpi_status             status;
diff -Nru a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
--- a/drivers/acpi/executer/exdump.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/acpi/executer/exdump.c	Sun Nov 17 20:30:03 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exdump - Interpreter debug output routines
- *              $Revision: 162 $
+ *              $Revision: 163 $
  *
  *****************************************************************************/
 
@@ -590,6 +590,7 @@
 
 		acpi_ex_out_integer ("Length",       obj_desc->buffer.length);
 		acpi_ex_out_pointer ("Pointer",      obj_desc->buffer.pointer);
+		ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length);
 		break;
 
 
diff -Nru a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
--- a/drivers/acpi/executer/exfield.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/executer/exfield.c	Sun Nov 17 20:30:02 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
- *              $Revision: 112 $
+ *              $Revision: 113 $
  *
  *****************************************************************************/
 
@@ -27,6 +27,8 @@
 #include "acpi.h"
 #include "acdispat.h"
 #include "acinterp.h"
+#include "acevents.h"
+#include "amlcode.h"
 
 
 #define _COMPONENT          ACPI_EXECUTER
@@ -82,6 +84,45 @@
 			}
 		}
 	}
+	else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+			 (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+		/*
+		 * This is an SMBus read.  We must create a buffer to hold the data
+		 * and directly access the region handler.
+		 */
+		buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!buffer_desc) {
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+
+		/* Create the actual read buffer */
+
+		buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE);
+		if (!buffer_desc->buffer.pointer) {
+			acpi_ut_remove_reference (buffer_desc);
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+
+		/* Complete the buffer object initialization */
+
+		buffer_desc->common.flags = AOPOBJ_DATA_VALID;
+		buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE;
+		buffer = buffer_desc->buffer.pointer;
+
+		/* Lock entire transaction if requested */
+
+		locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+
+		/*
+		 * Perform the read.
+		 * Note: Smbus protocol value is passed in upper 16-bits of Function
+		 */
+		status = acpi_ex_access_region (obj_desc, 0,
+				  (acpi_integer *) buffer_desc->buffer.pointer,
+				  ACPI_READ | (obj_desc->field.attribute << 16));
+		acpi_ex_release_global_lock (locked);
+		goto exit;
+	}
 
 	/*
 	 * Allocate a buffer for the contents of the field.
@@ -138,17 +179,17 @@
 		obj_desc->common_field.start_field_bit_offset,
 		obj_desc->common_field.base_byte_offset));
 
+	/* Lock entire transaction if requested */
+
 	locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
 
 	/* Read from the field */
 
 	status = acpi_ex_extract_from_field (obj_desc, buffer, length);
-
-	/*
-	 * Release global lock if we acquired it earlier
-	 */
 	acpi_ex_release_global_lock (locked);
 
+
+exit:
 	if (ACPI_FAILURE (status)) {
 		acpi_ut_remove_reference (buffer_desc);
 	}
@@ -176,7 +217,8 @@
 acpi_status
 acpi_ex_write_data_to_field (
 	acpi_operand_object     *source_desc,
-	acpi_operand_object     *obj_desc)
+	acpi_operand_object     *obj_desc,
+	acpi_operand_object     **result_desc)
 {
 	acpi_status             status;
 	u32                     length;
@@ -184,6 +226,7 @@
 	void                    *buffer;
 	void                    *new_buffer;
 	u8                      locked;
+	acpi_operand_object     *buffer_desc;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("Ex_write_data_to_field", obj_desc);
@@ -207,6 +250,64 @@
 			}
 		}
 	}
+	else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+			 (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+		/*
+		 * This is an SMBus write.  We will bypass the entire field mechanism
+		 * and handoff the buffer directly to the handler.
+		 *
+		 * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
+		 */
+		if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
+			ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
+				acpi_ut_get_object_type_name (source_desc)));
+			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+		}
+
+		if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
+			ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n",
+				ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
+			return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
+		}
+
+		buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!buffer_desc) {
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+
+		/* Create the actual read buffer */
+
+		buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE);
+		if (!buffer_desc->buffer.pointer) {
+			acpi_ut_remove_reference (buffer_desc);
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+
+		/* Complete the buffer object initialization */
+
+		buffer_desc->common.flags = AOPOBJ_DATA_VALID;
+		buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE;
+		buffer = buffer_desc->buffer.pointer;
+
+
+		ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE);
+
+		/* Lock entire transaction if requested */
+
+		locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+
+		/*
+		 * Perform the write (returns status and perhaps data in the same buffer)
+		 * Note: SMBus protocol type is passed in upper 16-bits of Function.
+		 */
+		status = acpi_ex_access_region (obj_desc, 0,
+				  (acpi_integer *) buffer,
+				  ACPI_WRITE | (obj_desc->field.attribute << 16));
+		acpi_ex_release_global_lock (locked);
+
+		*result_desc = buffer_desc;
+		return_ACPI_STATUS (status);
+	}
 
 	/*
 	 * Get a pointer to the data to be written
@@ -267,16 +368,13 @@
 		obj_desc->common_field.start_field_bit_offset,
 		obj_desc->common_field.base_byte_offset));
 
+	/* Lock entire transaction if requested */
+
 	locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
 
-	/*
-	 * Write to the field
-	 */
-	status = acpi_ex_insert_into_field (obj_desc, buffer, length);
+	/* Write to the field */
 
-	/*
-	 * Release global lock if we acquired it earlier
-	 */
+	status = acpi_ex_insert_into_field (obj_desc, buffer, length);
 	acpi_ex_release_global_lock (locked);
 
 	/* Free temporary buffer if we used one */
diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
--- a/drivers/acpi/executer/exfldio.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/acpi/executer/exfldio.c	Sun Nov 17 20:30:12 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exfldio - Aml Field I/O
- *              $Revision: 89 $
+ *              $Revision: 90 $
  *
  *****************************************************************************/
 
@@ -64,6 +64,8 @@
 
 	rgn_desc = obj_desc->common_field.region_obj;
 
+	/* We must have a valid region */
+
 	if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
 			ACPI_GET_OBJECT_TYPE (rgn_desc),
@@ -83,6 +85,12 @@
 		}
 	}
 
+	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
+		/* SMBus has a non-linear address space */
+
+		return_ACPI_STATUS (AE_OK);
+	}
+
 	/*
 	 * Validate the request.  The entire request from the byte offset for a
 	 * length of one field datum (access width) must fit within the region.
@@ -127,8 +135,10 @@
  * PARAMETERS:  *Obj_desc               - Field to be read
  *              Field_datum_byte_offset - Byte offset of this datum within the
  *                                        parent field
- *              *Value                  - Where to store value (must be 32 bits)
- *              Read_write              - Read or Write flag
+ *              *Value                  - Where to store value (must at least
+ *                                        the size of acpi_integer)
+ *              Function                - Read or Write flag plus other region-
+ *                                        dependent flags
  *
  * RETURN:      Status
  *
@@ -141,7 +151,7 @@
 	acpi_operand_object     *obj_desc,
 	u32                     field_datum_byte_offset,
 	acpi_integer            *value,
-	u32                     read_write)
+	u32                     function)
 {
 	acpi_status             status;
 	acpi_operand_object     *rgn_desc;
@@ -152,6 +162,15 @@
 
 
 	/*
+	 * Ensure that the region operands are fully evaluated and verify
+	 * the validity of the request
+	 */
+	status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/*
 	 * The physical address of this field datum is:
 	 *
 	 * 1) The base of the region, plus
@@ -163,7 +182,7 @@
 			 + obj_desc->common_field.base_byte_offset
 			 + field_datum_byte_offset;
 
-	if (read_write == ACPI_READ) {
+	if ((function & ACPI_IO_MASK) == ACPI_READ) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
 	}
 	else {
@@ -181,7 +200,7 @@
 
 	/* Invoke the appropriate Address_space/Op_region handler */
 
-	status = acpi_ev_address_space_dispatch (rgn_desc, read_write,
+	status = acpi_ev_address_space_dispatch (rgn_desc, function,
 			  address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
 
 	if (ACPI_FAILURE (status)) {
@@ -191,7 +210,6 @@
 				acpi_ut_get_region_name (rgn_desc->region.space_id),
 				rgn_desc->region.space_id));
 		}
-
 		else if (status == AE_NOT_EXIST) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 				"Region %s(%X) has no handler\n",
@@ -371,11 +389,6 @@
 		 * For simple Region_fields, we just directly access the owning
 		 * Operation Region.
 		 */
-		status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
-
 		status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
 				  read_write);
 		break;
diff -Nru a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
--- a/drivers/acpi/executer/exoparg1.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/executer/exoparg1.c	Sun Nov 17 20:30:15 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exoparg1 - AML execution - opcodes with 1 argument
- *              $Revision: 144 $
+ *              $Revision: 145 $
  *
  *****************************************************************************/
 
@@ -389,14 +389,16 @@
 			return_ACPI_STATUS (status);
 		}
 
-		/*
-		 * Normally, we would remove a reference on the Operand[0] parameter;
-		 * But since it is being used as the internal return object
-		 * (meaning we would normally increment it), the two cancel out,
-		 * and we simply don't do anything.
-		 */
-		walk_state->result_obj = operand[0];
-		walk_state->operands[0] = NULL; /* Prevent deletion */
+		if (!walk_state->result_obj) {
+			/*
+			 * Normally, we would remove a reference on the Operand[0] parameter;
+			 * But since it is being used as the internal return object
+			 * (meaning we would normally increment it), the two cancel out,
+			 * and we simply don't do anything.
+			 */
+			walk_state->result_obj = operand[0];
+			walk_state->operands[0] = NULL; /* Prevent deletion */
+		}
 		return_ACPI_STATUS (status);
 
 
@@ -461,7 +463,9 @@
 
 cleanup:
 
-	walk_state->result_obj = return_desc;
+	if (!walk_state->result_obj) {
+		walk_state->result_obj = return_desc;
+	}
 
 	/* Delete return object on error */
 
diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
--- a/drivers/acpi/executer/exoparg2.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/executer/exoparg2.c	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
- *              $Revision: 113 $
+ *              $Revision: 114 $
  *
  *****************************************************************************/
 
@@ -490,7 +490,9 @@
 			goto cleanup;
 		}
 
-		walk_state->result_obj = return_desc;
+		if (!walk_state->result_obj) {
+			walk_state->result_obj = return_desc;
+		}
 	}
 
 
diff -Nru a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
--- a/drivers/acpi/executer/exoparg3.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/executer/exoparg3.c	Sun Nov 17 20:30:02 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exoparg3 - AML execution - opcodes with 3 arguments
- *              $Revision: 14 $
+ *              $Revision: 15 $
  *
  *****************************************************************************/
 
@@ -226,7 +226,9 @@
 
 	/* Set the return object and exit */
 
-	walk_state->result_obj = return_desc;
+	if (!walk_state->result_obj) {
+		walk_state->result_obj = return_desc;
+	}
 	return_ACPI_STATUS (status);
 }
 
diff -Nru a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
--- a/drivers/acpi/executer/exprep.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/acpi/executer/exprep.c	Sun Nov 17 20:30:04 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
- *              $Revision: 120 $
+ *              $Revision: 121 $
  *
  *****************************************************************************/
 
@@ -107,28 +107,24 @@
 		break;
 
 	case AML_FIELD_ACCESS_BYTE:
+	case AML_FIELD_ACCESS_BUFFER:   /* ACPI 2.0 (SMBus Buffer) */
 		byte_alignment = 1;
-		bit_length = 8;
+		bit_length    = 8;
 		break;
 
 	case AML_FIELD_ACCESS_WORD:
 		byte_alignment = 2;
-		bit_length = 16;
+		bit_length    = 16;
 		break;
 
 	case AML_FIELD_ACCESS_DWORD:
 		byte_alignment = 4;
-		bit_length = 32;
+		bit_length    = 32;
 		break;
 
-	case AML_FIELD_ACCESS_QWORD:  /* ACPI 2.0 */
+	case AML_FIELD_ACCESS_QWORD:    /* ACPI 2.0 */
 		byte_alignment = 8;
-		bit_length = 64;
-		break;
-
-	case AML_FIELD_ACCESS_BUFFER:  /* ACPI 2.0 */
-		byte_alignment = 8;
-		bit_length = 8;
+		bit_length    = 64;
 		break;
 
 	default:
diff -Nru a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
--- a/drivers/acpi/executer/exstore.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acpi/executer/exstore.c	Sun Nov 17 20:30:13 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exstore - AML Interpreter object store support
- *              $Revision: 173 $
+ *              $Revision: 174 $
  *
  *****************************************************************************/
 
@@ -81,7 +81,7 @@
 	if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
 		/*
 		 * Dest is a namespace node,
-		 * Storing an object into a Name "container"
+		 * Storing an object into a Named node.
 		 */
 		status = acpi_ex_store_object_to_node (source_desc,
 				 (acpi_namespace_node *) dest_desc, walk_state);
@@ -435,7 +435,7 @@
 		/*
 		 * For fields, copy the source data to the target field.
 		 */
-		status = acpi_ex_write_data_to_field (source_desc, target_desc);
+		status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj);
 		break;
 
 
diff -Nru a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
--- a/drivers/acpi/executer/exsystem.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/executer/exsystem.c	Sun Nov 17 20:30:15 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exsystem - Interface to OS services
- *              $Revision: 73 $
+ *              $Revision: 74 $
  *
  *****************************************************************************/
 
@@ -51,7 +51,7 @@
 acpi_status
 acpi_ex_system_wait_semaphore (
 	acpi_handle             semaphore,
-	u32                     timeout)
+	u16                     timeout)
 {
 	acpi_status             status;
 	acpi_status             status2;
@@ -201,12 +201,12 @@
 	 * Support for the _GL_ Mutex object -- go get the global lock
 	 */
 	if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
-		status = acpi_ev_acquire_global_lock ((u32) time_desc->integer.value);
+		status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value);
 		return_ACPI_STATUS (status);
 	}
 
 	status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore,
-			  (u32) time_desc->integer.value);
+			  (u16) time_desc->integer.value);
 	return_ACPI_STATUS (status);
 }
 
@@ -312,7 +312,7 @@
 
 	if (obj_desc) {
 		status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore,
-				  (u32) time_desc->integer.value);
+				  (u16) time_desc->integer.value);
 	}
 
 	return_ACPI_STATUS (status);
diff -Nru a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
--- a/drivers/acpi/executer/exutils.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/acpi/executer/exutils.c	Sun Nov 17 20:30:04 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exutils - interpreter/scanner utilities
- *              $Revision: 105 $
+ *              $Revision: 106 $
  *
  *****************************************************************************/
 
@@ -189,7 +189,7 @@
 	if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
 		/* We should attempt to get the lock, wait forever */
 
-		status = acpi_ev_acquire_global_lock (ACPI_UINT32_MAX);
+		status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER);
 		if (ACPI_SUCCESS (status)) {
 			locked = TRUE;
 		}
diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c
--- a/drivers/acpi/fan.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/fan.c	Sun Nov 17 20:30:02 2002
@@ -151,12 +151,6 @@
 	if (!device)
 		return_VALUE(-EINVAL);
 
-	if (!acpi_fan_dir) {
-		acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
-		if (!acpi_fan_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_fan_dir);
@@ -187,9 +181,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
 
-	if (!acpi_fan_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
 
@@ -276,9 +267,15 @@
 
 	ACPI_FUNCTION_TRACE("acpi_fan_init");
 
+	acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
+	if (!acpi_fan_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_fan_driver);
-	if (result < 0)
+	if (result < 0) {
+		remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
 		return_VALUE(-ENODEV);
+	}
 
 	return_VALUE(0);
 }
@@ -287,13 +284,11 @@
 void __exit
 acpi_fan_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_fan_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_fan_driver);
-	if (!result)
-		remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_fan_driver);
+
+	remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h
--- a/drivers/acpi/include/acconfig.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/include/acconfig.h	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acconfig.h - Global configuration constants
- *       $Revision: 115 $
+ *       $Revision: 117 $
  *
  *****************************************************************************/
 
@@ -54,7 +54,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20021101
+#define ACPI_CA_VERSION                 0x20021111
 
 /* Version of ACPI supported */
 
@@ -165,6 +165,10 @@
 
 #define ACPI_RSDP_CHECKSUM_LENGTH       20
 #define ACPI_RSDP_XCHECKSUM_LENGTH      36
+
+/* SMBus bidirectional buffer size */
+
+#define ACPI_SMBUS_BUFFER_SIZE          34
 
 
 /******************************************************************************
diff -Nru a/drivers/acpi/include/acdisasm.h b/drivers/acpi/include/acdisasm.h
--- a/drivers/acpi/include/acdisasm.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/include/acdisasm.h	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acdisasm.h - AML disassembler
- *       $Revision: 4 $
+ *       $Revision: 5 $
  *
  *****************************************************************************/
 
@@ -239,6 +239,9 @@
 acpi_dm_bit_list (
 	u16                     mask);
 
+void
+acpi_dm_decode_attribute (
+	u8                      attribute);
 
 /*
  * dmresrcl
diff -Nru a/drivers/acpi/include/acevents.h b/drivers/acpi/include/acevents.h
--- a/drivers/acpi/include/acevents.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/include/acevents.h	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acevents.h - Event subcomponent prototypes and defines
- *       $Revision: 79 $
+ *       $Revision: 80 $
  *
  *****************************************************************************/
 
@@ -63,7 +63,7 @@
 
 acpi_status
 acpi_ev_acquire_global_lock(
-	u32                     timeout);
+	u16                     timeout);
 
 acpi_status
 acpi_ev_release_global_lock(
diff -Nru a/drivers/acpi/include/acinterp.h b/drivers/acpi/include/acinterp.h
--- a/drivers/acpi/include/acinterp.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/include/acinterp.h	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acinterp.h - Interpreter subcomponent prototypes and defines
- *       $Revision: 140 $
+ *       $Revision: 142 $
  *
  *****************************************************************************/
 
@@ -164,7 +164,8 @@
 acpi_status
 acpi_ex_write_data_to_field (
 	acpi_operand_object     *source_desc,
-	acpi_operand_object     *obj_desc);
+	acpi_operand_object     *obj_desc,
+	acpi_operand_object     **result_desc);
 
 /*
  * exmisc - ACPI AML (p-code) execution - specific opcodes
@@ -377,7 +378,7 @@
 acpi_status
 acpi_ex_system_wait_semaphore (
 	acpi_handle             semaphore,
-	u32                     timeout);
+	u16                     timeout);
 
 
 /*
diff -Nru a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h
--- a/drivers/acpi/include/aclocal.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/include/aclocal.h	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclocal.h - Internal data types used across the ACPI subsystem
- *       $Revision: 178 $
+ *       $Revision: 179 $
  *
  *****************************************************************************/
 
@@ -27,7 +27,7 @@
 #define __ACLOCAL_H__
 
 
-#define WAIT_FOREVER                    ((u32) -1)
+#define ACPI_WAIT_FOREVER               0xFFFF  /* u16, as per ACPI spec */
 
 typedef void*                           acpi_mutex;
 typedef u32                             ACPI_MUTEX_HANDLE;
diff -Nru a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h
--- a/drivers/acpi/include/acpiosxf.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/include/acpiosxf.h	Sun Nov 17 20:30:02 2002
@@ -117,7 +117,7 @@
 acpi_os_wait_semaphore (
 	acpi_handle             handle,
 	u32                     units,
-	u32                     timeout);
+	u16                     timeout);
 
 acpi_status
 acpi_os_signal_semaphore (
diff -Nru a/drivers/acpi/include/acpixf.h b/drivers/acpi/include/acpixf.h
--- a/drivers/acpi/include/acpixf.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/acpi/include/acpixf.h	Sun Nov 17 20:30:02 2002
@@ -281,7 +281,7 @@
 
 acpi_status
 acpi_acquire_global_lock (
-	u32                     timeout,
+	u16                     timeout,
 	u32                     *handle);
 
 acpi_status
diff -Nru a/drivers/acpi/include/actypes.h b/drivers/acpi/include/actypes.h
--- a/drivers/acpi/include/actypes.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/include/actypes.h	Sun Nov 17 20:30:14 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: actypes.h - Common data types for the entire ACPI subsystem
- *       $Revision: 240 $
+ *       $Revision: 241 $
  *
  *****************************************************************************/
 
@@ -499,6 +499,7 @@
  */
 #define ACPI_READ                       0
 #define ACPI_WRITE                      1
+#define ACPI_IO_MASK                    1
 
 
 /*
diff -Nru a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h
--- a/drivers/acpi/include/amlcode.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/include/amlcode.h	Sun Nov 17 20:30:14 2002
@@ -3,7 +3,7 @@
  * Name: amlcode.h - Definitions for AML, as included in "definition blocks"
  *                   Declarations and definitions contained herein are derived
  *                   directly from the ACPI specification.
- *       $Revision: 70 $
+ *       $Revision: 71 $
  *
  *****************************************************************************/
 
@@ -462,7 +462,8 @@
 	AML_FIELD_ATTRIB_SMB_BYTE       = 0x06,
 	AML_FIELD_ATTRIB_SMB_WORD       = 0x08,
 	AML_FIELD_ATTRIB_SMB_BLOCK      = 0x0A,
-	AML_FIELD_ATTRIB_SMB_CALL       = 0x0E
+	AML_FIELD_ATTRIB_SMB_WORD_CALL  = 0x0C,
+	AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D
 
 } AML_ACCESS_ATTRIBUTE;
 
diff -Nru a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
--- a/drivers/acpi/namespace/nsdump.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/namespace/nsdump.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: nsdump - table dumping routines for debug
- *              $Revision: 145 $
+ *              $Revision: 146 $
  *
  *****************************************************************************/
 
@@ -180,7 +180,7 @@
 
 	/* Indent the object according to the level */
 
-	acpi_os_printf ("%2d%*s", level - 1, level * 2, " ");
+	acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " ");
 
 	/* Check the node type and name */
 
diff -Nru a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
--- a/drivers/acpi/namespace/nsobject.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acpi/namespace/nsobject.c	Sun Nov 17 20:30:13 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsobject - Utilities for objects attached to namespace
  *                         table entries
- *              $Revision: 84 $
+ *              $Revision: 85 $
  *
  ******************************************************************************/
 
@@ -173,13 +173,13 @@
  *
  * FUNCTION:    Acpi_ns_detach_object
  *
- * PARAMETERS:  Node           - An object whose Value will be deleted
+ * PARAMETERS:  Node           - An node whose object will be detached
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Delete the Value associated with a namespace object.  If the
- *              Value is an allocated object, it is freed.  Otherwise, the
- *              field is simply cleared.
+ * DESCRIPTION: Detach/delete an object associated with a namespace node.
+ *              if the object is an allocated object, it is freed.
+ *              Otherwise, the field is simply cleared.
  *
  ******************************************************************************/
 
@@ -234,6 +234,8 @@
  * RETURN:      Current value of the object field from the Node whose
  *              handle is passed
  *
+ * DESCRIPTION: Obtain the object attached to a namespace node.
+ *
  ******************************************************************************/
 
 acpi_operand_object *
@@ -266,7 +268,9 @@
  * PARAMETERS:  Node             - Parent Node to be examined
  *
  * RETURN:      Current value of the object field from the Node whose
- *              handle is passed
+ *              handle is passed.
+ *
+ * DESCRIPTION: Obtain a secondary object associated with a namespace node.
  *
  ******************************************************************************/
 
@@ -292,11 +296,13 @@
  *
  * FUNCTION:    Acpi_ns_attach_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - Namespace node
+ *              Handler         - Handler to be associated with the data
+ *              Data            - Data to be attached
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Low-level attach data.  Create and attach a Data object.
  *
  ******************************************************************************/
 
@@ -311,7 +317,8 @@
 	acpi_operand_object     *data_desc;
 
 
-	/* */
+	/* We only allow one attachment per handler */
+
 	prev_obj_desc = NULL;
 	obj_desc = node->object;
 	while (obj_desc) {
@@ -324,7 +331,6 @@
 		obj_desc = obj_desc->common.next_object;
 	}
 
-
 	/* Create an internal object for the data */
 
 	data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA);
@@ -335,7 +341,6 @@
 	data_desc->data.handler = handler;
 	data_desc->data.pointer = data;
 
-
 	/* Install the data object */
 
 	if (prev_obj_desc) {
@@ -353,11 +358,13 @@
  *
  * FUNCTION:    Acpi_ns_detach_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - Namespace node
+ *              Handler         - Handler associated with the data
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Low-level detach data.  Delete the data node, but the caller
+ *              is responsible for the actual data.
  *
  ******************************************************************************/
 
@@ -398,11 +405,14 @@
  *
  * FUNCTION:    Acpi_ns_get_attached_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - Namespace node
+ *              Handler         - Handler associated with the data
+ *              Data            - Where the data is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Low level interface to obtain data previously associated with
+ *              a namespace node.
  *
  ******************************************************************************/
 
diff -Nru a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
--- a/drivers/acpi/namespace/nsutils.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/namespace/nsutils.c	Sun Nov 17 20:30:14 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
  *                        parents and siblings and Scope manipulation
- *              $Revision: 115 $
+ *              $Revision: 116 $
  *
  *****************************************************************************/
 
@@ -45,7 +45,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print warning message
+ * DESCRIPTION: Print warning message with full pathname
  *
  ******************************************************************************/
 
@@ -61,12 +61,16 @@
 	char                    *name;
 
 
+	/* Convert path to external format */
+
 	status = acpi_ns_externalize_name (ACPI_UINT32_MAX, internal_name, NULL, &name);
 
 	acpi_os_printf ("%8s-%04d: *** Error: Looking up ",
 		module_name, line_number);
 
-	if (name) {
+	/* Print target name */
+
+	if (ACPI_SUCCESS (status)) {
 		acpi_os_printf ("[%s]", name);
 	}
 	else {
diff -Nru a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
--- a/drivers/acpi/namespace/nsxfeval.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/namespace/nsxfeval.c	Sun Nov 17 20:30:15 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
  *                         ACPI Object evaluation interfaces
- *              $Revision: 3 $
+ *              $Revision: 4 $
  *
  ******************************************************************************/
 
@@ -570,11 +570,13 @@
  *
  * FUNCTION:    Acpi_attach_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Obj_handle          - Namespace node
+ *              Handler             - Handler for this attachment
+ *              Data                - Pointer to data to be attached
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
  *
  ******************************************************************************/
 
@@ -621,11 +623,12 @@
  *
  * FUNCTION:    Acpi_detach_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Obj_handle          - Namespace node handle
+ *              Handler             - Handler used in call to Acpi_attach_data
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Remove data that was previously attached to a node.
  *
  ******************************************************************************/
 
@@ -670,11 +673,13 @@
  *
  * FUNCTION:    Acpi_get_data
  *
- * PARAMETERS:
+ * PARAMETERS:  Obj_handle          - Namespace node
+ *              Handler             - Handler used in call to Attach_data
+ *              Data                - Where the data is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
  *
  ******************************************************************************/
 
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/osl.c	Sun Nov 17 20:30:15 2002
@@ -702,7 +702,7 @@
 acpi_os_wait_semaphore(
 	acpi_handle		handle,
 	u32			units,
-	u32			timeout)
+	u16			timeout)
 {
 	acpi_status		status = AE_OK;
 	struct semaphore	*sem = (struct semaphore*)handle;
@@ -739,7 +739,7 @@
 		 * Wait Indefinitely:
 		 * ------------------
 		 */
-		case WAIT_FOREVER:
+		case ACPI_WAIT_FOREVER:
 		ret = down_interruptible(sem);
 		if (ret < 0)
 			status = AE_ERROR;
diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c
--- a/drivers/acpi/power.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/acpi/power.c	Sun Nov 17 20:30:14 2002
@@ -443,12 +443,6 @@
 	if (!device)
 		return_VALUE(-EINVAL);
 
-	if (!acpi_power_dir) {
-		acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir);
-		if (!acpi_power_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_power_dir);
@@ -478,9 +472,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
 
-	if (!acpi_power_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_power_dir);
 
@@ -590,6 +581,10 @@
 		return_VALUE(0);
 
 	INIT_LIST_HEAD(&acpi_power_resource_list);
+
+	acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir);
+	if (!acpi_power_dir)
+		return_VALUE(-ENODEV);
 
 	result = acpi_bus_register_driver(&acpi_power_driver);
 	if (result < 0) {
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/processor.c	Sun Nov 17 20:30:15 2002
@@ -2289,13 +2289,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
 
-	if (!acpi_processor_dir) {
-		acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, 
-			acpi_root_dir);
-		if (!acpi_processor_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_processor_dir);
@@ -2378,9 +2371,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
 
-	if (!acpi_processor_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
 
@@ -2640,9 +2630,15 @@
 	memset(&processors, 0, sizeof(processors));
 	memset(&errata, 0, sizeof(errata));
 
+	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+	if (!acpi_processor_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_processor_driver);
-	if (result < 0)
+	if (result < 0) {
+		remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
 		return_VALUE(-ENODEV);
+	}
 
 	return_VALUE(0);
 }
@@ -2651,13 +2647,11 @@
 static void __exit
 acpi_processor_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_processor_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_processor_driver);
-	if (!result)
-		remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_processor_driver);
+
+	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c
--- a/drivers/acpi/scan.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acpi/scan.c	Sun Nov 17 20:30:13 2002
@@ -258,6 +258,8 @@
 		return_VALUE(result);
 	}
 
+	device->driver = driver;
+
 	/*
 	 * TBD - Configuration Management: Assign resources to device based
 	 * upon possible configuration and currently allocated resources.
diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
--- a/drivers/acpi/tables/tbconvrt.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/acpi/tables/tbconvrt.c	Sun Nov 17 20:30:13 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbconvrt - ACPI Table conversion utilities
- *              $Revision: 44 $
+ *              $Revision: 45 $
  *
  *****************************************************************************/
 
@@ -36,11 +36,13 @@
  *
  * FUNCTION:    Acpi_tb_get_table_count
  *
- * PARAMETERS:
+ * PARAMETERS:  RSDP            - Pointer to the RSDP
+ *              RSDT            - Pointer to the RSDT/XSDT
  *
- * RETURN:
+ * RETURN:      The number of tables pointed to by the RSDT or XSDT.
  *
- * DESCRIPTION: Calculate the number of tables
+ * DESCRIPTION: Calculate the number of tables.  Automatically handles either
+ *              an RSDT or XSDT.
  *
  ******************************************************************************/
 
@@ -80,9 +82,9 @@
  *
  * FUNCTION:    Acpi_tb_convert_to_xsdt
  *
- * PARAMETERS:
+ * PARAMETERS:  Table_info      - Info about the RSDT
  *
- * RETURN:
+ * RETURN:      Status
  *
  * DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
  *
@@ -311,13 +313,11 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
- *    Converts a BIOS supplied ACPI 1.0 FADT to an intermediate
- *    ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
- *    copied to the intermediate FADT.  The ACPI CA software uses this
- *    intermediate FADT. Thus a significant amount of special #ifdef
- *    type codeing is saved. This intermediate FADT will need to be
- *    freed at some point.
+ * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
+ *              ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
+ *              copied to the local FADT.  The ACPI CA software uses this
+ *              local FADT. Thus a significant amount of special #ifdef
+ *              type codeing is saved.
  *
  ******************************************************************************/
 
diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
--- a/drivers/acpi/tables/tbxfroot.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/tables/tbxfroot.c	Sun Nov 17 20:30:15 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
- *              $Revision: 64 $
+ *              $Revision: 65 $
  *
  *****************************************************************************/
 
@@ -302,7 +302,8 @@
 
 	status = acpi_tb_find_rsdp (&table_info, flags);
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not found\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not found, %s Flags=%X\n",
+			acpi_format_exception (status), flags));
 		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 	}
 
@@ -406,6 +407,8 @@
 		status = acpi_os_map_memory ((u64) LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE,
 				  (void **) &table_ptr);
 		if (ACPI_FAILURE (status)) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+				LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE));
 			return_ACPI_STATUS (status);
 		}
 
@@ -428,6 +431,8 @@
 		status = acpi_os_map_memory ((u64) HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE,
 				  (void **) &table_ptr);
 		if (ACPI_FAILURE (status)) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+				HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE));
 			return_ACPI_STATUS (status);
 		}
 
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/acpi/thermal.c	Sun Nov 17 20:30:15 2002
@@ -1060,13 +1060,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
 
-	if (!acpi_thermal_dir) {
-		acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, 
-			acpi_root_dir);
-		if (!acpi_thermal_dir)
-			return_VALUE(-ENODEV);
-	}
-
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 			acpi_thermal_dir);
@@ -1147,9 +1140,6 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
 
-	if (!acpi_thermal_dir)
-		return_VALUE(-ENODEV);
-
 	if (acpi_device_dir(device))
 		remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
 
@@ -1351,9 +1341,15 @@
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_init");
 
+	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
+	if (!acpi_thermal_dir)
+		return_VALUE(-ENODEV);
+
 	result = acpi_bus_register_driver(&acpi_thermal_driver);
-	if (result < 0)
+	if (result < 0) {
+		remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
 		return_VALUE(-ENODEV);
+	}
 
 	return_VALUE(0);
 }
@@ -1362,13 +1358,11 @@
 static void __exit
 acpi_thermal_exit (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_thermal_exit");
 
-	result = acpi_bus_unregister_driver(&acpi_thermal_driver);
-	if (!result)
-		remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
+	acpi_bus_unregister_driver(&acpi_thermal_driver);
+
+	remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
 
 	return_VOID;
 }
diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
--- a/drivers/acpi/utilities/utmisc.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/acpi/utilities/utmisc.c	Sun Nov 17 20:30:03 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: utmisc - common utility procedures
- *              $Revision: 85 $
+ *              $Revision: 86 $
  *
  ******************************************************************************/
 
@@ -685,7 +685,7 @@
 			 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
 
 	status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex,
-			   1, WAIT_FOREVER);
+			   1, ACPI_WAIT_FOREVER);
 	if (ACPI_SUCCESS (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
 				 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
--- a/drivers/atm/idt77252.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/atm/idt77252.c	Sun Nov 17 20:30:14 2002
@@ -2148,9 +2148,9 @@
 
 	est->interval = 2;		/* XXX: make this configurable */
 	est->ewma_log = 2;		/* XXX: make this configurable */
+	init_timer(&est->timer);
 	est->timer.data = (unsigned long)vc;
 	est->timer.function = idt77252_est_timer;
-	init_timer(&est->timer);
 
 	est->timer.expires = jiffies + ((HZ / 4) << est->interval);
 	add_timer(&est->timer);
@@ -3745,9 +3745,9 @@
 	spin_lock_init(&card->cmd_lock);
 	spin_lock_init(&card->tst_lock);
 
+	init_timer(&card->tst_timer);
 	card->tst_timer.data = (unsigned long)card;
 	card->tst_timer.function = tst_timer;
-	init_timer(&card->tst_timer);
 
 	/* Do the I/O remapping... */
 	card->membase = (unsigned long) ioremap(membase, 1024);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/base/bus.c	Sun Nov 17 20:30:12 2002
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #include "base.h"
 
 static LIST_HEAD(bus_driver_list);
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/base/class.c	Sun Nov 17 20:30:16 2002
@@ -5,6 +5,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #include "base.h"
 
 static LIST_HEAD(class_list);
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/base/core.c	Sun Nov 17 20:30:02 2002
@@ -8,10 +8,14 @@
 #define DEBUG 0
 
 #include <linux/device.h>
-#include <linux/module.h>
-#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/semaphore.h>
+
 #include "base.h"
 
 LIST_HEAD(global_device_list);
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/base/driver.c	Sun Nov 17 20:30:15 2002
@@ -8,6 +8,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 #include "base.h"
 
 #define to_dev(node) container_of(node,struct device,driver_list)
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/base/interface.c	Sun Nov 17 20:30:03 2002
@@ -8,6 +8,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/stat.h>
+#include <linux/string.h>
 
 static ssize_t device_read_name(struct device * dev, char * buf, size_t count, loff_t off)
 {
diff -Nru a/drivers/base/intf.c b/drivers/base/intf.c
--- a/drivers/base/intf.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/base/intf.c	Sun Nov 17 20:30:15 2002
@@ -6,6 +6,7 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include "base.h"
 
 
diff -Nru a/drivers/base/power.c b/drivers/base/power.c
--- a/drivers/base/power.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/base/power.c	Sun Nov 17 20:30:14 2002
@@ -12,6 +12,7 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <asm/semaphore.h>
 #include "base.h"
 
 #define to_dev(node) container_of(node,struct device,g_list)
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/base/sys.c	Sun Nov 17 20:30:02 2002
@@ -13,11 +13,12 @@
 #define DEBUG 1
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/err.h>
+#include <linux/string.h>
 
 /* The default system device parent. */
 static struct device system_bus = {
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/DAC960.c	Sun Nov 17 20:30:15 2002
@@ -2913,7 +2913,7 @@
 
 static inline int DAC960_PartitionByCommand(DAC960_Command_T *Command)
 {
-	return DAC960_PartitionNumber(to_kdev_t(Command->BufferHeader->bi_bdev->bd_dev)); 
+	return (int)Command->BufferHeader->bi_bdev->bd_disk->private_data;
 }
 
 /*
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/block/amiflop.c	Sun Nov 17 20:30:14 2002
@@ -1586,7 +1586,6 @@
 	int drive = minor(inode->i_rdev) & 3;
 	int system =  (minor(inode->i_rdev) & 4) >> 2;
 	int old_dev;
-	int system;
 	unsigned long flags;
 
 	old_dev = fd_device[drive];
@@ -1621,7 +1620,7 @@
 	restore_flags(flags);
 
 	if (old_dev != system)
-		invalidate_buffers(mk_kdev(MAJOR_NR, drive + (system << 2));
+		invalidate_buffers(mk_kdev(MAJOR_NR, drive + (system << 2)));
 
 	unit[drive].dtype=&data_types[system];
 	unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/cciss.c	Sun Nov 17 20:30:15 2002
@@ -22,6 +22,7 @@
 
 #include <linux/config.h>	/* CONFIG_PROC_FS */
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/pci.h>
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/block/cpqarray.c	Sun Nov 17 20:30:03 2002
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/bio.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -309,7 +310,7 @@
 			put_disk(ida_gendisk[i][j]);
 		}
 	}
-	devfs_find_and_unregister(NULL, "ida", 0, 0, 0, 0);
+	devfs_remove("ida");
 	remove_proc_entry("cpqarray", proc_root_driver);
 }
 
@@ -436,7 +437,7 @@
 	printk( KERN_ERR "cpqarray: out of memory");
 
 	if (!num_cntlrs_reg) {
-		devfs_find_and_unregister(NULL,"ida",0,0,0,0);
+		devfs_remove("ida");
 		remove_proc_entry("cpqarray", proc_root_driver);
 		return -ENODEV;
 	}
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/block/floppy.c	Sun Nov 17 20:30:03 2002
@@ -151,6 +151,7 @@
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/version.h>
 #define FDPATCHES
 #include <linux/fdreg.h>
 
@@ -3299,7 +3300,7 @@
 static int invalidate_drive(struct block_device *bdev)
 {
 	/* invalidate the buffer track to force a reread */
-	set_bit(DRIVE(to_kdev_t(bdev->bd_dev)), &fake_change);
+	set_bit((int)bdev->bd_disk->private_data, &fake_change);
 	process_fd_request();
 	check_disk_change(bdev);
 	return 0;
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/block/ll_rw_blk.c	Sun Nov 17 20:30:03 2002
@@ -673,31 +673,22 @@
 	seg_size = nr_phys_segs = nr_hw_segs = 0;
 	bio_for_each_segment(bv, bio, i) {
 		if (bvprv && cluster) {
-			int phys, seg;
-
-			if (seg_size + bv->bv_len > q->max_segment_size) {
-				nr_phys_segs++;
+			if (seg_size + bv->bv_len > q->max_segment_size)
 				goto new_segment;
-			}
-
-			phys = BIOVEC_PHYS_MERGEABLE(bvprv, bv);
-			seg = BIOVEC_SEG_BOUNDARY(q, bvprv, bv);
-			if (!phys || !seg)
-				nr_phys_segs++;
-			if (!seg)
+			if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
 				goto new_segment;
-
-			if (!BIOVEC_VIRT_MERGEABLE(bvprv, bv))
+			if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
 				goto new_segment;
 
 			seg_size += bv->bv_len;
 			bvprv = bv;
 			continue;
-		} else {
-			nr_phys_segs++;
 		}
 new_segment:
-		nr_hw_segs++;
+		if (!bvprv || !BIOVEC_VIRT_MERGEABLE(bvprv, bv))
+			nr_hw_segs++;
+
+		nr_phys_segs++;
 		bvprv = bv;
 		seg_size = bv->bv_len;
 	}
@@ -1386,7 +1377,6 @@
 void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
 	int rw = rq_data_dir(rq);
-	unsigned int major, index;
 
 	if (!rq->rq_disk)
 		return;
@@ -1404,9 +1394,6 @@
 		disk_round_stats(rq->rq_disk);
 		rq->rq_disk->in_flight++;
 	}
-
-	major = rq->rq_disk->major;
-	index = rq->rq_disk->first_minor >> rq->rq_disk->minor_shift;
 }
 
 /*
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/block/loop.c	Sun Nov 17 20:30:14 2002
@@ -304,21 +304,16 @@
 {
 	struct lo_read_data cookie;
 	struct file *file;
-	int error;
+	int retval;
 
 	cookie.lo = lo;
 	cookie.data = kmap(bvec->bv_page) + bvec->bv_offset;
 	cookie.bsize = bsize;
-
-	/* umm, what does this lock actually try to protect? */
-	spin_lock_irq(&lo->lo_lock);
 	file = lo->lo_backing_file;
-	spin_unlock_irq(&lo->lo_lock);
-
-	error = file->f_op->sendfile(file, &pos, bvec->bv_len,
+	retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
 			lo_read_actor, &cookie);
 	kunmap(bvec->bv_page);
-	return error;
+	return (retval < 0)? retval: 0;
 }
 
 static int
diff -Nru a/drivers/block/paride/aten.c b/drivers/block/paride/aten.c
--- a/drivers/block/paride/aten.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/block/paride/aten.c	Sun Nov 17 20:30:02 2002
@@ -131,17 +131,8 @@
 
 }
 
-static void aten_init_proto( PIA *pi )
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void aten_release_proto( PIA *pi )
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol aten = {
+	.owner		= THIS_MODULE,
 	.name		= "aten",
 	.max_mode	= 2,
 	.epp_first	= 2,
@@ -154,8 +145,6 @@
 	.connect	= aten_connect,
 	.disconnect	= aten_disconnect,
 	.log_adapter	= aten_log_adapter,
-	.init_proto	= aten_init_proto,
-	.release_proto	= aten_release_proto,
 };
 
 static int __init aten_init(void)
diff -Nru a/drivers/block/paride/bpck.c b/drivers/block/paride/bpck.c
--- a/drivers/block/paride/bpck.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/bpck.c	Sun Nov 17 20:30:15 2002
@@ -443,17 +443,8 @@
 		pi->mode,mode_string[pi->mode],pi->delay);
 }
 
-static void bpck_init_proto( PIA *pi)
-
-{	MOD_INC_USE_COUNT;
-}
-
-static void bpck_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol bpck = {
+	.owner		= THIS_MODULE,
 	.name		= "bpck",
 	.max_mode	= 5,
 	.epp_first	= 2,
@@ -469,8 +460,6 @@
 	.probe_unit	= bpck_probe_unit,
 	.test_proto	= bpck_test_proto,
 	.log_adapter	= bpck_log_adapter,
-	.init_proto	= bpck_init_proto,
-	.release_proto	= bpck_release_proto,
 };
 
 static int __init bpck_init(void)
diff -Nru a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c
--- a/drivers/block/paride/bpck6.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/block/paride/bpck6.c	Sun Nov 17 20:30:14 2002
@@ -222,38 +222,27 @@
 		pi->unit,pi->mode,mode_string[pi->mode],pi->delay);
 }
 
-static void bpck6_init_proto(PIA *pi)
+static int bpck6_init_proto(PIA *pi)
 {
-	int i;
+	PPC *p = kmalloc(sizeof(PPC), GFP_KERNEL);
 
-	/* allocate a state structure for this item */
-	pi->private=(int)kmalloc(sizeof(PPC),GFP_KERNEL);
-
-	if(pi->private==(int)NULL)
-	{
-		printk(KERN_ERR "%s: ERROR COULDN'T ALLOCATE MEMORY\n",pi->device); 
-		return;
-	}
-	else
-	{	
-		MOD_INC_USE_COUNT; 
+	if (p) {
+		memset(p, 0, sizeof(PPC));
+		pi->private = (int)p;
+		return 0;
 	}
 
-	for(i=0;i<sizeof(PPC);i++)
-	{
-		((unsigned char *)(pi->private))[i]=0;
-	}
+	printk(KERN_ERR "%s: ERROR COULDN'T ALLOCATE MEMORY\n", pi->device); 
+	return -1;
 }
 
 static void bpck6_release_proto(PIA *pi)
 {
-	MOD_DEC_USE_COUNT;
-	/* free after use count decremented so that we aren't using it
-		when it is decremented */
 	kfree((void *)(pi->private)); 
 }
 
 static struct pi_protocol bpck6 = {
+	.owner		= THIS_MODULE,
 	.name		= "bpck6",
 	.max_mode	= 5,
 	.epp_first	= 2, /* 2-5 use epp (need 8 ports) */
diff -Nru a/drivers/block/paride/comm.c b/drivers/block/paride/comm.c
--- a/drivers/block/paride/comm.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/block/paride/comm.c	Sun Nov 17 20:30:12 2002
@@ -187,17 +187,8 @@
 
 }
 
-static void comm_init_proto(PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void comm_release_proto(PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol comm = {
+	.owner		= THIS_MODULE,
 	.name		= "comm",
 	.max_mode	= 5,
 	.epp_first	= 2,
@@ -210,8 +201,6 @@
 	.connect	= comm_connect,
 	.disconnect	= comm_disconnect,
 	.log_adapter	= comm_log_adapter,
-	.init_proto	= comm_init_proto,
-	.release_proto	= comm_release_proto,
 };
 
 static int __init comm_init(void)
diff -Nru a/drivers/block/paride/dstr.c b/drivers/block/paride/dstr.c
--- a/drivers/block/paride/dstr.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/dstr.c	Sun Nov 17 20:30:15 2002
@@ -202,17 +202,8 @@
 
 }
 
-static void dstr_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void dstr_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol dstr = {
+	.owner		= THIS_MODULE,
 	.name		= "dstr",
 	.max_mode	= 5,
 	.epp_first	= 2,
@@ -225,8 +216,6 @@
 	.connect	= dstr_connect,
 	.disconnect	= dstr_disconnect,
 	.log_adapter	= dstr_log_adapter,
-	.init_proto	= dstr_init_proto,
-	.release_proto	= dstr_release_proto,
 };
 
 static int __init dstr_init(void)
diff -Nru a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c
--- a/drivers/block/paride/epat.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/block/paride/epat.c	Sun Nov 17 20:30:16 2002
@@ -301,17 +301,8 @@
 
 }
 
-static void epat_init_proto( PIA *pi)
-
-{  	MOD_INC_USE_COUNT;
-}
-
-static void epat_release_proto( PIA *pi)
-
-{	MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol epat = {
+	.owner		= THIS_MODULE,
 	.name		= "epat",
 	.max_mode	= 6,
 	.epp_first	= 3,
@@ -325,8 +316,6 @@
 	.disconnect	= epat_disconnect,
 	.test_proto	= epat_test_proto,
 	.log_adapter	= epat_log_adapter,
-	.init_proto	= epat_init_proto,
-	.release_proto	= epat_release_proto,
 };
 
 static int __init epat_init(void)
diff -Nru a/drivers/block/paride/epia.c b/drivers/block/paride/epia.c
--- a/drivers/block/paride/epia.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/block/paride/epia.c	Sun Nov 17 20:30:12 2002
@@ -284,17 +284,8 @@
 
 }
 
-static void epia_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void epia_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol epia = {
+	.owner		= THIS_MODULE,
 	.name		= "epia",
 	.max_mode	= 6,
 	.epp_first	= 3,
@@ -308,8 +299,6 @@
 	.disconnect	= epia_disconnect,
 	.test_proto	= epia_test_proto,
 	.log_adapter	= epia_log_adapter,
-	.init_proto	= epia_init_proto,
-	.release_proto	= epia_release_proto,
 };
 
 static int __init epia_init(void)
diff -Nru a/drivers/block/paride/fit2.c b/drivers/block/paride/fit2.c
--- a/drivers/block/paride/fit2.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/block/paride/fit2.c	Sun Nov 17 20:30:14 2002
@@ -120,17 +120,8 @@
 
 }
 
-static void fit2_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void fit2_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol fit2 = {
+	.owner		= THIS_MODULE,
 	.name		= "fit2",
 	.max_mode	= 1,
 	.epp_first	= 2,
@@ -143,8 +134,6 @@
 	.connect	= fit2_connect,
 	.disconnect	= fit2_disconnect,
 	.log_adapter	= fit2_log_adapter,
-	.init_proto	= fit2_init_proto,
-	.release_proto	= fit2_release_proto,
 };
 
 static int __init fit2_init(void)
diff -Nru a/drivers/block/paride/fit3.c b/drivers/block/paride/fit3.c
--- a/drivers/block/paride/fit3.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/fit3.c	Sun Nov 17 20:30:15 2002
@@ -180,17 +180,8 @@
 
 }
 
-static void fit3_init_proto(PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void fit3_release_proto(PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol fit3 = {
+	.owner		= THIS_MODULE,
 	.name		= "fit3",
 	.max_mode	= 3,
 	.epp_first	= 2,
@@ -203,8 +194,6 @@
 	.connect	= fit3_connect,
 	.disconnect	= fit3_disconnect,
 	.log_adapter	= fit3_log_adapter,
-	.init_proto	= fit3_init_proto,
-	.release_proto	= fit3_release_proto,
 };
 
 static int __init fit3_init(void)
diff -Nru a/drivers/block/paride/friq.c b/drivers/block/paride/friq.c
--- a/drivers/block/paride/friq.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/friq.c	Sun Nov 17 20:30:15 2002
@@ -233,25 +233,18 @@
 
 }
 
-static void friq_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-	pi->private = 0;
-}
-
 static void friq_release_proto( PIA *pi)
-
-{       if (pi->private) {		/* turn off the power */
+{
+	if (pi->private) {		/* turn off the power */
 		friq_connect(pi);
 		CMD(0x1d); CMD(0x1e);
 		friq_disconnect(pi);
 		pi->private = 0;
 	}
-
-	MOD_DEC_USE_COUNT;
 }
 
 static struct pi_protocol friq = {
+	.owner		= THIS_MODULE,
 	.name		= "friq",
 	.max_mode	= 5,
 	.epp_first	= 2,
@@ -265,7 +258,6 @@
 	.disconnect	= friq_disconnect,
 	.test_proto	= friq_test_proto,
 	.log_adapter	= friq_log_adapter,
-	.init_proto	= friq_init_proto,
 	.release_proto	= friq_release_proto,
 };
 
diff -Nru a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
--- a/drivers/block/paride/frpw.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/frpw.c	Sun Nov 17 20:30:15 2002
@@ -281,18 +281,8 @@
 
 }
 
-static void frpw_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-	pi->private = 0;
-}
-
-static void frpw_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol frpw = {
+	.owner		= THIS_MODULE,
 	.name		= "frpw",
 	.max_mode	= 6,
 	.epp_first	= 2,
@@ -306,8 +296,6 @@
 	.disconnect	= frpw_disconnect,
 	.test_proto	= frpw_test_proto,
 	.log_adapter	= frpw_log_adapter,
-	.init_proto	= frpw_init_proto,
-	.release_proto	= frpw_release_proto,
 };
 
 static int __init frpw_init(void)
diff -Nru a/drivers/block/paride/kbic.c b/drivers/block/paride/kbic.c
--- a/drivers/block/paride/kbic.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/kbic.c	Sun Nov 17 20:30:15 2002
@@ -249,17 +249,8 @@
 {       kbic_log_adapter(pi,scratch,verbose,"KBIC-971A");
 }
 
-static void kbic_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void kbic_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol k951 = {
+	.owner		= THIS_MODULE,
 	.name		= "k951",
 	.max_mode	= 6,
 	.epp_first	= 3,
@@ -272,11 +263,10 @@
 	.connect	= k951_connect,
 	.disconnect	= k951_disconnect,
 	.log_adapter	= k951_log_adapter,
-	.init_proto	= kbic_init_proto,
-	.release_proto	= kbic_release_proto
 };
 
 static struct pi_protocol k971 = {
+	.owner		= THIS_MODULE,
 	.name		= "k971",
 	.max_mode	= 6,
 	.epp_first	= 3,
@@ -289,8 +279,6 @@
 	.connect	= k971_connect,
 	.disconnect	= k971_disconnect,
 	.log_adapter	= k971_log_adapter,
-	.init_proto	= kbic_init_proto,
-	.release_proto	= kbic_release_proto
 };
 
 static int __init kbic_init(void)
diff -Nru a/drivers/block/paride/ktti.c b/drivers/block/paride/ktti.c
--- a/drivers/block/paride/ktti.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/block/paride/ktti.c	Sun Nov 17 20:30:12 2002
@@ -97,17 +97,8 @@
 
 }
 
-static void ktti_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void ktti_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol ktti = {
+	.owner		= THIS_MODULE,
 	.name		= "ktti",
 	.max_mode	= 1,
 	.epp_first	= 2,
@@ -120,8 +111,6 @@
 	.connect	= ktti_connect,
 	.disconnect	= ktti_disconnect,
 	.log_adapter	= ktti_log_adapter,
-	.init_proto	= ktti_init_proto,
-	.release_proto	= ktti_release_proto,
 };
 
 static int __init ktti_init(void)
diff -Nru a/drivers/block/paride/on20.c b/drivers/block/paride/on20.c
--- a/drivers/block/paride/on20.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/on20.c	Sun Nov 17 20:30:15 2002
@@ -122,17 +122,8 @@
 
 }
 
-static void on20_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void on20_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol on20 = {
+	.owner		= THIS_MODULE,
 	.name		= "on20",
 	.max_mode	= 2,
 	.epp_first	= 2,
@@ -145,8 +136,6 @@
 	.connect	= on20_connect,
 	.disconnect	= on20_disconnect,
 	.log_adapter	= on20_log_adapter,
-	.init_proto	= on20_init_proto,
-	.release_proto	= on20_release_proto,
 };
 
 static int __init on20_init(void)
diff -Nru a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
--- a/drivers/block/paride/on26.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/paride/on26.c	Sun Nov 17 20:30:15 2002
@@ -287,17 +287,8 @@
 
 }
 
-static void on26_init_proto( PIA *pi)
-
-{       MOD_INC_USE_COUNT;
-}
-
-static void on26_release_proto( PIA *pi)
-
-{       MOD_DEC_USE_COUNT;
-}
-
 static struct pi_protocol on26 = {
+	.owner		= THIS_MODULE,
 	.name		= "on26",
 	.max_mode	= 5,
 	.epp_first	= 2,
@@ -311,8 +302,6 @@
 	.disconnect	= on26_disconnect,
 	.test_port	= on26_test_port,
 	.log_adapter	= on26_log_adapter,
-	.init_proto	= on26_init_proto,
-	.release_proto	= on26_release_proto,
 };
 
 static int __init on26_init(void)
diff -Nru a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
--- a/drivers/block/paride/paride.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/block/paride/paride.c	Sun Nov 17 20:30:03 2002
@@ -42,47 +42,47 @@
 
 #define MAX_PROTOS	32
 
-static struct pi_protocol	*protocols[MAX_PROTOS];
+static struct pi_protocol *protocols[MAX_PROTOS];
 
-static spinlock_t	pi_spinlock = SPIN_LOCK_UNLOCKED;
+static spinlock_t pi_spinlock = SPIN_LOCK_UNLOCKED;
 
-void pi_write_regr( PIA *pi, int cont, int regr, int val)
-
-{	pi->proto->write_regr(pi,cont,regr,val);
+void pi_write_regr(PIA * pi, int cont, int regr, int val)
+{
+	pi->proto->write_regr(pi, cont, regr, val);
 }
 
 EXPORT_SYMBOL(pi_write_regr);
 
-int pi_read_regr( PIA *pi, int cont, int regr)
-
-{	return pi->proto->read_regr(pi,cont,regr);
+int pi_read_regr(PIA * pi, int cont, int regr)
+{
+	return pi->proto->read_regr(pi, cont, regr);
 }
 
 EXPORT_SYMBOL(pi_read_regr);
 
-void pi_write_block( PIA *pi, char * buf, int count)
-
-{	pi->proto->write_block(pi,buf,count);
+void pi_write_block(PIA * pi, char *buf, int count)
+{
+	pi->proto->write_block(pi, buf, count);
 }
 
 EXPORT_SYMBOL(pi_write_block);
 
-void pi_read_block( PIA *pi, char * buf, int count)
-
-{       pi->proto->read_block(pi,buf,count);
+void pi_read_block(PIA * pi, char *buf, int count)
+{
+	pi->proto->read_block(pi, buf, count);
 }
 
 EXPORT_SYMBOL(pi_read_block);
 
 #ifdef CONFIG_PARPORT
 
-static void pi_wake_up( void *p)
-
-{       PIA  *pi = (PIA *) p;
+static void pi_wake_up(void *p)
+{
+	PIA *pi = (PIA *) p;
 	unsigned long flags;
-	void (*cont)(void) = NULL;
+	void (*cont) (void) = NULL;
 
-	spin_lock_irqsave(&pi_spinlock,flags);
+	spin_lock_irqsave(&pi_spinlock, flags);
 
 	if (pi->claim_cont && !parport_claim(pi->pardev)) {
 		cont = pi->claim_cont;
@@ -90,147 +90,150 @@
 		pi->claimed = 1;
 	}
 
-	spin_unlock_irqrestore(&pi_spinlock,flags);	
+	spin_unlock_irqrestore(&pi_spinlock, flags);
 
 	wake_up(&(pi->parq));
 
-	if (cont) cont();
+	if (cont)
+		cont();
 }
 
 #endif
 
-void pi_do_claimed( PIA *pi, void(*cont)(void))
-
+void pi_do_claimed(PIA * pi, void (*cont) (void))
+{
 #ifdef CONFIG_PARPORT
+	unsigned long flags;
 
-{	unsigned long flags;
-
-	spin_lock_irqsave(&pi_spinlock,flags); 
-
-	if (!pi->pardev || !parport_claim(pi->pardev)) {
-		pi->claimed = 1;
-		spin_unlock_irqrestore(&pi_spinlock,flags);
-		cont();
-	} else {
+	spin_lock_irqsave(&pi_spinlock, flags);
+	if (pi->pardev && parport_claim(pi->pardev)) {
 		pi->claim_cont = cont;
-		spin_unlock_irqrestore(&pi_spinlock,flags);	
+		spin_unlock_irqrestore(&pi_spinlock, flags);
+		return;
 	}
-}
-
-#else
-
-{	cont();
-}
-
+	pi->claimed = 1;
+	spin_unlock_irqrestore(&pi_spinlock, flags);
 #endif
+	cont();
+}
 
 EXPORT_SYMBOL(pi_do_claimed);
 
-static void pi_claim( PIA *pi)
-
-{	if (pi->claimed) return;
+static void pi_claim(PIA * pi)
+{
+	if (pi->claimed)
+		return;
 	pi->claimed = 1;
 #ifdef CONFIG_PARPORT
-        if (pi->pardev)
-		wait_event (pi->parq,
-			    !parport_claim ((struct pardevice *)pi->pardev));
+	if (pi->pardev)
+		wait_event(pi->parq,
+			   !parport_claim((struct pardevice *) pi->pardev));
 #endif
 }
 
-static void pi_unclaim( PIA *pi)
-
-{	pi->claimed = 0;
+static void pi_unclaim(PIA * pi)
+{
+	pi->claimed = 0;
 #ifdef CONFIG_PARPORT
-        if (pi->pardev) parport_release((struct pardevice *)(pi->pardev));
-#endif 
+	if (pi->pardev)
+		parport_release((struct pardevice *) (pi->pardev));
+#endif
 }
 
-void pi_connect( PIA *pi)
-
-{	pi_claim(pi);
+void pi_connect(PIA * pi)
+{
+	pi_claim(pi);
 	pi->proto->connect(pi);
 }
 
 EXPORT_SYMBOL(pi_connect);
 
-void pi_disconnect( PIA *pi)
-
-{	pi->proto->disconnect(pi);
+void pi_disconnect(PIA * pi)
+{
+	pi->proto->disconnect(pi);
 	pi_unclaim(pi);
 }
 
 EXPORT_SYMBOL(pi_disconnect);
 
-static void pi_unregister_parport( PIA *pi)
-
+static void pi_unregister_parport(PIA * pi)
 {
 #ifdef CONFIG_PARPORT
-        if (pi->pardev) {
-           parport_unregister_device((struct pardevice *)(pi->pardev));
-	   pi->pardev = NULL;
+	if (pi->pardev) {
+		parport_unregister_device((struct pardevice *) (pi->pardev));
+		pi->pardev = NULL;
 	}
 #endif
 }
 
-void pi_release( PIA *pi)
-
-{	pi_unregister_parport(pi);
+void pi_release(PIA * pi)
+{
+	pi_unregister_parport(pi);
 #ifndef CONFIG_PARPORT
 	if (pi->reserved)
-		release_region(pi->port,pi->reserved);
-#endif /* !CONFIG_PARPORT */
-	pi->proto->release_proto(pi);
+		release_region(pi->port, pi->reserved);
+#endif				/* !CONFIG_PARPORT */
+	if (pi->proto->release_proto)
+		pi->proto->release_proto(pi);
+	if (pi->proto->owner)
+		__MOD_DEC_USE_COUNT(pi->proto->owner);
 }
 
 EXPORT_SYMBOL(pi_release);
 
-#define WR(r,v)         pi_write_regr(pi,0,r,v)
-#define RR(r)           (pi_read_regr(pi,0,r))
-
-static int pi_test_proto( PIA *pi, char * scratch, int verbose )
+static int default_test_proto(PIA * pi, char *scratch, int verbose)
+{
+	int j, k;
+	int e[2] = { 0, 0 };
 
-{       int     j, k;
-        int     e[2] = {0,0};
+	pi->proto->connect(pi);
 
-	if (pi->proto->test_proto) {
-		pi_claim(pi);
-		j = pi->proto->test_proto(pi,scratch,verbose);
-		pi_unclaim(pi);
-		return j;
+	for (j = 0; j < 2; j++) {
+		pi_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
+		for (k = 0; k < 256; k++) {
+			pi_write_regr(pi, 0, 2, k ^ 0xaa);
+			pi_write_regr(pi, 0, 3, k ^ 0x55);
+			if (pi_read_regr(pi, 0, 2) != (k ^ 0xaa))
+				e[j]++;
+		}
 	}
+	pi->proto->disconnect(pi);
 
-        pi_connect(pi);
+	if (verbose)
+		printk("%s: %s: port 0x%x, mode  %d, test=(%d,%d)\n",
+		       pi->device, pi->proto->name, pi->port,
+		       pi->mode, e[0], e[1]);
 
-        for (j=0;j<2;j++) {
-                WR(6,0xa0+j*0x10);
-                for (k=0;k<256;k++) {
-                        WR(2,k^0xaa);
-                        WR(3,k^0x55);
-                        if (RR(2) != (k^0xaa)) e[j]++;
-                        }
-                }
+	return (e[0] && e[1]);	/* not here if both > 0 */
+}
 
-        pi_disconnect(pi);
+static int pi_test_proto(PIA * pi, char *scratch, int verbose)
+{
+	int res;
 
-        if (verbose)
-                printk("%s: %s: port 0x%x, mode  %d, test=(%d,%d)\n",
-                        pi->device,pi->proto->name,pi->port,
-			pi->mode,e[0],e[1]);
+	pi_claim(pi);
+	if (pi->proto->test_proto)
+		res = pi->proto->test_proto(pi, scratch, verbose);
+	else
+		res = default_test_proto(pi, scratch, verbose);
+	pi_unclaim(pi);
 
-        return (e[0] && e[1]);  /* not here if both > 0 */
+	return res;
 }
 
-int  pi_register( PIP *pr)
-
-{	int k;
+int pi_register(PIP * pr)
+{
+	int k;
 
-	for (k=0;k<MAX_PROTOS;k++) 
-	   if (protocols[k] && !strcmp(pr->name,protocols[k]->name)) {
-		printk("paride: %s protocol already registered\n",pr->name);
-		return 0;
-	   }
+	for (k = 0; k < MAX_PROTOS; k++)
+		if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) {
+			printk("paride: %s protocol already registered\n",
+			       pr->name);
+			return 0;
+		}
 	k = 0;
-	while((k<MAX_PROTOS) && (protocols[k])) k++;
+	while ((k < MAX_PROTOS) && (protocols[k]))
+		k++;
 	if (k == MAX_PROTOS) {
 		printk("paride: protocol table full\n");
 		return 0;
@@ -238,151 +241,171 @@
 	MOD_INC_USE_COUNT;
 	protocols[k] = pr;
 	pr->index = k;
-	printk("paride: %s registered as protocol %d\n",pr->name,k);
+	printk("paride: %s registered as protocol %d\n", pr->name, k);
 	return 1;
-}	
+}
 
 EXPORT_SYMBOL(pi_register);
 
-void pi_unregister( PIP *pr)
-
-{	if (!pr) return;
+void pi_unregister(PIP * pr)
+{
+	if (!pr)
+		return;
 	if (protocols[pr->index] != pr) {
-		printk("paride: %s not registered\n",pr->name);
+		printk("paride: %s not registered\n", pr->name);
 		return;
-	} 
+	}
 	protocols[pr->index] = 0;
 	MOD_DEC_USE_COUNT;
 }
 
 EXPORT_SYMBOL(pi_unregister);
 
-static int pi_register_parport( PIA *pi, int verbose)
-
+static int pi_register_parport(PIA * pi, int verbose)
 {
 #ifdef CONFIG_PARPORT
 
 	struct parport *port;
 
-	port = parport_find_base (pi->port);
+	port = parport_find_base(pi->port);
 	if (!port)
-	  return 0;
+		return 0;
 
 	pi->pardev = parport_register_device(port,
-					     pi->device,NULL,
-					     pi_wake_up,NULL,
-					     0,(void *)pi);
-	parport_put_port (port);
+					     pi->device, NULL,
+					     pi_wake_up, NULL, 0, (void *) pi);
+	parport_put_port(port);
 	if (!pi->pardev)
-	  return 0;
+		return 0;
 
 	init_waitqueue_head(&pi->parq);
 
-	if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,
-			    port->name);
-	
-	pi->parname = (char *)port->name;
+	if (verbose)
+		printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name);
+
+	pi->parname = (char *) port->name;
 #endif
 
 	return 1;
 }
 
-static int pi_probe_mode( PIA *pi, int max, char * scratch, int verbose)
-
-{	int	best, range;
+static int pi_probe_mode(PIA * pi, int max, char *scratch, int verbose)
+{
+	int best, range;
 
 	if (pi->mode != -1) {
-		if (pi->mode >= max) return 0;
+		if (pi->mode >= max)
+			return 0;
 		range = 3;
-		if (pi->mode >= pi->proto->epp_first) range = 8;
-		if ((range == 8) && (pi->port % 8)) return 0;
+		if (pi->mode >= pi->proto->epp_first)
+			range = 8;
+		if ((range == 8) && (pi->port % 8))
+			return 0;
 		pi->reserved = range;
-		return (!pi_test_proto(pi,scratch,verbose));
+		return (!pi_test_proto(pi, scratch, verbose));
 	}
 	best = -1;
-	for(pi->mode=0;pi->mode<max;pi->mode++) {
+	for (pi->mode = 0; pi->mode < max; pi->mode++) {
 		range = 3;
-		if (pi->mode >= pi->proto->epp_first) range = 8;
-		if ((range == 8) && (pi->port % 8)) break;
+		if (pi->mode >= pi->proto->epp_first)
+			range = 8;
+		if ((range == 8) && (pi->port % 8))
+			break;
 		pi->reserved = range;
-		if (!pi_test_proto(pi,scratch,verbose)) best = pi->mode;
+		if (!pi_test_proto(pi, scratch, verbose))
+			best = pi->mode;
 	}
 	pi->mode = best;
 	return (best > -1);
 }
 
-static int pi_probe_unit( PIA *pi, int unit, char * scratch, int verbose)
-
-{	int max,s,e;
+static int pi_probe_unit(PIA * pi, int unit, char *scratch, int verbose)
+{
+	int max, s, e;
 
-	s = unit; e = s+1;
+	s = unit;
+	e = s + 1;
 
-	if (s == -1) { 
-		s = 0; 
-		e = pi->proto->max_units; 
+	if (s == -1) {
+		s = 0;
+		e = pi->proto->max_units;
 	}
 
-	if (!pi_register_parport(pi,verbose))
-	  return 0;
+	if (!pi_register_parport(pi, verbose))
+		return 0;
 
 	if (pi->proto->test_port) {
 		pi_claim(pi);
 		max = pi->proto->test_port(pi);
 		pi_unclaim(pi);
-	}
-	else max = pi->proto->max_mode;
+	} else
+		max = pi->proto->max_mode;
 
 	if (pi->proto->probe_unit) {
-	   pi_claim(pi);
-	   for (pi->unit=s;pi->unit<e;pi->unit++)
-	      if (pi->proto->probe_unit(pi)) {
-		 pi_unclaim(pi);
-		 if (pi_probe_mode(pi,max,scratch,verbose)) return 1;
-	         pi_unregister_parport(pi); 
-		 return 0;
-	         }
-	   pi_unclaim(pi);
-	   pi_unregister_parport(pi); 
-	   return 0;
-	   }
-
-	if (!pi_probe_mode(pi,max,scratch,verbose)) {
-	   pi_unregister_parport(pi); 
-	   return 0;
+		pi_claim(pi);
+		for (pi->unit = s; pi->unit < e; pi->unit++)
+			if (pi->proto->probe_unit(pi)) {
+				pi_unclaim(pi);
+				if (pi_probe_mode(pi, max, scratch, verbose))
+					return 1;
+				pi_unregister_parport(pi);
+				return 0;
+			}
+		pi_unclaim(pi);
+		pi_unregister_parport(pi);
+		return 0;
+	}
+
+	if (!pi_probe_mode(pi, max, scratch, verbose)) {
+		pi_unregister_parport(pi);
+		return 0;
 	}
 	return 1;
-		
-}
 
-int pi_init(PIA *pi, int autoprobe, int port, int mode, 
-	    int unit, int protocol, int delay, char * scratch, 
-	    int devtype, int verbose, char *device )
+}
 
-{	int p,k,s,e;
-	int lpts[7] = {0x3bc,0x378,0x278,0x268,0x27c,0x26c,0};
+int pi_init(PIA * pi, int autoprobe, int port, int mode,
+	int unit, int protocol, int delay, char *scratch,
+	int devtype, int verbose, char *device)
+{
+	int p, k, s, e;
+	int lpts[7] = { 0x3bc, 0x378, 0x278, 0x268, 0x27c, 0x26c, 0 };
 
-	s = protocol; e = s+1;
+	s = protocol;
+	e = s + 1;
 
 	if (!protocols[0])
-		request_module ("paride_protocol");
+		request_module("paride_protocol");
 
 	if (autoprobe) {
-		s = 0; 
+		s = 0;
 		e = MAX_PROTOS;
 	} else if ((s < 0) || (s >= MAX_PROTOS) || (port <= 0) ||
-		    (!protocols[s]) || (unit < 0) || 
-		    (unit >= protocols[s]->max_units)) {
-			printk("%s: Invalid parameters\n",device);
-			return 0;
-		        }
+		   (!protocols[s]) || (unit < 0) ||
+		   (unit >= protocols[s]->max_units)) {
+		printk("%s: Invalid parameters\n", device);
+		return 0;
+	}
 
-	for (p=s;p<e;p++) {
-	  if (protocols[p]) {
-		pi->proto = protocols[p];
+	for (p = s; p < e; p++) {
+		struct pi_protocol *proto = protocols[p];
+		if (!proto)
+			continue;
+		/* still racy */
+		if (proto->owner)
+			__MOD_INC_USE_COUNT(proto->owner);
+		pi->proto = proto;
 		pi->private = 0;
-		pi->proto->init_proto(pi);
-		if (delay == -1) pi->delay = pi->proto->default_delay;
-		  else pi->delay = delay;
+		if (proto->init_proto && proto->init_proto(pi) < 0) {
+			pi->proto = NULL;
+			if (proto->owner)
+				__MOD_DEC_USE_COUNT(proto->owner);
+			continue;
+		}
+		if (delay == -1)
+			pi->delay = pi->proto->default_delay;
+		else
+			pi->delay = delay;
 		pi->devtype = devtype;
 		pi->device = device;
 
@@ -391,41 +414,48 @@
 		init_waitqueue_head(&pi->parq);
 		pi->claimed = 0;
 		pi->claim_cont = NULL;
-	        
+
 		pi->mode = mode;
 		if (port != -1) {
 			pi->port = port;
-			if (pi_probe_unit(pi,unit,scratch,verbose)) break;
+			if (pi_probe_unit(pi, unit, scratch, verbose))
+				break;
 			pi->port = 0;
-		} else { 
+		} else {
 			k = 0;
 			while ((pi->port = lpts[k++]))
-			   if (pi_probe_unit(pi,unit,scratch,verbose)) break;
-      			if (pi->port) break;
+				if (pi_probe_unit
+				    (pi, unit, scratch, verbose))
+					break;
+			if (pi->port)
+				break;
 		}
-		pi->proto->release_proto(pi);
-	  }
+		if (pi->proto->release_proto)
+			pi->proto->release_proto(pi);
+		if (proto->owner)
+			__MOD_DEC_USE_COUNT(proto->owner);
 	}
 
 	if (!pi->port) {
-		if (autoprobe) printk("%s: Autoprobe failed\n",device);
-		else printk("%s: Adapter not found\n",device);
+		if (autoprobe)
+			printk("%s: Autoprobe failed\n", device);
+		else
+			printk("%s: Adapter not found\n", device);
 		return 0;
 	}
-
 #ifndef CONFIG_PARPORT
-	if (!request_region(pi->port,pi->reserved,pi->device))
-		{
-		printk(KERN_WARNING"paride: Unable to request region 0x%x\n", pi->port);
+	if (!request_region(pi->port, pi->reserved, pi->device)) {
+		printk(KERN_WARNING "paride: Unable to request region 0x%x\n",
+		       pi->port);
 		return 0;
-		}
-#endif /* !CONFIG_PARPORT */
+	}
+#endif				/* !CONFIG_PARPORT */
 
 	if (pi->parname)
-	   printk("%s: Sharing %s at 0x%x\n",pi->device,
-			pi->parname,pi->port);
+		printk("%s: Sharing %s at 0x%x\n", pi->device,
+		       pi->parname, pi->port);
 
-	pi->proto->log_adapter(pi,scratch,verbose);
+	pi->proto->log_adapter(pi, scratch, verbose);
 
 	return 1;
 }
diff -Nru a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h
--- a/drivers/block/paride/paride.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/block/paride/paride.h	Sun Nov 17 20:30:12 2002
@@ -155,8 +155,9 @@
 	int  (*test_proto)(PIA *,char *,int);
 	void (*log_adapter)(PIA *,char *,int);
 	
-	void (*init_proto)(PIA *);
+	int (*init_proto)(PIA *);
 	void (*release_proto)(PIA *);
+	struct module *owner;
 };
 
 typedef struct pi_protocol PIP;
diff -Nru a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
--- a/drivers/block/paride/pseudo.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/block/paride/pseudo.h	Sun Nov 17 20:30:12 2002
@@ -33,114 +33,69 @@
 #define PS_VERSION	"1.02"
 
 #include <linux/sched.h>
-#include <linux/timer.h>
 #include <linux/workqueue.h>
 
-static void ps_timer_int( unsigned long data);
 static void ps_tq_int( void *data);
 
 static void (* ps_continuation)(void);
 static int (* ps_ready)(void);
-static int ps_then;
 static int ps_timeout;
-static int ps_timer_active = 0;
 static int ps_tq_active = 0;
 static int ps_nice = 0;
 
 static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;
 
-static struct timer_list ps_timer = TIMER_INITIALIZER(ps_timer_int, 0, 0);
 static DECLARE_WORK(ps_tq, ps_tq_int, NULL);
 
-static void ps_set_intr( void (*continuation)(void), 
-			 int (*ready)(void),
-			 int timeout, int nice )
-
-{       unsigned long	flags;
+static void ps_set_intr(void (*continuation)(void), 
+			int (*ready)(void),
+			int timeout, int nice)
+{
+	unsigned long	flags;
 
 	spin_lock_irqsave(&ps_spinlock,flags);
 
 	ps_continuation = continuation;
 	ps_ready = ready;
-        ps_then = jiffies;
 	ps_timeout = jiffies + timeout;
 	ps_nice = nice;
 
-        if (!ps_nice && !ps_tq_active) {
-#ifdef HAVE_DISABLE_HLT
-                disable_hlt();
-#endif
+	if (!ps_tq_active) {
 		ps_tq_active = 1;
-                schedule_work(&ps_tq);
+		if (!ps_nice)
+			schedule_work(&ps_tq);
+		else
+			schedule_delayed_work(&ps_tq, ps_nice-1);
 	}
-
-        if (!ps_timer_active) {
-		ps_timer_active = 1;
-                ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
-                add_timer(&ps_timer);
-        }
-
 	spin_unlock_irqrestore(&ps_spinlock,flags);
 }
 
 static void ps_tq_int( void *data )
-
-{       void (*con)(void);
+{
+	void (*con)(void);
 	unsigned long flags;
 
 	spin_lock_irqsave(&ps_spinlock,flags);
 
-        con = ps_continuation;
-
-#ifdef HAVE_DISABLE_HLT
-        enable_hlt();
-#endif
-
-        ps_tq_active = 0;
+	con = ps_continuation;
+	ps_tq_active = 0;
 
-        if (!con) {
+	if (!con) {
 		spin_unlock_irqrestore(&ps_spinlock,flags);
 		return;
 	}
-        if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
-                ps_continuation = NULL;
-        	spin_unlock_irqrestore(&ps_spinlock,flags);
-                con();
-                return;
-                }
-
-#ifdef HAVE_DISABLE_HLT
-        disable_hlt();
-#endif
-
-        ps_tq_active = 1;
-	schedule_work(&ps_tq);
-        spin_unlock_irqrestore(&ps_spinlock,flags);
-}
-
-static void ps_timer_int( unsigned long data)
-
-{       void (*con)(void);
-	unsigned long	flags;
-
-	spin_lock_irqsave(&ps_spinlock,flags);
-
-	con = ps_continuation;
-	ps_timer_active = 0;
-	if (!con) {
-	        spin_unlock_irqrestore(&ps_spinlock,flags);
+	if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
+		ps_continuation = NULL;
+		spin_unlock_irqrestore(&ps_spinlock,flags);
+		con();
 		return;
 	}
-        if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
-                ps_continuation = NULL;
-	        spin_unlock_irqrestore(&ps_spinlock,flags);
-                con();
-		return;
-		}
-	ps_timer_active = 1;
-        ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
-        add_timer(&ps_timer);
-        spin_unlock_irqrestore(&ps_spinlock,flags);
+	ps_tq_active = 1;
+	if (!ps_nice)
+		schedule_work(&ps_tq);
+	else
+		schedule_delayed_work(&ps_tq, ps_nice-1);
+	spin_unlock_irqrestore(&ps_spinlock,flags);
 }
 
 /* end of pseudo.h */
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/block/ps2esdi.c	Sun Nov 17 20:30:02 2002
@@ -37,14 +37,13 @@
 #define DEVICE_NR(device) (minor(device) >> 6)
 
 #include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/genhd.h>
 #include <linux/ps2esdi.h>
 #include <linux/blk.h>
-#include <linux/blkpg.h>
 #include <linux/mca.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -508,7 +507,7 @@
 	}
 
 	if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
-		printk("Grrr. error. ps2esdi_drives: %d, %lu %llu\n",
+		printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n",
 		    ps2esdi_drives, req->sector,
 		    (unsigned long long)get_capacity(req->rq_disk));
 		end_request(req, FAIL);
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/block/xd.c	Sun Nov 17 20:30:15 2002
@@ -35,7 +35,7 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -44,6 +44,7 @@
 #include <linux/hdreg.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/wait.h>
 #include <linux/devfs_fs_kernel.h>
 
 #include <asm/system.h>
diff -Nru a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
--- a/drivers/bluetooth/bluecard_cs.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/bluetooth/bluecard_cs.c	Sun Nov 17 20:30:14 2002
@@ -849,6 +849,7 @@
 	link = &info->link;
 	link->priv = info;
 
+	init_timer(&link->release);
 	link->release.function = &bluecard_release;
 	link->release.data = (u_long)link;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
--- a/drivers/bluetooth/bt3c_cs.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/bluetooth/bt3c_cs.c	Sun Nov 17 20:30:16 2002
@@ -643,6 +643,7 @@
 	link = &info->link;
 	link->priv = info;
 
+	init_timer(&link->release);
 	link->release.function = &bt3c_release;
 	link->release.data = (u_long)link;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
diff -Nru a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
--- a/drivers/bluetooth/dtl1_cs.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/bluetooth/dtl1_cs.c	Sun Nov 17 20:30:13 2002
@@ -582,6 +582,7 @@
 	link = &info->link;
 	link->priv = info;
 
+	init_timer(&link->release);
 	link->release.function = &dtl1_release;
 	link->release.data = (u_long)link;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/cdrom/aztcd.c	Sun Nov 17 20:30:15 2002
@@ -1934,7 +1934,7 @@
 err_out3:
 	put_disk(azt_disk);
 err_out2:
-	devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	devfs_remove("aztcd");
 err_out:
 	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
 		SWITCH_IDE_MASTER;
@@ -1947,7 +1947,7 @@
 
 static void __exit aztcd_exit(void)
 {
-	devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	devfs_remove("aztcd");
 	del_gendisk(azt_disk);
 	put_disk(azt_disk);
 	if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/cdrom/cm206.c	Sun Nov 17 20:30:15 2002
@@ -1514,6 +1514,7 @@
 	memset(cd, 0, sizeof(*cd));	/* give'm some reasonable value */
 	cd->sector_last = -1;	/* flag no data buffered */
 	cd->adapter_last = -1;
+	init_timer(&cd->timer);
 	cd->timer.function = cm206_timeout;
 	cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
 	printk(KERN_INFO "%d kB adapter memory available, "
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/cdrom/gscd.c	Sun Nov 17 20:30:02 2002
@@ -883,7 +883,7 @@
 {
 	CLEAR_TIMER;
 
-	devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	devfs_remove("gscd");
 	del_gendisk(gscd_disk);
 	put_disk(gscd_disk);
 	if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/cdrom/mcd.c	Sun Nov 17 20:30:14 2002
@@ -82,8 +82,8 @@
 #include <linux/module.h>
 
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
@@ -99,6 +99,7 @@
 /* #define REALLY_SLOW_IO  */
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/current.h>
 #include <asm/uaccess.h>
 #include <linux/blk.h>
 
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/cdrom/mcdx.c	Sun Nov 17 20:30:14 2002
@@ -60,7 +60,7 @@
 #include <linux/module.h>
 
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/cdrom.h>
@@ -69,6 +69,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <asm/io.h>
+#include <asm/current.h>
 #include <asm/uaccess.h>
 
 #include <linux/major.h>
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/cdrom/optcd.c	Sun Nov 17 20:30:12 2002
@@ -2067,7 +2067,7 @@
 
 static void __exit optcd_exit(void)
 {
-	devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	devfs_remove("optcd");
 	del_gendisk(optcd_disk);
 	put_disk(optcd_disk);
 	if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/cdrom/sbpcd.c	Sun Nov 17 20:30:04 2002
@@ -5871,8 +5871,8 @@
 		disk->fops = &sbpcd_bdops;
 		strcpy(disk->disk_name, sbpcd_infop->name);
 		disk->flags = GENHD_FL_CD;
-		sprintf(nbuff, "c0t%d", p->drv_id);
-		disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL);
+		sprintf(nbuff, "sbp/c0t%d", p->drv_id);
+		disk->de = devfs_mk_dir(NULL, nbuff, NULL);
 		p->disk = disk;
 		if (register_cdrom(sbpcd_infop))
 		{
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/cdrom/sjcd.c	Sun Nov 17 20:30:14 2002
@@ -1801,7 +1801,7 @@
 
 static void __exit sjcd_exit(void)
 {
-	devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	devfs_remove("sjcd");
 	del_gendisk(sjcd_disk);
 	put_disk(sjcd_disk);
 	release_region(sjcd_base, 4);
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/cdrom/sonycd535.c	Sun Nov 17 20:30:12 2002
@@ -1671,8 +1671,7 @@
 	kfree(sony_buffer);
 	kfree(last_sony_subcode);
 	kfree(sony_toc);
-	devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0,
-				  DEVFS_SPECIAL_BLK, 0);
+	devfs_remove(CDU535_HANDLE);
 	del_gendisk(cdu_disk);
 	put_disk(cdu_disk);
 	blk_cleanup_queue(&sonycd535_queue);
diff -Nru a/drivers/char/agp/agp.c b/drivers/char/agp/agp.c
--- a/drivers/char/agp/agp.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/agp/agp.c	Sun Nov 17 20:30:15 2002
@@ -47,7 +47,7 @@
 EXPORT_SYMBOL(agp_backend_acquire);
 EXPORT_SYMBOL(agp_backend_release);
 
-struct agp_bridge_data agp_bridge = { type: NOT_SUPPORTED };
+struct agp_bridge_data agp_bridge = { .type = NOT_SUPPORTED };
 static int agp_try_unsupported __initdata = 0;
 
 int agp_memory_reserved;
diff -Nru a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
--- a/drivers/char/agp/ali-agp.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/agp/ali-agp.c	Sun Nov 17 20:30:14 2002
@@ -216,7 +216,7 @@
 /* Setup function */
 static struct gatt_mask ali_generic_masks[] =
 {
-	{mask: 0x00000000, type: 0}
+	{.mask = 0x00000000, .type = 0}
 };
 
 static struct aper_size_info_32 ali_generic_sizes[7] =
diff -Nru a/drivers/char/agp/amd-agp.c b/drivers/char/agp/amd-agp.c
--- a/drivers/char/agp/amd-agp.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/char/agp/amd-agp.c	Sun Nov 17 20:30:16 2002
@@ -370,7 +370,7 @@
 
 static struct gatt_mask amd_irongate_masks[] =
 {
-	{mask: 0x00000001, type: 0}
+	{.mask = 0x00000001, .type = 0}
 };
 
 int __init amd_irongate_setup (struct pci_dev *pdev)
diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
--- a/drivers/char/agp/hp-agp.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/agp/hp-agp.c	Sun Nov 17 20:30:15 2002
@@ -53,7 +53,7 @@
 
 static struct gatt_mask hp_zx1_masks[] =
 {
-	{mask: HP_ZX1_PDIR_VALID_BIT, type: 0}
+	{.mask = HP_ZX1_PDIR_VALID_BIT, .type = 0}
 };
 
 static struct _hp_private {
diff -Nru a/drivers/char/agp/i810-agp.c b/drivers/char/agp/i810-agp.c
--- a/drivers/char/agp/i810-agp.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/agp/i810-agp.c	Sun Nov 17 20:30:14 2002
@@ -44,9 +44,9 @@
 
 static struct gatt_mask intel_i810_masks[] =
 {
-	{mask: I810_PTE_VALID, type: 0},
-	{mask: (I810_PTE_VALID | I810_PTE_LOCAL), type: AGP_DCACHE_MEMORY},
-	{mask: I810_PTE_VALID, type: 0}
+	{.mask = I810_PTE_VALID, .type = 0},
+	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
+	{.mask = I810_PTE_VALID, .type = 0}
 };
 
 static struct _intel_i810_private {
diff -Nru a/drivers/char/agp/i8x0-agp.c b/drivers/char/agp/i8x0-agp.c
--- a/drivers/char/agp/i8x0-agp.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/agp/i8x0-agp.c	Sun Nov 17 20:30:14 2002
@@ -427,7 +427,7 @@
 /* Setup function */
 static struct gatt_mask intel_generic_masks[] =
 {
-	{mask: 0x00000017, type: 0}
+	{.mask = 0x00000017, .type = 0}
 };
 
 static struct aper_size_info_8 intel_815_sizes[2] =
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/char/agp/sis-agp.c	Sun Nov 17 20:30:02 2002
@@ -106,7 +106,7 @@
 
 static struct gatt_mask sis_generic_masks[] =
 {
-	{mask: 0x00000000, type: 0}
+	{.mask = 0x00000000, .type = 0}
 };
 
 int __init sis_generic_setup (struct pci_dev *pdev)
diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
--- a/drivers/char/agp/sworks-agp.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/agp/sworks-agp.c	Sun Nov 17 20:30:12 2002
@@ -438,7 +438,7 @@
 
 static struct gatt_mask serverworks_masks[] =
 {
-	{mask: 0x00000001, type: 0}
+	{.mask = 0x00000001, .type = 0}
 };
 
 static struct aper_size_info_lvl2 serverworks_sizes[7] =
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/agp/via-agp.c	Sun Nov 17 20:30:15 2002
@@ -114,7 +114,7 @@
 
 static struct gatt_mask via_generic_masks[] =
 {
-	{mask: 0x00000000, type: 0}
+	{.mask = 0x00000000, .type = 0}
 };
 
 int __init via_generic_setup (struct pci_dev *pdev)
diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c
--- a/drivers/char/applicom.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/applicom.c	Sun Nov 17 20:30:15 2002
@@ -22,15 +22,17 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/wait.h>
 #include <linux/init.h>
 #include <linux/compatmac.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
 
 #include "applicom.h"
 
diff -Nru a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
--- a/drivers/char/drm/Makefile	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/Makefile	Sun Nov 17 20:30:15 2002
@@ -4,8 +4,8 @@
 
 gamma-objs  := gamma_drv.o gamma_dma.o
 tdfx-objs   := tdfx_drv.o
-r128-objs   := r128_drv.o r128_cce.o r128_state.o
-mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o
+r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
+mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
 i830-objs   := i830_drv.o i830_dma.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
diff -Nru a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/drm/drm_sarea.h	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,57 @@
+/* sarea.h -- SAREA definitions -*- linux-c -*-
+ *
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Michel Dänzer <michel@daenzer.net>
+ */
+
+#ifndef _DRM_SAREA_H_
+#define _DRM_SAREA_H_
+
+#define SAREA_MAX_DRAWABLES 		256
+
+typedef struct _drm_sarea_drawable_t {
+    unsigned int	stamp;
+    unsigned int	flags;
+} drm_sarea_drawable_t;
+
+typedef struct _dri_sarea_frame_t {
+    unsigned int        x;
+    unsigned int        y;
+    unsigned int        width;
+    unsigned int        height;
+    unsigned int        fullscreen;
+} drm_sarea_frame_t;
+
+typedef struct _drm_sarea_t {
+    /* first thing is always the drm locking structure */
+    drm_hw_lock_t		lock;
+		/* NOT_DONE: Use readers/writer lock for drawable_lock */
+    drm_hw_lock_t		drawable_lock;
+    drm_sarea_drawable_t	drawableTable[SAREA_MAX_DRAWABLES];
+    drm_sarea_frame_t		frame;
+    drm_context_t		dummy_context;
+} drm_sarea_t;
+
+#endif	/* _DRM_SAREA_H_ */
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/char/drm/drm_vm.h	Sun Nov 17 20:30:16 2002
@@ -71,7 +71,7 @@
          * Find the right map
          */
 
-	if(!dev->agp->cant_use_aperture) goto vm_nopage_error;
+	if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
 
 	list_for_each(list, &dev->maplist->head) {
 		r_list = (drm_map_list_t *)list;
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/drm/i810_dma.c	Sun Nov 17 20:30:12 2002
@@ -26,7 +26,7 @@
  *
  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  *	    Jeff Hartmann <jhartmann@valinux.com>
- *          Keith Whitwell <keith_whitwell@yahoo.com>
+ *          Keith Whitwell <keith@tungstengraphics.com>
  *
  */
 
@@ -264,44 +264,6 @@
 	return retcode;
 }
 
-static unsigned long i810_alloc_page(drm_device_t *dev)
-{
-	unsigned long address;
-
-	address = __get_free_page(GFP_KERNEL);
-	if(address == 0UL)
-		return 0;
-
-#if LINUX_VERSION_CODE < 0x020409
-	atomic_inc(&virt_to_page(address)->count);
-	set_bit(PG_locked, &virt_to_page(address)->flags);
-#else
-	get_page(virt_to_page(address));
-#if LINUX_VERSION_CODE < 0x020500
-	LockPage(virt_to_page(address));
-#else
-	SetPageLocked(virt_to_page(address));
-#endif
-#endif
-	return address;
-}
-
-static void i810_free_page(drm_device_t *dev, unsigned long page)
-{
-	if (page) {
-#if LINUX_VERSION_CODE < 0x020409
-		atomic_dec(&virt_to_page(page)->count);
-		clear_bit(PG_locked, &virt_to_page(page)->flags);
-		wake_up(&virt_to_page(page)->wait);
-#else
-		struct page *p = virt_to_page(page);
-		put_page(p);
-		unlock_page(p);
-#endif
-		free_page(page);
-	}
-}
-
 static int i810_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
@@ -316,7 +278,9 @@
 					 dev_priv->ring.Size);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
-		   	i810_free_page(dev, dev_priv->hw_status_page);
+		   	pci_free_consistent(dev->pdev, PAGE_SIZE,
+					    (void *)dev_priv->hw_status_page,
+					    dev_priv->dma_status_page);
 		   	/* Need to rewrite hardware status page */
 		   	I810_WRITE(0x02080, 0x1ffff000);
 		}
@@ -476,7 +440,9 @@
 	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 
    	/* Program Hardware Status Page */
-   	dev_priv->hw_status_page = i810_alloc_page(dev);
+   	dev_priv->hw_status_page =
+		(unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+						&dev_priv->dma_status_page);
    	if(dev_priv->hw_status_page == 0UL) {
 		dev->dev_private = (void *)dev_priv;
 		i810_dma_cleanup(dev);
@@ -486,7 +452,7 @@
    	memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
    	DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
 
-   	I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
+	I810_WRITE(0x02080, dev_priv->dma_status_page);
    	DRM_DEBUG("Enabled hardware status page\n");
 
    	/* Now we need to init our freelist */
diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
--- a/drivers/char/drm/i810_drv.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/i810_drv.h	Sun Nov 17 20:30:15 2002
@@ -64,6 +64,8 @@
       	unsigned long hw_status_page;
    	unsigned long counter;
 
+	dma_addr_t dma_status_page;
+
 	drm_buf_t *mmap_buffer;
 
 
diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
--- a/drivers/char/drm/i830_dma.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/char/drm/i830_dma.c	Sun Nov 17 20:30:03 2002
@@ -272,29 +272,6 @@
 	return retcode;
 }
 
-static unsigned long i830_alloc_page(drm_device_t *dev)
-{
-	unsigned long address;
-   
-	address = __get_free_page(GFP_KERNEL);
-	if(address == 0UL) 
-		return 0;
-	
-	get_page(virt_to_page(address));
-	LockPage(virt_to_page(address));
-	return address;
-}
-
-static void i830_free_page(drm_device_t *dev, unsigned long page)
-{
-	if (page) {
-		struct page *p = virt_to_page(page);
-		put_page(p);
-		UnlockPage(p);
-		free_page(page);
-	}
-}
-
 static int i830_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
@@ -309,7 +286,9 @@
 					 dev_priv->ring.Size);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
-		   	i830_free_page(dev, dev_priv->hw_status_page);
+		   	pci_free_consistent(dev->pdev, PAGE_SIZE,
+					    (void *)dev_priv->hw_status_page,
+					    dev_priv->dma_status_page);
 		   	/* Need to rewrite hardware status page */
 		   	I830_WRITE(0x02080, 0x1ffff000);
 		}
@@ -483,7 +462,9 @@
 	dev_priv->depth_pitch = init->depth_pitch;
 
    	/* Program Hardware Status Page */
-   	dev_priv->hw_status_page = i830_alloc_page(dev);
+   	dev_priv->hw_status_page =
+		(unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+						&dev_priv->dma_status_page);
    	if(dev_priv->hw_status_page == 0UL) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
@@ -493,7 +474,7 @@
    	memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
 	DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
    
-   	I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
+	I830_WRITE(0x02080, dev_priv->dma_status_page);
 	DRM_DEBUG("Enabled hardware status page\n");
    
    	/* Now we need to init our freelist */
diff -Nru a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
--- a/drivers/char/drm/i830_drv.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/drm/i830_drv.h	Sun Nov 17 20:30:14 2002
@@ -64,6 +64,8 @@
       	unsigned long hw_status_page;
    	unsigned long counter;
 
+	dma_addr_t dma_status_page;
+
 	drm_buf_t *mmap_buffer;
 	
 	u32 front_di1, back_di1, zi1;
diff -Nru a/drivers/char/drm/mga.h b/drivers/char/drm/mga.h
--- a/drivers/char/drm/mga.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/char/drm/mga.h	Sun Nov 17 20:30:02 2002
@@ -45,11 +45,11 @@
 
 #define DRIVER_NAME		"mga"
 #define DRIVER_DESC		"Matrox G200/G400"
-#define DRIVER_DATE		"20010321"
+#define DRIVER_DATE		"20021029"
 
 #define DRIVER_MAJOR		3
-#define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	2
+#define DRIVER_MINOR		1
+#define DRIVER_PATCHLEVEL	0
 
 #define DRIVER_IOCTLS							   \
 	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	      = { mga_dma_buffers, 1, 0 }, \
@@ -61,7 +61,8 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
 
 #define __HAVE_COUNTERS         3
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
@@ -77,6 +78,9 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
+#define __HAVE_DMA_IRQ		1
+#define __HAVE_VBL_IRQ		1
+#define __HAVE_SHARED_IRQ       1
 
 #define __HAVE_DMA_QUIESCENT	1
 #define DRIVER_DMA_QUIESCENT() do {					\
diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
--- a/drivers/char/drm/mga_dma.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/mga_dma.c	Sun Nov 17 20:30:15 2002
@@ -27,7 +27,7 @@
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keithw@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  *
  * Rewritten by:
  *    Gareth Hughes <gareth@valinux.com>
@@ -166,7 +166,7 @@
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
 		if ( status == MGA_ENDPRDMASTS ) break;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 	if ( primary->tail == primary->last_flush ) {
diff -Nru a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
--- a/drivers/char/drm/mga_drm.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/mga_drm.h	Sun Nov 17 20:30:15 2002
@@ -26,7 +26,7 @@
  *
  * Authors:
  *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keithw@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  *
  * Rewritten by:
  *    Gareth Hughes <gareth@valinux.com>
@@ -239,6 +239,7 @@
 #define DRM_IOCTL_MGA_INDICES		DRM_IOW( 0x46, drm_mga_indices_t)
 #define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x47, drm_mga_iload_t)
 #define DRM_IOCTL_MGA_BLIT		DRM_IOW( 0x48, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_GETPARAM		DRM_IOWR(0x49, drm_mga_getparam_t)
 
 typedef struct _drm_mga_warp_index {
    	int installed;
@@ -321,5 +322,15 @@
 	int height, ydir;		/* flip image vertically */
 	int source_pitch, dest_pitch;
 } drm_mga_blit_t;
+
+/* 3.1: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define MGA_PARAM_IRQ_NR            1
+
+typedef struct drm_mga_getparam {
+	int param;
+	int *value;
+} drm_mga_getparam_t;
 
 #endif
diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
--- a/drivers/char/drm/mga_drv.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/mga_drv.h	Sun Nov 17 20:30:15 2002
@@ -125,6 +125,7 @@
 extern int  mga_dma_indices( DRM_IOCTL_ARGS );
 extern int  mga_dma_iload( DRM_IOCTL_ARGS );
 extern int  mga_dma_blit( DRM_IOCTL_ARGS );
+extern int  mga_getparam( DRM_IOCTL_ARGS );
 
 				/* mga_warp.c */
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
@@ -141,6 +142,7 @@
 
 #ifdef __alpha__
 #define MGA_READ( reg )		(_MGA_READ((u32 *)MGA_ADDR(reg)))
+#define MGA_READ8( reg )	(_MGA_READ((u8 *)MGA_ADDR(reg)))
 #define MGA_WRITE( reg, val )	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
 #define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
 
@@ -152,6 +154,7 @@
 
 #else
 #define MGA_READ( reg )		MGA_DEREF( reg )
+#define MGA_READ8( reg )	MGA_DEREF8( reg )
 #define MGA_WRITE( reg, val )	do { MGA_DEREF( reg ) = val; } while (0)
 #define MGA_WRITE8( reg, val )  do { MGA_DEREF8( reg ) = val; } while (0)
 #endif
@@ -345,6 +348,11 @@
 /* A reduced set of the mga registers.
  */
 #define MGA_CRTC_INDEX			0x1fd4
+#define MGA_CRTC_DATA			0x1fd5
+
+/* CRTC11 */
+#define MGA_VINTCLR			(1 << 4)
+#define MGA_VINTEN			(1 << 5)
 
 #define MGA_ALPHACTRL 			0x2c7c
 #define MGA_AR0 			0x1c60
@@ -416,8 +424,10 @@
 
 #define MGA_ICLEAR 			0x1e18
 #	define MGA_SOFTRAPICLR			(1 << 0)
+#	define MGA_VLINEICLR			(1 << 5)
 #define MGA_IEN 			0x1e1c
 #	define MGA_SOFTRAPIEN			(1 << 0)
+#	define MGA_VLINEIEN			(1 << 5)
 
 #define MGA_LEN 			0x1c5c
 
@@ -456,6 +466,8 @@
 #	define MGA_SRCACC_AGP			(1 << 1)
 #define MGA_STATUS 			0x1e14
 #	define MGA_SOFTRAPEN			(1 << 0)
+#	define MGA_VSYNCPEN			(1 << 4)
+#	define MGA_VLINEPEN			(1 << 5)
 #	define MGA_DWGENGSTS			(1 << 16)
 #	define MGA_ENDPRDMASTS			(1 << 17)
 #define MGA_STENCIL			0x2cc8
diff -Nru a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/drm/mga_irq.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,99 @@
+/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "mga.h"
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+void mga_dma_service( DRM_IRQ_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+	int status;
+
+	status = MGA_READ( MGA_STATUS );
+	
+	/* VBLANK interrupt */
+	if ( status & MGA_VLINEPEN ) {
+		MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+	}
+}
+
+int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks... 
+	 */
+	DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 
+		     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+			 + ~*sequence + 1 ) <= (1<<23) ) );
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+void mga_driver_irq_preinstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+
+	/* Disable *all* interrupts */
+      	MGA_WRITE( MGA_IEN, 0 );
+	/* Clear bits if they're already high */
+   	MGA_WRITE( MGA_ICLEAR, ~0 );
+}
+
+void mga_driver_irq_postinstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+
+	/* Turn on VBL interrupt */
+   	MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+}
+
+void mga_driver_irq_uninstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+	if ( dev_priv ) {
+		/* Disable *all* interrupts */
+		MGA_WRITE( MGA_IEN, 0 );
+	}
+}
diff -Nru a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
--- a/drivers/char/drm/mga_state.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/char/drm/mga_state.c	Sun Nov 17 20:30:13 2002
@@ -26,7 +26,7 @@
  *
  * Authors:
  *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keithw@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  *
  * Rewritten by:
  *    Gareth Hughes <gareth@valinux.com>
@@ -1073,5 +1073,38 @@
 	 */
 	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 
+	return 0;
+}
+
+int mga_getparam( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_getparam_t param;
+	int value;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data,
+			     sizeof(param) );
+
+	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+
+	switch( param.param ) {
+	case MGA_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
 	return 0;
 }
diff -Nru a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
--- a/drivers/char/drm/r128.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/drm/r128.h	Sun Nov 17 20:30:12 2002
@@ -47,10 +47,10 @@
 
 #define DRIVER_NAME		"r128"
 #define DRIVER_DESC		"ATI Rage 128"
-#define DRIVER_DATE		"20010917"
+#define DRIVER_DATE		"20021029"
 
 #define DRIVER_MAJOR		2
-#define DRIVER_MINOR		2
+#define DRIVER_MINOR		3
 #define DRIVER_PATCHLEVEL	0
 
 
@@ -70,7 +70,8 @@
    [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)]       = { r128_cce_blit,     1, 0 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)]      = { r128_cce_depth,    1, 0 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 },
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 1 },
 
 /* Driver customization:
  */
@@ -90,6 +91,9 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
+#define __HAVE_DMA_IRQ		1
+#define __HAVE_VBL_IRQ		1
+#define __HAVE_SHARED_IRQ       1
 
 #if 0
 /* GH: Remove this for now... */
diff -Nru a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
--- a/drivers/char/drm/r128_drm.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/drm/r128_drm.h	Sun Nov 17 20:30:14 2002
@@ -190,6 +190,7 @@
 #define DRM_IOCTL_R128_INDIRECT		DRM_IOWR(0x4f, drm_r128_indirect_t)
 #define DRM_IOCTL_R128_FULLSCREEN	DRM_IOW( 0x50, drm_r128_fullscreen_t)
 #define DRM_IOCTL_R128_CLEAR2		DRM_IOW( 0x51, drm_r128_clear2_t)
+#define DRM_IOCTL_R128_GETPARAM		DRM_IOW( 0x52, drm_r128_getparam_t)
 
 typedef struct drm_r128_init {
 	enum {
@@ -304,5 +305,15 @@
 		R128_CLEANUP_FULLSCREEN = 0x02
 	} func;
 } drm_r128_fullscreen_t;
+
+/* 2.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define R128_PARAM_IRQ_NR            1
+
+typedef struct drm_r128_getparam {
+	int param;
+	int *value;
+} drm_r128_getparam_t;
 
 #endif
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/char/drm/r128_drv.h	Sun Nov 17 20:30:16 2002
@@ -124,6 +124,7 @@
 extern int r128_engine_reset( DRM_IOCTL_ARGS );
 extern int r128_fullscreen( DRM_IOCTL_ARGS );
 extern int r128_cce_buffers( DRM_IOCTL_ARGS );
+extern int r128_getparam( DRM_IOCTL_ARGS );
 
 extern void r128_freelist_reset( drm_device_t *dev );
 extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
@@ -213,6 +214,11 @@
 #define R128_DST_PITCH_OFFSET_C		0x1c80
 #	define R128_DST_TILE			(1 << 31)
 
+#define R128_GEN_INT_CNTL		0x0040
+#	define R128_CRTC_VBLANK_INT_EN		(1 <<  0)
+#define R128_GEN_INT_STATUS		0x0044
+#	define R128_CRTC_VBLANK_INT		(1 <<  0)
+#	define R128_CRTC_VBLANK_INT_AK		(1 <<  0)
 #define R128_GEN_RESET_CNTL		0x00f0
 #	define R128_SOFT_RESET_GUI		(1 <<  0)
 
diff -Nru a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/drm/r128_irq.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,99 @@
+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "r128.h"
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+void r128_dma_service( DRM_IRQ_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+	int status;
+
+	status = R128_READ( R128_GEN_INT_STATUS );
+	
+	/* VBLANK interrupt */
+	if ( status & R128_CRTC_VBLANK_INT ) {
+		R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+	}
+}
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks... 
+	 */
+	DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 
+		     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+			 + ~*sequence + 1 ) <= (1<<23) ) );
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+void r128_driver_irq_preinstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+
+	/* Disable *all* interrupts */
+      	R128_WRITE( R128_GEN_INT_CNTL, 0 );
+	/* Clear vblank bit if it's already high */
+   	R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+}
+
+void r128_driver_irq_postinstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+
+	/* Turn on VBL interrupt */
+   	R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN );
+}
+
+void r128_driver_irq_uninstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+	if ( dev_priv ) {
+		/* Disable *all* interrupts */
+		R128_WRITE( R128_GEN_INT_CNTL, 0 );
+	}
+}
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/char/drm/r128_state.c	Sun Nov 17 20:30:04 2002
@@ -1564,3 +1564,36 @@
 
 	return 0;
 }
+
+int r128_getparam( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_getparam_t param;
+	int value;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data,
+			     sizeof(param) );
+
+	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+
+	switch( param.param ) {
+	case R128_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
+	return 0;
+}
diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
--- a/drivers/char/drm/radeon.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/radeon.h	Sun Nov 17 20:30:15 2002
@@ -51,7 +51,7 @@
 #define DRIVER_DATE		"20020828"
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		6
+#define DRIVER_MINOR		7
 #define DRIVER_PATCHLEVEL	0
 
 /* Interface history:
@@ -73,6 +73,10 @@
  *       Add irq ioctls and irq_active getparam.
  *       Add wait command for cmdbuf ioctl
  *       Add agp offset query for getparam
+ * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
+ *       and R200_PP_CUBIC_OFFSET_F1_[0..5].
+ *       Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
+ *       R200_EMIT_PP_CUBIC_OFFSETS_[0..5].  (brian)
  */
 #define DRIVER_IOCTLS							     \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
--- a/drivers/char/drm/radeon_drm.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/drm/radeon_drm.h	Sun Nov 17 20:30:14 2002
@@ -27,7 +27,7 @@
  * Authors:
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *    Keith Whitwell <keith_whitwell@yahoo.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
 #ifndef __RADEON_DRM_H__
@@ -129,7 +129,19 @@
 #define R200_EMIT_SE_VTX_STATE_CNTL                 58 /* cst/1 */
 #define R200_EMIT_RE_POINTSIZE                      59 /* cst/1 */
 #define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0       60 /* cst/4 */
-#define RADEON_MAX_STATE_PACKETS                    61
+#define R200_EMIT_PP_CUBIC_FACES_0                  61
+#define R200_EMIT_PP_CUBIC_OFFSETS_0                62
+#define R200_EMIT_PP_CUBIC_FACES_1                  63
+#define R200_EMIT_PP_CUBIC_OFFSETS_1                64
+#define R200_EMIT_PP_CUBIC_FACES_2                  65
+#define R200_EMIT_PP_CUBIC_OFFSETS_2                66
+#define R200_EMIT_PP_CUBIC_FACES_3                  67
+#define R200_EMIT_PP_CUBIC_OFFSETS_3                68
+#define R200_EMIT_PP_CUBIC_FACES_4                  69
+#define R200_EMIT_PP_CUBIC_OFFSETS_4                70
+#define R200_EMIT_PP_CUBIC_FACES_5                  71
+#define R200_EMIT_PP_CUBIC_OFFSETS_5                72
+#define RADEON_MAX_STATE_PACKETS                    73
 
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but
@@ -343,6 +355,7 @@
 	int ctx_owner;
         int pfState;                /* number of 3d windows (0,1,2ormore) */
         int pfCurrentPage;	    /* which buffer is being displayed? */
+	int crtc2_base;		    /* CRTC2 frame offset */
 } drm_radeon_sarea_t;
 
 
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/drm/radeon_drv.h	Sun Nov 17 20:30:14 2002
@@ -109,8 +109,6 @@
 	int do_boxes;
 	int page_flipping;
 	int current_page;
-	u32 crtc_offset;
-	u32 crtc_offset_cntl;
 
 	u32 color_fmt;
 	unsigned int front_offset;
@@ -230,6 +228,8 @@
 #define RADEON_CRTC_OFFSET_CNTL		0x0228
 #	define RADEON_CRTC_TILE_EN		(1 << 15)
 #	define RADEON_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
+#define RADEON_CRTC2_OFFSET		0x0324
+#define RADEON_CRTC2_OFFSET_CNTL	0x0328
 
 #define RADEON_RB3D_COLORPITCH		0x1c48
 
@@ -574,6 +574,9 @@
 #define RADEON_TXFORMAT_RGBA8888	7
 #define RADEON_TXFORMAT_VYUY422         10
 #define RADEON_TXFORMAT_YVYU422         11
+#define RADEON_TXFORMAT_DXT1            12
+#define RADEON_TXFORMAT_DXT23           14
+#define RADEON_TXFORMAT_DXT45           15
 
 #define R200_PP_TXCBLEND_0                0x2f00
 #define R200_PP_TXCBLEND_1                0x2f10
@@ -602,6 +605,44 @@
 #define R200_PP_TXOFFSET_2                0x2d30
 #define R200_PP_TXOFFSET_1                0x2d18
 #define R200_PP_TXOFFSET_0                0x2d00
+
+#define R200_PP_CUBIC_FACES_0             0x2c18
+#define R200_PP_CUBIC_FACES_1             0x2c38
+#define R200_PP_CUBIC_FACES_2             0x2c58
+#define R200_PP_CUBIC_FACES_3             0x2c78
+#define R200_PP_CUBIC_FACES_4             0x2c98
+#define R200_PP_CUBIC_FACES_5             0x2cb8
+#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
+#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
+#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
+#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
+#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
+#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
+#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
+#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
+#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
+#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
+#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
+#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
+#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
+#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
+#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
+#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
+#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
+#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
+#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
+#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
+#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
+#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
+#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
+#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
+#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
+#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
+#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
+#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
+#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
+#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
+
 #define R200_RE_AUX_SCISSOR_CNTL          0x26f0
 #define R200_SE_VTE_CNTL                  0x20b0
 #define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/drm/radeon_state.c	Sun Nov 17 20:30:15 2002
@@ -30,6 +30,7 @@
 #include "radeon.h"
 #include "drmP.h"
 #include "drm.h"
+#include "drm_sarea.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
@@ -279,6 +280,18 @@
 	{ R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, 
 	{ R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, 
 	{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
+	{ R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
+	{ R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
+	{ R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
+	{ R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
+	{ R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
+	{ R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
+	{ R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
+	{ R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
+	{ R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
+	{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
+	{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
+	{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
 };
 
 
@@ -791,6 +804,9 @@
 static void radeon_cp_dispatch_flip( drm_device_t *dev )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
+	int offset = (dev_priv->current_page == 1)
+		   ? dev_priv->front_offset : dev_priv->back_offset;
 	RING_LOCALS;
 	DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
 		__FUNCTION__, 
@@ -804,18 +820,17 @@
 		radeon_cp_performance_boxes( dev_priv );
 	}
 
-	BEGIN_RING( 4 );
+	/* Update the frame offsets for both CRTCs
+	 */
+	BEGIN_RING( 6 );
 
 	RADEON_WAIT_UNTIL_3D_IDLE();
-	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
-
-	if ( dev_priv->current_page == 0 ) {
-		OUT_RING( dev_priv->back_offset );
-		dev_priv->current_page = 1;
-	} else {
-		OUT_RING( dev_priv->front_offset );
-		dev_priv->current_page = 0;
-	}
+	OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
+					      + sarea->frame.x 
+					      * ( dev_priv->color_fmt - 2 ) ) & ~7 )
+					  + offset );
+	OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+					   + offset );
 
 	ADVANCE_RING();
 
@@ -824,7 +839,8 @@
 	 * performing the swapbuffer ioctl.
 	 */
 	dev_priv->sarea_priv->last_frame++;
-	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+					      1 - dev_priv->current_page;
 
 	BEGIN_RING( 2 );
 
@@ -1292,12 +1308,12 @@
 
 	DRM_DEBUG( "\n" );
 
-	dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
-
-	BEGIN_RING( 4 );
+	BEGIN_RING( 6 );
 	RADEON_WAIT_UNTIL_3D_IDLE();
 	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
-	OUT_RING( dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL );
+	OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
+	OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
+	OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
 	ADVANCE_RING();
 
 	dev_priv->page_flipping = 1;
@@ -1318,10 +1334,6 @@
 	if (dev_priv->current_page != 0)
 		radeon_cp_dispatch_flip( dev );
 
-	/* FIXME: If the X server changes screen resolution, it
-	 * clobbers the value of RADEON_CRTC_OFFSET_CNTL, above,
-	 * leading to a flashing efect.
-	 */
 	dev_priv->page_flipping = 0;
 	return 0;
 }
@@ -1792,11 +1804,16 @@
 	drm_radeon_cmd_buffer_t *cmdbuf )
 {
 	int id = (int)header.packet.packet_id;
-	int sz = packet[id].len;
-	int reg = packet[id].start;
+	int sz, reg;
 	int *data = (int *)cmdbuf->buf;
 	RING_LOCALS;
    
+	if (id >= RADEON_MAX_STATE_PACKETS)
+		return DRM_ERR(EINVAL);
+
+	sz = packet[id].len;
+	reg = packet[id].start;
+
 	if (sz * sizeof(int) > cmdbuf->bufsz) 
 		return DRM_ERR(EINVAL);
 
diff -Nru a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
--- a/drivers/char/ftape/compressor/zftape-compress.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/ftape/compressor/zftape-compress.c	Sun Nov 17 20:30:15 2002
@@ -1266,13 +1266,6 @@
 "Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");
 MODULE_LICENSE("GPL");
 
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
-static int can_unload(void)
-{
-	return keep_module_locked ? -EBUSY : 0;
-}
-#endif
-
 /* Called by modules package when installing the driver
  */
 int init_module(void)
@@ -1282,9 +1275,11 @@
 #if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
 	register_symtab(0); /* remove global ftape symbols */
 #else
+#if 0 /* FIXME --RR */
 	if (!mod_member_present(&__this_module, can_unload))
 		return -EBUSY;
 	__this_module.can_unload = can_unload;
+#endif
 #endif
 	result = zft_compressor_init();
 	keep_module_locked = 0;
diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
--- a/drivers/char/ftape/zftape/zftape-init.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/char/ftape/zftape/zftape-init.c	Sun Nov 17 20:30:13 2002
@@ -415,8 +415,6 @@
 void cleanup_module(void)
 {
 	int i;
-	char devname[9];
-
 	TRACE_FUN(ft_t_flow);
 
 	if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
@@ -425,18 +423,12 @@
 		TRACE(ft_t_info, "successful");
 	}
         for (i = 0; i < 4; i++) {
-		sprintf(devname, "qft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0);
-		sprintf(devname, "nqft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0);
-		sprintf(devname, "zqft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0);
-		sprintf(devname, "nzqft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0);
-		sprintf(devname, "rawqft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0);
-		sprintf(devname, "nrawqft%i", i);
-		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0);
+		devfs_remove("qft%i", i);
+		devfs_remove("nqft%i", i);
+		devfs_remove("zqft%i", i);
+		devfs_remove("nzqft%i", i);
+		devfs_remove("rawqft%i", i);
+		devfs_remove("nrawqft%i", i);
 	}
 	zft_uninit_mem(); /* release remaining memory, if any */
         printk(KERN_INFO "zftape successfully unloaded.\n");
diff -Nru a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
--- a/drivers/char/mwave/mwavedd.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/mwave/mwavedd.c	Sun Nov 17 20:30:12 2002
@@ -126,7 +126,6 @@
 	PRINTK_2(TRACE_MWAVE,
 		"mwavedd::mwave_open, exit return retval %x\n", retval);
 
-	MOD_INC_USE_COUNT;
 	return retval;
 }
 
@@ -141,7 +140,6 @@
 	PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %x\n",
 		retval);
 
-	MOD_DEC_USE_COUNT;
 	return retval;
 }
 
diff -Nru a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
--- a/drivers/char/mwave/tp3780i.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/char/mwave/tp3780i.c	Sun Nov 17 20:30:03 2002
@@ -47,6 +47,7 @@
 */
 
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
--- a/drivers/char/pcmcia/synclink_cs.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/pcmcia/synclink_cs.c	Sun Nov 17 20:30:12 2002
@@ -582,6 +582,7 @@
     link->priv = info;
     
     /* Initialize the dev_link_t structure */
+    init_timer(&link->release);
     link->release.function = &mgslpc_release;
     link->release.data = (u_long)link;
 
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/char/random.c	Sun Nov 17 20:30:02 2002
@@ -2117,7 +2117,7 @@
 {
 	struct keydata *keyptr;
 
-	keyptr = check_and_rekey(CURRENT_TIME);
+	keyptr = check_and_rekey(get_seconds());
 
 	return halfMD4Transform(daddr, keyptr->secret);
 }
@@ -2177,7 +2177,7 @@
 	struct keydata *keyptr;
 	__u32 hash[4];
 
-	keyptr = check_and_rekey(CURRENT_TIME);
+	keyptr = check_and_rekey(get_seconds());
 
 	/*
 	 *  Pick a unique starting offset for each IP destination.
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/raw.c	Sun Nov 17 20:30:14 2002
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/raw.h>
 #include <linux/capability.h>
+#include <linux/uio.h>
 
 #include <asm/uaccess.h>
 
@@ -178,14 +179,12 @@
 			up(&raw_mutex);
 		} else {
 			struct block_device *bdev;
-			kdev_t dev;
 
 			down(&raw_mutex);
 			bdev = rawdev->binding;
 			if (bdev) {
-				dev = to_kdev_t(bdev->bd_dev);
-				rq.block_major = major(dev);
-				rq.block_minor = minor(dev);
+				rq.block_major = MAJOR(bdev->bd_dev);
+				rq.block_minor = MINOR(bdev->bd_dev);
 			} else {
 				rq.block_major = rq.block_minor = 0;
 			}
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/char/rtc.c	Sun Nov 17 20:30:13 2002
@@ -58,6 +58,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -70,8 +71,9 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/sysctl.h>
+#include <linux/wait.h>
 
-#include <asm/io.h>
+#include <asm/current.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/char/sonypi.c	Sun Nov 17 20:30:15 2002
@@ -34,9 +34,12 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/miscdevice.h>
 #include <linux/poll.h>
 #include <linux/delay.h>
+#include <linux/wait.h>
+
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c
--- a/drivers/char/sx.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/char/sx.c	Sun Nov 17 20:30:13 2002
@@ -225,6 +225,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
+#include <linux/bitops.h>
 
 /* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
 #define BYTE u8
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/tpqic02.c	Sun Nov 17 20:30:14 2002
@@ -77,6 +77,7 @@
 
 #include <linux/config.h>
 
+#include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
@@ -2766,22 +2767,14 @@
 	if (status_zombie == NO)
 		qic02_release_resources();
 		
-	devfs_find_and_unregister(NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "tpqic11", QIC02_TAPE_MAJOR, 3,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "tpqic24", QIC02_TAPE_MAJOR, 5,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "tpqic120", QIC02_TAPE_MAJOR, 7,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(NULL, "tpqic150", QIC02_TAPE_MAJOR, 9,
-				  DEVFS_SPECIAL_CHR, 0);
+	devfs_remove("ntpqic11");
+	devfs_remove("tpqic11");
+	devfs_remove("ntpqic24");
+	devfs_remove("tpqic24");
+	devfs_remove("ntpqic120");
+	devfs_remove("tpqic120");
+	devfs_remove("ntpqic150");
+	devfs_remove("tpqic150");
 }
 
 int init_module(void)
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/tty_io.c	Sun Nov 17 20:30:14 2002
@@ -2050,14 +2050,7 @@
 
 void tty_unregister_devfs (struct tty_driver *driver, unsigned minor)
 {
-#ifdef CONFIG_DEVFS_FS
-	int idx = minor - driver->minor_start;
-	char buf[32];
-
-	sprintf(buf, driver->name, idx + driver->name_base);
-	devfs_find_and_unregister(NULL, buf, driver->major, minor,
-				  DEVFS_SPECIAL_CHR, 0);
-#endif /* CONFIG_DEVFS_FS */
+	devfs_remove(driver->name, minor-driver->minor_start+driver->name_base);
 }
 
 EXPORT_SYMBOL(tty_register_devfs);
diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
--- a/drivers/char/vc_screen.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/char/vc_screen.c	Sun Nov 17 20:30:12 2002
@@ -470,30 +470,24 @@
 	.open		= vcs_open,
 };
 
-static devfs_handle_t devfs_handle;
-
 void vcs_make_devfs (unsigned int index, int unregister)
 {
 #ifdef CONFIG_DEVFS_FS
-    char name[8];
 
-    sprintf (name, "a%u", index + 1);
-    if (unregister)
-    {
-	devfs_find_and_unregister(devfs_handle, name + 1, 0, 0,
-				  DEVFS_SPECIAL_CHR, 0);
-	devfs_find_and_unregister(devfs_handle, name, 0, 0,
-				  DEVFS_SPECIAL_CHR, 0);
-    }
-    else
-    {
-	devfs_register (devfs_handle, name + 1, DEVFS_FL_DEFAULT,
-			VCS_MAJOR, index + 1,
-			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-	devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT,
-			VCS_MAJOR, index + 129,
-			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-    }
+	if (unregister) {
+		devfs_remove("vcc/%u", index + 1);
+		devfs_remove("vcc/a%u", index + 1);
+	} else {
+		char name[16];
+		sprintf(name, "vcc/%u", index + 1);
+		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
+				VCS_MAJOR, index + 1,
+				S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
+		sprintf(name, "vcc/a%u", index + 1);
+		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
+				VCS_MAJOR, index + 129,
+				S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
+	}
 #endif /* CONFIG_DEVFS_FS */
 }
 
@@ -506,12 +500,9 @@
 	if (error)
 		printk("unable to get major %d for vcs device", VCS_MAJOR);
 
-	devfs_handle = devfs_mk_dir (NULL, "vcc", NULL);
-	devfs_register (devfs_handle, "0", DEVFS_FL_DEFAULT,
-			VCS_MAJOR, 0,
+	devfs_register(NULL, "vcc/0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0,
 			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-	devfs_register (devfs_handle, "a", DEVFS_FL_DEFAULT,
-			VCS_MAJOR, 128,
+	devfs_register(NULL, "vcc/a", DEVFS_FL_DEFAULT, VCS_MAJOR, 128,
 			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
 
 	return error;
diff -Nru a/drivers/char/wdt.c b/drivers/char/wdt.c
--- a/drivers/char/wdt.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/char/wdt.c	Sun Nov 17 20:30:14 2002
@@ -31,25 +31,25 @@
  */
 
 #include <linux/config.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include "wd501p.h"
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
 
 static unsigned long wdt_is_open;
 
diff -Nru a/drivers/fc4/fc.c b/drivers/fc4/fc.c
--- a/drivers/fc4/fc.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/fc4/fc.c	Sun Nov 17 20:30:14 2002
@@ -676,6 +676,7 @@
 	l.magic = LSOMAGIC;
 	FCND(("FCP Force Offline for %d channels\n", count))
 	init_MUTEX_LOCKED(&l.sem);
+	init_timer(&l.timer);
 	l.timer.function = fcp_login_timeout;
 	l.timer.data = (unsigned long)&l;
 	atomic_set (&l.todo, count);
@@ -977,7 +978,7 @@
 
 
         fc->rst_pkt->eh_state = SCSI_STATE_QUEUED;
-
+	init_timer(&fc->rst_pkt->eh_timeout);
 	fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt;
 	fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT;
 	fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done;
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/hotplug/pci_hotplug_core.c	Sun Nov 17 20:30:15 2002
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/pci.h>
 #include <linux/dnotify.h>
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/ide-probe.c	Sun Nov 17 20:30:14 2002
@@ -1047,7 +1047,6 @@
 static void init_gendisk (ide_hwif_t *hwif)
 {
 	unsigned int unit;
-	extern devfs_handle_t ide_devfs_handle;
 
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t * drive = &hwif->drives[unit];
@@ -1059,13 +1058,13 @@
 			 "%s","IDE Drive");
 		drive->gendev.parent = &hwif->gendev;
 		drive->gendev.bus = &ide_bus_type;
-		sprintf (name, "host%d/bus%d/target%d/lun%d",
+		sprintf (name, "ide/host%d/bus%d/target%d/lun%d",
 			(hwif->channel && hwif->mate) ?
 			hwif->mate->index : hwif->index,
 			hwif->channel, unit, drive->lun);
 		if (drive->present) {
 			device_register(&drive->gendev);
-			drive->de = devfs_mk_dir(ide_devfs_handle, name, NULL);
+			drive->de = devfs_mk_dir(NULL, name, NULL);
 		}
 	}
 	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/ide/ide-tape.c	Sun Nov 17 20:30:12 2002
@@ -6122,6 +6122,7 @@
 	drive->driver_data = NULL;
 	devfs_unregister(tape->de_r);
 	devfs_unregister(tape->de_n);
+	devfs_unregister_tape(drive->disk->number);
 	kfree (tape);
 	drive->disk->fops = ide_fops;
 	return 0;
@@ -6269,7 +6270,7 @@
 			    HWIF(drive)->major, minor + 128,
 			    S_IFCHR | S_IRUGO | S_IWUGO,
 			    &idetape_fops, NULL);
-	devfs_register_tape(tape->de_r);
+	drive->disk->number = devfs_register_tape(drive->de);
 	drive->disk->fops = &idetape_block_ops;
 	return 0;
 failed:
diff -Nru a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
--- a/drivers/ide/legacy/ide-cs.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/legacy/ide-cs.c	Sun Nov 17 20:30:15 2002
@@ -134,6 +134,7 @@
     memset(info, 0, sizeof(*info));
     link = &info->link; link->priv = info;
 
+    init_timer(&link->release);
     link->release.function = &ide_release;
     link->release.data = (u_long)link;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
diff -Nru a/drivers/ide/pci/adma100.h b/drivers/ide/pci/adma100.h
--- a/drivers/ide/pci/adma100.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/adma100.h	Sun Nov 17 20:30:15 2002
@@ -12,24 +12,24 @@
 
 static ide_pci_device_t pdcadma_chipsets[] __devinitdata = {
 	{
-		vendor:	PCI_VENDOR_ID_PDC,
-		device:	PCI_DEVICE_ID_PDC_1841,
-		name:		"ADMA100",
-		init_setup:	init_setup_pdcadma,
-		init_chipset:	init_chipset_pdcadma,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdcadma,
-		init_dma:	init_dma_pdcadma,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_PDC,
+		.device		= PCI_DEVICE_ID_PDC_1841,
+		.name		= "ADMA100",
+		.init_setup	= init_setup_pdcadma,
+		.init_chipset	= init_chipset_pdcadma,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdcadma,
+		.init_dma	= init_dma_pdcadma,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 }
 
diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h
--- a/drivers/ide/pci/aec62xx.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/aec62xx.h	Sun Nov 17 20:30:14 2002
@@ -84,10 +84,10 @@
 
 static ide_pci_host_proc_t aec62xx_procs[] __initdata = {
 	{
-		name:		"aec62xx",
-		set:		1,
-		get_info:	aec62xx_get_info,
-		parent:		NULL,
+		.name		= "aec62xx",
+		.set		= 1,
+		.get_info	= aec62xx_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
@@ -100,75 +100,75 @@
 
 static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_ARTOP,
-		device:		PCI_DEVICE_ID_ARTOP_ATP850UF,
-		name:		"AEC6210",
-		init_setup:	init_setup_aec62xx,
-		init_chipset:	init_chipset_aec62xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_aec62xx,
-		init_dma:	init_dma_aec62xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ARTOP,
+		.device		= PCI_DEVICE_ID_ARTOP_ATP850UF,
+		.name		= "AEC6210",
+		.init_setup	= init_setup_aec62xx,
+		.init_chipset	= init_chipset_aec62xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_aec62xx,
+		.init_dma	= init_dma_aec62xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_ARTOP,
-		device:		PCI_DEVICE_ID_ARTOP_ATP860,
-		name:		"AEC6260",
-		init_setup:	init_setup_aec62xx,
-		init_chipset:	init_chipset_aec62xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_aec62xx,
-		init_dma:	init_dma_aec62xx,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ARTOP,
+		.device		= PCI_DEVICE_ID_ARTOP_ATP860,
+		.name		= "AEC6260",
+		.init_setup	= init_setup_aec62xx,
+		.init_chipset	= init_chipset_aec62xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_aec62xx,
+		.init_dma	= init_dma_aec62xx,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_ARTOP,
-		device:		PCI_DEVICE_ID_ARTOP_ATP860R,
-		name:		"AEC6260R",
-		init_setup:	init_setup_aec62xx,
-		init_chipset:	init_chipset_aec62xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_aec62xx,
-		init_dma:	init_dma_aec62xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-		bootable:	NEVER_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ARTOP,
+		.device		= PCI_DEVICE_ID_ARTOP_ATP860R,
+		.name		= "AEC6260R",
+		.init_setup	= init_setup_aec62xx,
+		.init_chipset	= init_chipset_aec62xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_aec62xx,
+		.init_dma	= init_dma_aec62xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+		.bootable	= NEVER_BOARD,
+		.extra		= 0,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_ARTOP,
-		device:		PCI_DEVICE_ID_ARTOP_ATP865,
-		name:		"AEC6X80",
-		init_setup:	init_setup_aec6x80,
-		init_chipset:	init_chipset_aec62xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_aec62xx,
-		init_dma:	init_dma_aec62xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ARTOP,
+		.device		= PCI_DEVICE_ID_ARTOP_ATP865,
+		.name		= "AEC6X80",
+		.init_setup	= init_setup_aec6x80,
+		.init_chipset	= init_chipset_aec62xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_aec62xx,
+		.init_dma	= init_dma_aec62xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_ARTOP,
-		device:		PCI_DEVICE_ID_ARTOP_ATP865R,
-		name:		"AEC6X80R",
-		init_setup:	init_setup_aec6x80,
-		init_chipset:	init_chipset_aec62xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_aec62xx,
-		init_dma:	init_dma_aec62xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ARTOP,
+		.device		= PCI_DEVICE_ID_ARTOP_ATP865R,
+		.name		= "AEC6X80R",
+		.init_setup	= init_setup_aec6x80,
+		.init_chipset	= init_chipset_aec62xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_aec62xx,
+		.init_dma	= init_dma_aec62xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	}
 };
 
diff -Nru a/drivers/ide/pci/alim15x3.h b/drivers/ide/pci/alim15x3.h
--- a/drivers/ide/pci/alim15x3.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/alim15x3.h	Sun Nov 17 20:30:02 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t ali_procs[] __initdata = {
 	{
-		name:		"ali",
-		set:		1,
-		get_info:	ali_get_info,
-		parent:		NULL,
+		.name		= "ali",
+		.set		= 1,
+		.get_info	= ali_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_ALI_TIMINGS && CONFIG_PROC_FS */
@@ -32,23 +32,23 @@
 
 static ide_pci_device_t ali15x3_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_AL,
-		device:		PCI_DEVICE_ID_AL_M5229,
-		name:		"ALI15X3",
-		init_chipset:	init_chipset_ali15x3,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_ali15x3,
-		init_dma:	init_dma_ali15x3,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AL,
+		.device		= PCI_DEVICE_ID_AL_M5229,
+		.name		= "ALI15X3",
+		.init_chipset	= init_chipset_ali15x3,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_ali15x3,
+		.init_dma	= init_dma_ali15x3,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/amd74xx.h b/drivers/ide/pci/amd74xx.h
--- a/drivers/ide/pci/amd74xx.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/amd74xx.h	Sun Nov 17 20:30:02 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t amd74xx_procs[] __initdata = {
 	{
-		name:		"amd74xx",
-		set:		1,
-		get_info:	amd74xx_get_info,
-		parent:		NULL,
+		.name		= "amd74xx",
+		.set		= 1,
+		.get_info	= amd74xx_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -31,75 +31,75 @@
 
 static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_AMD,
-		device:		PCI_DEVICE_ID_AMD_COBRA_7401,
-		name:		"AMD7401",
-		init_chipset:	init_chipset_amd74xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_amd74xx,
-		init_dma:	init_dma_amd74xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_COBRA_7401,
+		.name		= "AMD7401",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_AMD,
-		device:		PCI_DEVICE_ID_AMD_VIPER_7409,
-		name:		"AMD7409",
-		init_chipset:	init_chipset_amd74xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_amd74xx,
-		init_dma:	init_dma_amd74xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_VIPER_7409,
+		.name		= "AMD7409",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_AMD,
-		device:		PCI_DEVICE_ID_AMD_VIPER_7411,
-		name:		"AMD7411",
-		init_chipset:	init_chipset_amd74xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_amd74xx,
-		init_dma:	init_dma_amd74xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_VIPER_7411,
+		.name		= "AMD7411",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_AMD,
-		device:		PCI_DEVICE_ID_AMD_OPUS_7441,
-		name:		"AMD7441",
-		init_chipset:	init_chipset_amd74xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_amd74xx,
-		init_dma:	init_dma_amd74xx,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_OPUS_7441,
+		.name		= "AMD7441",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_AMD,
-		device:		PCI_DEVICE_ID_AMD_8111_IDE,
-		name:		"AMD8111",
-		init_chipset:	init_chipset_amd74xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_amd74xx,
-		init_dma:	init_dma_amd74xx,
-		autodma:	AUTODMA,
-		channels:	2,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_8111_IDE,
+		.name		= "AMD8111",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_amd74xx,
+		.init_dma	= init_dma_amd74xx,
+		.autodma	= AUTODMA,
+		.channels	= 2,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/cmd640.h b/drivers/ide/pci/cmd640.h
--- a/drivers/ide/pci/cmd640.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/cmd640.h	Sun Nov 17 20:30:15 2002
@@ -9,23 +9,23 @@
 
 static ide_pci_device_t cmd640_chipsets[] __initdata = {
 	{
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_CMD_640,
-		name:		"CMD640",
-		init_setup:	NULL,
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	IDE_IGNORE,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_CMD_640,
+		.name		= "CMD640",
+		.init_setup	= NULL,
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= IDE_IGNORE,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.bootable	= EOL,
 	}
 }
 
diff -Nru a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h
--- a/drivers/ide/pci/cmd64x.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/ide/pci/cmd64x.h	Sun Nov 17 20:30:13 2002
@@ -71,10 +71,10 @@
 
 static ide_pci_host_proc_t cmd64x_procs[] __initdata = {
 	{
-		name:		"cmd64x",
-		set:		1,
-		get_info:	cmd64x_get_info,
-		parent:		NULL,
+		.name		= "cmd64x",
+		.set		= 1,
+		.get_info	= cmd64x_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -85,62 +85,62 @@
 
 static ide_pci_device_t cmd64x_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_CMD_643,
-		name:		"CMD643",
-		init_chipset:	init_chipset_cmd64x,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_cmd64x,
-		init_dma:	init_dma_cmd64x,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_CMD_643,
+		.name		= "CMD643",
+		.init_chipset	= init_chipset_cmd64x,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_cmd64x,
+		.init_dma	= init_dma_cmd64x,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_CMD_646,
-		name:		"CMD646",
-		init_chipset:	init_chipset_cmd64x,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_cmd64x,
-		init_dma:	init_dma_cmd64x,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x51,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_CMD_646,
+		.name		= "CMD646",
+		.init_chipset	= init_chipset_cmd64x,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_cmd64x,
+		.init_dma	= init_dma_cmd64x,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:	PCI_DEVICE_ID_CMD_648,
-		name:		"CMD648",
-		init_chipset:	init_chipset_cmd64x,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_cmd64x,
-		init_dma:	init_dma_cmd64x,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device	= PCI_DEVICE_ID_CMD_648,
+		.name		= "CMD648",
+		.init_chipset	= init_chipset_cmd64x,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_cmd64x,
+		.init_dma	= init_dma_cmd64x,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_CMD_649,
-		name:		"CMD649",
-		init_chipset:	init_chipset_cmd64x,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_cmd64x,
-		init_dma:	init_dma_cmd64x,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_CMD_649,
+		.name		= "CMD649",
+		.init_chipset	= init_chipset_cmd64x,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_cmd64x,
+		.init_dma	= init_dma_cmd64x,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	2,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 2,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/cs5530.h b/drivers/ide/pci/cs5530.h
--- a/drivers/ide/pci/cs5530.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/cs5530.h	Sun Nov 17 20:30:02 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t cs5530_procs[] __initdata = {
 	{
-		name:		"cs5530",
-		set:		1,
-		get_info:	cs5530_get_info,
-		parent:		NULL,
+		.name		= "cs5530",
+		.set		= 1,
+		.get_info	= cs5530_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
@@ -31,23 +31,23 @@
 
 static ide_pci_device_t cs5530_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_CYRIX,
-		device:		PCI_DEVICE_ID_CYRIX_5530_IDE,
-		name:		"CS5530",
-		init_chipset:	init_chipset_cs5530,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_cs5530,
-		init_dma:	init_dma_cs5530,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CYRIX,
+		.device		= PCI_DEVICE_ID_CYRIX_5530_IDE,
+		.name		= "CS5530",
+		.init_chipset	= init_chipset_cs5530,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_cs5530,
+		.init_dma	= init_dma_cs5530,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/cy82c693.h b/drivers/ide/pci/cy82c693.h
--- a/drivers/ide/pci/cy82c693.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/ide/pci/cy82c693.h	Sun Nov 17 20:30:12 2002
@@ -70,23 +70,23 @@
 
 static ide_pci_device_t cy82c693_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_CONTAQ,
-		device:		PCI_DEVICE_ID_CONTAQ_82C693,
-		name:		"CY82C693",
-		init_chipset:	init_chipset_cy82c693,
-		init_iops:	init_iops_cy82c693,
-		init_hwif:	init_hwif_cy82c693,
-		init_dma:	NULL,
-		channels:	1,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CONTAQ,
+		.device		= PCI_DEVICE_ID_CONTAQ_82C693,
+		.name		= "CY82C693",
+		.init_chipset	= init_chipset_cy82c693,
+		.init_iops	= init_iops_cy82c693,
+		.init_hwif	= init_hwif_cy82c693,
+		.init_dma	= NULL,
+		.channels	= 1,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/generic.h b/drivers/ide/pci/generic.h
--- a/drivers/ide/pci/generic.h	Sun Nov 17 20:30:03 2002
+++ b/drivers/ide/pci/generic.h	Sun Nov 17 20:30:03 2002
@@ -11,149 +11,149 @@
 
 static ide_pci_device_t generic_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_NS,
-		device:		PCI_DEVICE_ID_NS_87410,
-		name:		"NS87410",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x43,0x08,0x08}, {0x47,0x08,0x08}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_NS,
+		.device		= PCI_DEVICE_ID_NS_87410,
+		.name		= "NS87410",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
         },{	/* 1 */
-		vendor:		PCI_VENDOR_ID_PCTECH,
-		device:		PCI_DEVICE_ID_PCTECH_SAMURAI_IDE,
-		name:		"SAMURAI",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PCTECH,
+		.device		= PCI_DEVICE_ID_PCTECH_SAMURAI_IDE,
+		.name		= "SAMURAI",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_HOLTEK,
-		device:		PCI_DEVICE_ID_HOLTEK_6565,
-		name:		"HT6565",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_HOLTEK,
+		.device		= PCI_DEVICE_ID_HOLTEK_6565,
+		.name		= "HT6565",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_UMC,
-		device:		PCI_DEVICE_ID_UMC_UM8673F,
-		name:		"UM8673F",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_UMC,
+		.device		= PCI_DEVICE_ID_UMC_UM8673F,
+		.name		= "UM8673F",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_UMC,
-		device:		PCI_DEVICE_ID_UMC_UM8886A,
-		name:		"UM8886A",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_UMC,
+		.device		= PCI_DEVICE_ID_UMC_UM8886A,
+		.name		= "UM8886A",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 5 */
-		vendor:		PCI_VENDOR_ID_UMC,
-		device:		PCI_DEVICE_ID_UMC_UM8886BF,
-		name:		"UM8886BF",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_UMC,
+		.device		= PCI_DEVICE_ID_UMC_UM8886BF,
+		.name		= "UM8886BF",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 6 */
-		vendor:		PCI_VENDOR_ID_HINT,
-		device:		PCI_DEVICE_ID_HINT_VXPROII_IDE,
-		name:		"HINT_IDE",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_HINT,
+		.device		= PCI_DEVICE_ID_HINT_VXPROII_IDE,
+		.name		= "HINT_IDE",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 7 */
-		vendor:		PCI_VENDOR_ID_VIA,
-		device:		PCI_DEVICE_ID_VIA_82C561,
-		name:		"VIA_IDE",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_82C561,
+		.name		= "VIA_IDE",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 8 */
-		vendor:		PCI_VENDOR_ID_OPTI,
-		device:		PCI_DEVICE_ID_OPTI_82C558,
-		name:		"OPTI621V",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_OPTI,
+		.device		= PCI_DEVICE_ID_OPTI_82C558,
+		.name		= "OPTI621V",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
 static ide_pci_device_t unknown_chipset[] __devinitdata = {
 	{	/* 0 */
-		vendor:		0,
-		device:		0,
-		name:		"PCI_IDE",
-		init_chipset:	init_chipset_generic,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_generic,
-		init_dma:	init_dma_generic,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= 0,
+		.device		= 0,
+		.name		= "PCI_IDE",
+		.init_chipset	= init_chipset_generic,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 
 };
diff -Nru a/drivers/ide/pci/hpt34x.h b/drivers/ide/pci/hpt34x.h
--- a/drivers/ide/pci/hpt34x.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/hpt34x.h	Sun Nov 17 20:30:02 2002
@@ -23,10 +23,10 @@
 
 static ide_pci_host_proc_t hpt34x_procs[] __initdata = {
 	{
-		name:		"hpt34x",
-		set:		1,
-		get_info:	hpt34x_get_info,
-		parent:		NULL,
+		.name		= "hpt34x",
+		.set		= 1,
+		.get_info	= hpt34x_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -37,23 +37,23 @@
 
 static ide_pci_device_t hpt34x_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT343,
-		name:		"HPT34X",
-		init_chipset:	init_chipset_hpt34x,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt34x,
-		init_dma:	init_dma_hpt34x,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	NEVER_BOARD,
-		extra:		16
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT343,
+		.name		= "HPT34X",
+		.init_chipset	= init_chipset_hpt34x,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt34x,
+		.init_dma	= init_dma_hpt34x,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= NEVER_BOARD,
+		.extra		= 16
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h
--- a/drivers/ide/pci/hpt366.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/hpt366.h	Sun Nov 17 20:30:15 2002
@@ -426,10 +426,10 @@
 
 static ide_pci_host_proc_t hpt366_procs[] __initdata = {
 	{
-		name:		"hpt366",
-		set:		1,
-		get_info:	hpt366_get_info,
-		parent:		NULL,
+		.name		= "hpt366",
+		.set		= 1,
+		.get_info	= hpt366_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -443,80 +443,80 @@
 
 static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT366,
-		name:		"HPT366",
-		init_setup:	init_setup_hpt366,
-		init_chipset:	init_chipset_hpt366,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt366,
-		init_dma:	init_dma_hpt366,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		240
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT366,
+		.name		= "HPT366",
+		.init_setup	= init_setup_hpt366,
+		.init_chipset	= init_chipset_hpt366,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt366,
+		.init_dma	= init_dma_hpt366,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 240
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT372,
-		name:		"HPT372A",
-		init_setup:	init_setup_hpt37x,
-		init_chipset:	init_chipset_hpt366,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt366,
-		init_dma:	init_dma_hpt366,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT372,
+		.name		= "HPT372A",
+		.init_setup	= init_setup_hpt37x,
+		.init_chipset	= init_chipset_hpt366,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt366,
+		.init_dma	= init_dma_hpt366,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT302,
-		name:		"HPT302",
-		init_setup:	init_setup_hpt37x,
-		init_chipset:	init_chipset_hpt366,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt366,
-		init_dma:	init_dma_hpt366,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT302,
+		.name		= "HPT302",
+		.init_setup	= init_setup_hpt37x,
+		.init_chipset	= init_chipset_hpt366,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt366,
+		.init_dma	= init_dma_hpt366,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT371,
-		name:		"HPT371",
-		init_setup:	init_setup_hpt37x,
-		init_chipset:	init_chipset_hpt366,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt366,
-		init_dma:	init_dma_hpt366,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT371,
+		.name		= "HPT371",
+		.init_setup	= init_setup_hpt37x,
+		.init_chipset	= init_chipset_hpt366,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt366,
+		.init_dma	= init_dma_hpt366,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_TTI,
-		device:		PCI_DEVICE_ID_TTI_HPT374,
-		name:		"HPT374",
-		init_setup:	init_setup_hpt374,
-		init_chipset:	init_chipset_hpt366,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_hpt366,
-		init_dma:	init_dma_hpt366,
-		channels:	2,	/* 4 */
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_TTI,
+		.device		= PCI_DEVICE_ID_TTI_HPT374,
+		.name		= "HPT374",
+		.init_setup	= init_setup_hpt374,
+		.init_chipset	= init_chipset_hpt366,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_hpt366,
+		.init_dma	= init_dma_hpt366,
+		.channels	= 2,	/* 4 */
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/it8172.h b/drivers/ide/pci/it8172.h
--- a/drivers/ide/pci/it8172.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/ide/pci/it8172.h	Sun Nov 17 20:30:13 2002
@@ -21,24 +21,24 @@
 
 static ide_pci_device_t it8172_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_ITE,
-		device:		PCI_DEVICE_ID_ITE_IT8172G,
-		name:		"IT8172G",
-		init_setup:	init_setup_it8172,
-		init_chipset:	init_chipset_it8172,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_it8172,
-                init_dma:	init_dma_it8172,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x40,0x00,0x01}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_ITE,
+		.device		= PCI_DEVICE_ID_ITE_IT8172G,
+		.name		= "IT8172G",
+		.init_setup	= init_setup_it8172,
+		.init_chipset	= init_chipset_it8172,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_it8172,
+                .init_dma	= init_dma_it8172,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x40,0x00,0x01}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/ns87415.h b/drivers/ide/pci/ns87415.h
--- a/drivers/ide/pci/ns87415.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/ns87415.h	Sun Nov 17 20:30:02 2002
@@ -10,23 +10,23 @@
 
 static ide_pci_device_t ns87415_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_NS,
-		device:		PCI_DEVICE_ID_NS_87415,
-		name:		"NS87415",
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_ns87415,
-                init_dma:	init_dma_ns87415,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_NS,
+		.device		= PCI_DEVICE_ID_NS_87415,
+		.name		= "NS87415",
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_ns87415,
+                .init_dma	= init_dma_ns87415,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/nvidia.h b/drivers/ide/pci/nvidia.h
--- a/drivers/ide/pci/nvidia.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/nvidia.h	Sun Nov 17 20:30:14 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t nforce_procs[] __initdata = {
 	{
-		name:		"nforce",
-		set:		1,
-		get_info:	nforce_get_info,
-		parent:		NULL,
+		.name		= "nforce",
+		.set		= 1,
+		.get_info	= nforce_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -31,18 +31,18 @@
 
 static ide_pci_device_t nvidia_chipsets[] __devinitdata = {
 	{
-		vendor:		PCI_VENDOR_ID_NVIDIA,
-		device:		PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
-		name:		"NFORCE",
-		init_chipset:	init_chipset_nforce,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_nforce,
-		init_dma:	init_dma_nforce,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x50,0x01,0x01}, {0x50,0x02,0x02}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
+		.name		= "NFORCE",
+		.init_chipset	= init_chipset_nforce,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_nforce,
+		.init_dma	= init_dma_nforce,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x01,0x01}, {0x50,0x02,0x02}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	}
 };
 
diff -Nru a/drivers/ide/pci/opti621.h b/drivers/ide/pci/opti621.h
--- a/drivers/ide/pci/opti621.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/opti621.h	Sun Nov 17 20:30:15 2002
@@ -11,38 +11,38 @@
 
 static ide_pci_device_t opti621_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_OPTI,
-		device:		PCI_DEVICE_ID_OPTI_82C621,
-		name:		"OPTI621",
-		init_setup:	init_setup_opti621,
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_opti621,
-		init_dma:	init_dma_opti621,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_OPTI,
+		.device		= PCI_DEVICE_ID_OPTI_82C621,
+		.name		= "OPTI621",
+		.init_setup	= init_setup_opti621,
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_opti621,
+		.init_dma	= init_dma_opti621,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_OPTI,
-		device:		PCI_DEVICE_ID_OPTI_82C825,
-		name:		"OPTI621X",
-		init_setup:	init_setup_opti621,
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_opti621,
-                init_dma:	init_dma_opti621,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_OPTI,
+		.device		= PCI_DEVICE_ID_OPTI_82C825,
+		.name		= "OPTI621X",
+		.init_setup	= init_setup_opti621,
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_opti621,
+                .init_dma	= init_dma_opti621,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h
--- a/drivers/ide/pci/pdc202xx_new.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/pdc202xx_new.h	Sun Nov 17 20:30:02 2002
@@ -209,10 +209,10 @@
 
 static ide_pci_host_proc_t pdcnew_procs[] __initdata = {
 	{
-		name:		"pdcnew",
-		set:		1,
-		get_info:	pdcnew_get_info,
-		parent:		NULL,
+		.name		= "pdcnew",
+		.set		= 1,
+		.get_info	= pdcnew_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
@@ -227,116 +227,116 @@
 
 static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20268,
-		name:		"PDC20268",
-		init_setup:	init_setup_pdcnew,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20268,
+		.name		= "PDC20268",
+		.init_setup	= init_setup_pdcnew,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20269,
-		name:		"PDC20269",
-		init_setup:	init_setup_pdcnew,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20269,
+		.name		= "PDC20269",
+		.init_setup	= init_setup_pdcnew,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20270,
-		name:		"PDC20270",
-		init_setup:	init_setup_pdc20270,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20270,
+		.name		= "PDC20270",
+		.init_setup	= init_setup_pdc20270,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20271,
-		name:		"PDC20271",
-		init_setup:	init_setup_pdcnew,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20271,
+		.name		= "PDC20271",
+		.init_setup	= init_setup_pdcnew,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20275,
-		name:		"PDC20275",
-		init_setup:	init_setup_pdcnew,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20275,
+		.name		= "PDC20275",
+		.init_setup	= init_setup_pdcnew,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 5 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20276,
-		name:		"PDC20276",
-		init_setup:	init_setup_pdc20276,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20276,
+		.name		= "PDC20276",
+		.init_setup	= init_setup_pdc20276,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{	/* 6 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20277,
-		name:		"PDC20277",
-		init_setup:	init_setup_pdcnew,
-		init_chipset:	init_chipset_pdcnew,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202new,
-		init_dma:	init_dma_pdc202new,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20277,
+		.name		= "PDC20277",
+		.init_setup	= init_setup_pdcnew,
+		.init_chipset	= init_chipset_pdcnew,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202new,
+		.init_dma	= init_dma_pdc202new,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h
--- a/drivers/ide/pci/pdc202xx_old.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/pdc202xx_old.h	Sun Nov 17 20:30:02 2002
@@ -209,10 +209,10 @@
 
 static ide_pci_host_proc_t pdc202xx_procs[] __initdata = {
 	{
-		name:		"pdc202xx",
-		set:		1,
-		get_info:	pdc202xx_get_info,
-		parent:		NULL,
+		.name		= "pdc202xx",
+		.set		= 1,
+		.get_info	= pdc202xx_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
@@ -227,99 +227,99 @@
 
 static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20246,
-		name:		"PDC20246",
-		init_setup:	init_setup_pdc202ata4,
-		init_chipset:	init_chipset_pdc202xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202xx,
-		init_dma:	init_dma_pdc202xx,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20246,
+		.name		= "PDC20246",
+		.init_setup	= init_setup_pdc202ata4,
+		.init_chipset	= init_chipset_pdc202xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202xx,
+		.init_dma	= init_dma_pdc202xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		16,
+		.bootable	= OFF_BOARD,
+		.extra		= 16,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20262,
-		name:		"PDC20262",
-		init_setup:	init_setup_pdc202ata4,
-		init_chipset:	init_chipset_pdc202xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202xx,
-		init_dma:	init_dma_pdc202xx,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20262,
+		.name		= "PDC20262",
+		.init_setup	= init_setup_pdc202ata4,
+		.init_chipset	= init_chipset_pdc202xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202xx,
+		.init_dma	= init_dma_pdc202xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		48,
+		.bootable	= OFF_BOARD,
+		.extra		= 48,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20263,
-		name:		"PDC20263",
-		init_setup:	init_setup_pdc202ata4,
-		init_chipset:	init_chipset_pdc202xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202xx,
-		init_dma:	init_dma_pdc202xx,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20263,
+		.name		= "PDC20263",
+		.init_setup	= init_setup_pdc202ata4,
+		.init_chipset	= init_chipset_pdc202xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202xx,
+		.init_dma	= init_dma_pdc202xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		48,
+		.bootable	= OFF_BOARD,
+		.extra		= 48,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20265,
-		name:		"PDC20265",
-		init_setup:	init_setup_pdc20265,
-		init_chipset:	init_chipset_pdc202xx,
-		init_hwif:	init_hwif_pdc202xx,
-		init_dma:	init_dma_pdc202xx,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20265,
+		.name		= "PDC20265",
+		.init_setup	= init_setup_pdc20265,
+		.init_chipset	= init_chipset_pdc202xx,
+		.init_hwif	= init_hwif_pdc202xx,
+		.init_dma	= init_dma_pdc202xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		48,
+		.bootable	= OFF_BOARD,
+		.extra		= 48,
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_PROMISE,
-		device:		PCI_DEVICE_ID_PROMISE_20267,
-		name:		"PDC20267",
-		init_setup:	init_setup_pdc202xx,
-		init_chipset:	init_chipset_pdc202xx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdc202xx,
-		init_dma:	init_dma_pdc202xx,
-		channels:	2,
-		autodma:	AUTODMA,
+		.vendor		= PCI_VENDOR_ID_PROMISE,
+		.device		= PCI_DEVICE_ID_PROMISE_20267,
+		.name		= "PDC20267",
+		.init_setup	= init_setup_pdc202xx,
+		.init_chipset	= init_chipset_pdc202xx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdc202xx,
+		.init_dma	= init_dma_pdc202xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
 #ifdef CONFIG_PDC202XX_FORCE
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 #else /* !CONFIG_PDC202XX_FORCE */
-		enablebits:	{{0x50,0x02,0x02}, {0x50,0x04,0x04}},
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
 #endif
-		bootable:	OFF_BOARD,
-		extra:		48,
+		.bootable	= OFF_BOARD,
+		.extra		= 48,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/pdcadma.h b/drivers/ide/pci/pdcadma.h
--- a/drivers/ide/pci/pdcadma.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/pdcadma.h	Sun Nov 17 20:30:02 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t pdcadma_procs[] __initdata = {
 	{
-		name:		"pdcadma",
-		set:		1,
-		get_info:	pdcadma_get_info,
-		parent:		NULL,
+		.name		= "pdcadma",
+		.set		= 1,
+		.get_info	= pdcadma_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -32,24 +32,24 @@
 
 static ide_pci_device_t pdcadma_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_PDC,
-		device:		PCI_DEVICE_ID_PDC_1841,
-		name:		"PDCADMA",
-		init_setup:	init_setup_pdcadma,
-		init_chipset:	init_chipset_pdcadma,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_pdcadma,
-		init_dma:	init_dma_pdcadma,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	OFF_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PDC,
+		.device		= PCI_DEVICE_ID_PDC_1841,
+		.name		= "PDCADMA",
+		.init_setup	= init_setup_pdcadma,
+		.init_chipset	= init_chipset_pdcadma,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_pdcadma,
+		.init_dma	= init_dma_pdcadma,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= OFF_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/piix.h b/drivers/ide/pci/piix.h
--- a/drivers/ide/pci/piix.h	Sun Nov 17 20:30:04 2002
+++ b/drivers/ide/pci/piix.h	Sun Nov 17 20:30:04 2002
@@ -19,10 +19,10 @@
 
 static ide_pci_host_proc_t piix_procs[] __devinitdata = {
 	{
-		name:		"piix",
-		set:		1,
-		get_info:	piix_get_info,
-		parent:		NULL,
+		.name		= "piix",
+		.set		= 1,
+		.get_info	= piix_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -40,235 +40,235 @@
  
 static ide_pci_device_t piix_pci_info[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82371FB_0,
-		name:		"PIIXa",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371FB_0,
+		.name		= "PIIXa",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82371FB_1,
-		name:		"PIIXb",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371FB_1,
+		.name		= "PIIXb",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82371MX,
-		name:		"MPIIX",
-		init_setup:	init_setup_piix,
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371MX,
+		.name		= "MPIIX",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82371SB_1,
-		name:		"PIIX3",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371SB_1,
+		.name		= "PIIX3",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 4 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82371AB,
-		name:		"PIIX4",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82371AB,
+		.name		= "PIIX4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 5 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801AB_1,
-		name:		"ICH0",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801AB_1,
+		.name		= "ICH0",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 6 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82443MX_1,
-		name:		"PIIX4",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82443MX_1,
+		.name		= "PIIX4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 7 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801AA_1,
-		name:		"ICH",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801AA_1,
+		.name		= "ICH",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 8 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82372FB_1,
-		name:		"PIIX4",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82372FB_1,
+		.name		= "PIIX4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 9 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82451NX,
-		name:		"PIIX4",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82451NX,
+		.name		= "PIIX4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 10 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801BA_9,
-		name:		"ICH2",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801BA_9,
+		.name		= "ICH2",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 11 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801BA_8,
-		name:		"ICH2M",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801BA_8,
+		.name		= "ICH2M",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 12 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801CA_10,
-		name:		"ICH3M",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801CA_10,
+		.name		= "ICH3M",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 13 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801CA_11,
-		name:		"ICH3",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801CA_11,
+		.name		= "ICH3",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 14 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801DB_11,
-		name:		"ICH4",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801DB_11,
+		.name		= "ICH4",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 15 */
-		vendor:		PCI_VENDOR_ID_INTEL,
-		device:		PCI_DEVICE_ID_INTEL_82801E_11,
-		name:		"C-ICH",
-		init_setup:	init_setup_piix,
-		init_chipset:	init_chipset_piix,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_piix,
-		init_dma:	init_dma_piix,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_82801E_11,
+		.name		= "C-ICH",
+		.init_setup	= init_setup_piix,
+		.init_chipset	= init_chipset_piix,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_piix,
+		.init_dma	= init_dma_piix,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		init_setup:	NULL,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.init_setup	= NULL,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/rz1000.h b/drivers/ide/pci/rz1000.h
--- a/drivers/ide/pci/rz1000.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/rz1000.h	Sun Nov 17 20:30:15 2002
@@ -9,36 +9,36 @@
 
 static ide_pci_device_t rz1000_chipsets[] __devinitdata = {
 {
-		vendor:		PCI_VENDOR_ID_PCTECH,
-		device:		PCI_DEVICE_ID_PCTECH_RZ1000,
-		name:		"RZ1000",
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_rz1000,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PCTECH,
+		.device		= PCI_DEVICE_ID_PCTECH_RZ1000,
+		.name		= "RZ1000",
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_rz1000,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		PCI_VENDOR_ID_PCTECH,
-		device:		PCI_DEVICE_ID_PCTECH_RZ1001,
-		name:		"RZ1001",
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_rz1000,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	NODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_PCTECH,
+		.device		= PCI_DEVICE_ID_PCTECH_RZ1001,
+		.name		= "RZ1001",
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_rz1000,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= NODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
--- a/drivers/ide/pci/serverworks.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/ide/pci/serverworks.c	Sun Nov 17 20:30:02 2002
@@ -801,8 +801,8 @@
 	.id_table	= svwks_pci_tbl,
 	.probe		= svwks_init_one,
 #if 0	/* FIXME: implement */
-	suspend:	,
-	resume:		,
+	.suspend	= ,
+	.resume		= ,
 #endif
 };
 
diff -Nru a/drivers/ide/pci/serverworks.h b/drivers/ide/pci/serverworks.h
--- a/drivers/ide/pci/serverworks.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/ide/pci/serverworks.h	Sun Nov 17 20:30:12 2002
@@ -23,10 +23,10 @@
 
 static ide_pci_host_proc_t svwks_procs[] __initdata = {
 {
-		name:		"svwks",
-		set:		1,
-		get_info:	svwks_get_info,
-		parent:		NULL,
+		.name		= "svwks",
+		.set		= 1,
+		.get_info	= svwks_get_info,
+		.parent		= NULL,
 	},
 };
 #endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -39,66 +39,66 @@
 
 static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_SERVERWORKS,
-		device:		PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,
-		name:		"SvrWks OSB4",
-		init_setup:	init_setup_svwks,
-		init_chipset:	init_chipset_svwks,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_svwks,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_SERVERWORKS,
+		.device		= PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,
+		.name		= "SvrWks OSB4",
+		.init_setup	= init_setup_svwks,
+		.init_chipset	= init_chipset_svwks,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_svwks,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_SERVERWORKS,
-		device:		PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,
-		name:		"SvrWks CSB5",
-		init_setup:	init_setup_svwks,
-		init_chipset:	init_chipset_svwks,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_svwks,
-		init_dma:	init_dma_svwks,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_SERVERWORKS,
+		.device		= PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,
+		.name		= "SvrWks CSB5",
+		.init_setup	= init_setup_svwks,
+		.init_chipset	= init_chipset_svwks,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_svwks,
+		.init_dma	= init_dma_svwks,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 2 */
-		vendor:		PCI_VENDOR_ID_SERVERWORKS,
-		device:		PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,
-		name:		"SvrWks CSB6",
-		init_setup:	init_setup_csb6,
-		init_chipset:	init_chipset_svwks,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_svwks,
-		init_dma:	init_dma_svwks,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_SERVERWORKS,
+		.device		= PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,
+		.name		= "SvrWks CSB6",
+		.init_setup	= init_setup_csb6,
+		.init_chipset	= init_chipset_svwks,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_svwks,
+		.init_dma	= init_dma_svwks,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 3 */
-		vendor:		PCI_VENDOR_ID_SERVERWORKS,
-		device:		PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,
-		name:		"SvrWks CSB6",
-		init_setup:	init_setup_csb6,
-		init_chipset:	init_chipset_svwks,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_svwks,
-		init_dma:	init_dma_svwks,
-		channels:	1,	/* 2 */
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_SERVERWORKS,
+		.device		= PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,
+		.name		= "SvrWks CSB6",
+		.init_setup	= init_setup_csb6,
+		.init_chipset	= init_chipset_svwks,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_svwks,
+		.init_dma	= init_dma_svwks,
+		.channels	= 1,	/* 2 */
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/siimage.h b/drivers/ide/pci/siimage.h
--- a/drivers/ide/pci/siimage.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/siimage.h	Sun Nov 17 20:30:14 2002
@@ -99,10 +99,10 @@
 
 static ide_pci_host_proc_t siimage_procs[] __initdata = {
 	{
-		name:		"siimage",
-		set:		1,
-		get_info:	siimage_get_info,
-		parent:		NULL,
+		.name		= "siimage",
+		.set		= 1,
+		.get_info	= siimage_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */	
@@ -114,36 +114,36 @@
 
 static ide_pci_device_t siimage_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_SII_680,
-		name:		"SiI680",
-		init_chipset:	init_chipset_siimage,
-		init_iops:	init_iops_siimage,
-		init_hwif:	init_hwif_siimage,
-		init_dma:	init_dma_siimage,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_SII_680,
+		.name		= "SiI680",
+		.init_chipset	= init_chipset_siimage,
+		.init_iops	= init_iops_siimage,
+		.init_hwif	= init_hwif_siimage,
+		.init_dma	= init_dma_siimage,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_CMD,
-		device:		PCI_DEVICE_ID_SII_3112,
-		name:		"SiI3112 Serial ATA",
-		init_chipset:	init_chipset_siimage,
-		init_iops:	init_iops_siimage,
-		init_hwif:	init_hwif_siimage,
-		init_dma:	init_dma_siimage,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_CMD,
+		.device		= PCI_DEVICE_ID_SII_3112,
+		.name		= "SiI3112 Serial ATA",
+		.init_chipset	= init_chipset_siimage,
+		.init_iops	= init_iops_siimage,
+		.init_hwif	= init_hwif_siimage,
+		.init_dma	= init_dma_siimage,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/sis5513.h b/drivers/ide/pci/sis5513.h
--- a/drivers/ide/pci/sis5513.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/sis5513.h	Sun Nov 17 20:30:14 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t sis_procs[] __initdata = {
 {
-		name:		"sis",
-		set:		1,
-		get_info:	sis_get_info,
-		parent:		NULL,
+		.name		= "sis",
+		.set		= 1,
+		.get_info	= sis_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -31,23 +31,23 @@
 
 static ide_pci_device_t sis5513_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_SI,
-		device:		PCI_DEVICE_ID_SI_5513,
-		name:		"SIS5513",
-		init_chipset:	init_chipset_sis5513,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_sis5513,
-		init_dma:	init_dma_sis5513,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-		bootable:	ON_BOARD,
-		extra:		0
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_5513,
+		.name		= "SIS5513",
+		.init_chipset	= init_chipset_sis5513,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_sis5513,
+		.init_dma	= init_dma_sis5513,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+		.bootable	= ON_BOARD,
+		.extra		= 0
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/sl82c105.h b/drivers/ide/pci/sl82c105.h
--- a/drivers/ide/pci/sl82c105.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/ide/pci/sl82c105.h	Sun Nov 17 20:30:15 2002
@@ -11,23 +11,23 @@
 
 static ide_pci_device_t sl82c105_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_WINBOND,
-		device:		PCI_DEVICE_ID_WINBOND_82C105,
-		name:		"W82C105",
-		init_chipset:	init_chipset_sl82c105,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_sl82c105,
-		init_dma:	init_dma_sl82c105,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x40,0x01,0x01}, {0x40,0x10,0x10}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_WINBOND,
+		.device		= PCI_DEVICE_ID_WINBOND_82C105,
+		.name		= "W82C105",
+		.init_chipset	= init_chipset_sl82c105,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_sl82c105,
+		.init_dma	= init_dma_sl82c105,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/slc90e66.h b/drivers/ide/pci/slc90e66.h
--- a/drivers/ide/pci/slc90e66.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/ide/pci/slc90e66.h	Sun Nov 17 20:30:12 2002
@@ -19,10 +19,10 @@
 
 static ide_pci_host_proc_t slc90e66_procs[] __initdata = {
 	{
-		name:		"slc90e66",
-		set:		1,
-		get_info:	slc90e66_get_info,
-		parent:		NULL,
+		.name		= "slc90e66",
+		.set		= 1,
+		.get_info	= slc90e66_get_info,
+		.parent		= NULL,
 	},
 };
 #endif	/* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -33,23 +33,23 @@
 
 static ide_pci_device_t slc90e66_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_EFAR,
-		device:		PCI_DEVICE_ID_EFAR_SLC90E66_1,
-		name:		"SLC90E66",
-		init_chipset:	init_chipset_slc90e66,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_slc90e66,
-		init_dma:	init_dma_slc90e66,
-		channels:	2,
-		autodma:	AUTODMA,
-		enablebits:	{{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_EFAR,
+		.device		= PCI_DEVICE_ID_EFAR_SLC90E66_1,
+		.name		= "SLC90E66",
+		.init_chipset	= init_chipset_slc90e66,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_slc90e66,
+		.init_dma	= init_dma_slc90e66,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/trm290.h b/drivers/ide/pci/trm290.h
--- a/drivers/ide/pci/trm290.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/trm290.h	Sun Nov 17 20:30:14 2002
@@ -9,23 +9,23 @@
 
 static ide_pci_device_t trm290_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_TEKRAM,
-		device:		PCI_DEVICE_ID_TEKRAM_DC290,
-		name:		"TRM290",
-		init_chipset:	NULL,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_trm290,
-		init_dma:	NULL,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_TEKRAM,
+		.device		= PCI_DEVICE_ID_TEKRAM_DC290,
+		.name		= "TRM290",
+		.init_chipset	= NULL,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_trm290,
+		.init_dma	= NULL,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ide/pci/via82cxxx.h b/drivers/ide/pci/via82cxxx.h
--- a/drivers/ide/pci/via82cxxx.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/ide/pci/via82cxxx.h	Sun Nov 17 20:30:14 2002
@@ -17,10 +17,10 @@
 
 static ide_pci_host_proc_t via_procs[] __initdata = {
 	{
-		name:		"via",
-		set:		1,
-		get_info:	via_get_info,
-		parent:		NULL,
+		.name		= "via",
+		.set		= 1,
+		.get_info	= via_get_info,
+		.parent		= NULL,
 	},
 };
 #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
@@ -31,36 +31,36 @@
 
 static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = {
 	{	/* 0 */
-		vendor:		PCI_VENDOR_ID_VIA,
-		device:		PCI_DEVICE_ID_VIA_82C576_1,
-		name:		"VP_IDE",
-		init_chipset:	init_chipset_via82cxxx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_via82cxxx,
-		init_dma:	init_dma_via82cxxx,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x40,0x02,0x02}, {0x40,0x01,0x01}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_82C576_1,
+		.name		= "VP_IDE",
+		.init_chipset	= init_chipset_via82cxxx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_via82cxxx,
+		.init_dma	= init_dma_via82cxxx,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{	/* 1 */
-		vendor:		PCI_VENDOR_ID_VIA,
-		device:		PCI_DEVICE_ID_VIA_82C586_1,
-		name:		"VP_IDE",
-		init_chipset:	init_chipset_via82cxxx,
-		init_iops:	NULL,
-		init_hwif:	init_hwif_via82cxxx,
-		init_dma:	init_dma_via82cxxx,
-		channels:	2,
-		autodma:	NOAUTODMA,
-		enablebits:	{{0x40,0x02,0x02}, {0x40,0x01,0x01}},
-		bootable:	ON_BOARD,
-		extra:		0,
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= PCI_DEVICE_ID_VIA_82C586_1,
+		.name		= "VP_IDE",
+		.init_chipset	= init_chipset_via82cxxx,
+		.init_iops	= NULL,
+		.init_hwif	= init_hwif_via82cxxx,
+		.init_dma	= init_dma_via82cxxx,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+		.bootable	= ON_BOARD,
+		.extra		= 0,
 	},{
-		vendor:		0,
-		device:		0,
-		channels:	0,
-		bootable:	EOL,
+		.vendor		= 0,
+		.device		= 0,
+		.channels	= 0,
+		.bootable	= EOL,
 	}
 };
 
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/ieee1394/dv1394.c	Sun Nov 17 20:30:15 2002
@@ -169,15 +169,6 @@
 
 static struct hpsb_highlevel *hl_handle; /* = NULL; */
 
-static LIST_HEAD(dv1394_devfs);
-struct dv1394_devfs_entry {
-	struct list_head list;
-    devfs_handle_t devfs;
-	char name[32];
-	struct dv1394_devfs_entry *parent;
-};
-static spinlock_t dv1394_devfs_lock = SPIN_LOCK_UNLOCKED;
-
 /* translate from a struct file* to the corresponding struct video_card* */
 
 static inline struct video_card* file_to_video_card(struct file *file)
@@ -2564,135 +2555,40 @@
 
 /*** DEVFS HELPERS *********************************************************/
 
-struct dv1394_devfs_entry *
-dv1394_devfs_find( char *name)
-{
-	struct list_head *lh;
-	struct dv1394_devfs_entry *p;
-
-	spin_lock( &dv1394_devfs_lock);
-	if(!list_empty(&dv1394_devfs)) {
-		list_for_each(lh, &dv1394_devfs) {
-			p = list_entry(lh, struct dv1394_devfs_entry, list);
-			if(!strncmp(p->name, name, sizeof(p->name))) {
-				goto found;
-			}
-		}
-	}
-	p = NULL;
-	
-found:
-	spin_unlock( &dv1394_devfs_lock);
-	return p;
-}
-
 #ifdef CONFIG_DEVFS_FS
 static int dv1394_devfs_add_entry(struct video_card *video)
 {
-	char buf[32];
-	struct dv1394_devfs_entry *p;
-	struct dv1394_devfs_entry *parent;
+	char buf[64];
+	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s",
+		(video->id>>2),
+		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+		(video->mode == MODE_RECEIVE ? "in" : "out"));
 
-	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
-	if(!p) {
-		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
-		goto err;
-	}
-	memset(p, 0, sizeof(struct dv1394_devfs_entry));
-	
-	snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),
-						(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));
-		
-	parent = dv1394_devfs_find(buf);
-	if (parent == NULL) {
-		printk(KERN_ERR "dv1394: unable to locate parent devfs of %s\n", buf);
-		goto err_free;
-	}
-	
-	video->devfs_handle = devfs_register(
-						 parent->devfs,
-					     (video->mode == MODE_RECEIVE ? "in" : "out"),
-						 DEVFS_FL_NONE,
+	video->devfs_handle = devfs_register(NULL, buf, DEVFS_FL_NONE,
 					     IEEE1394_MAJOR,
 					     IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
 					     S_IFCHR | S_IRUGO | S_IWUGO,
 					     &dv1394_fops,
 					     (void*) video);
-	p->devfs = video->devfs_handle;
-
-	if (p->devfs == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s/%s\n",
-			parent->name,
-			(video->mode == MODE_RECEIVE ? "in" : "out"));
-		goto err_free;
+	if (video->devfs_handle == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /dev/%s\n", buf);
+		return -ENOMEM;
 	}
-	
-	spin_lock( &dv1394_devfs_lock);
-	INIT_LIST_HEAD(&p->list);
-	list_add_tail(&p->list, &dv1394_devfs);
-	spin_unlock( &dv1394_devfs_lock);
-	
 	return 0;
-	
- err_free:
-	kfree(p);
- err:
-	return -ENOMEM;
 }
 
-static int
-dv1394_devfs_add_dir( char *name,
-					struct dv1394_devfs_entry *parent, 
-					struct dv1394_devfs_entry **out)
+static int dv1394_devfs_add_dir(char *name)
 {
-	struct dv1394_devfs_entry *p;
-
-	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
-	if(!p) {
-		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
-		goto err;
-	}
-	memset(p, 0, sizeof(struct dv1394_devfs_entry));
-	
-	if (parent == NULL) {
-		snprintf(p->name, sizeof(p->name), "%s", name);
-		p->devfs = devfs_mk_dir(ieee1394_devfs_handle, name, NULL);
-	} else {
-		snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);
-		p->devfs = devfs_mk_dir(parent->devfs, name, NULL);
+	if (!devfs_mk_dir(NULL, name, NULL))
+		printk(KERN_ERR "dv1394: unable to create /dev/%s\n", name);
+		return -ENOMEM;
 	}
-	if (p->devfs == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s\n", p->name);
-		goto err_free;
-	}
-
-	p->parent = parent;
-	if (out != NULL) *out = p;
-
-	spin_lock( &dv1394_devfs_lock);
-	INIT_LIST_HEAD(&p->list);
-	list_add_tail(&p->list, &dv1394_devfs);
-	spin_unlock( &dv1394_devfs_lock);
-
 	return 0;
-	
- err_free:
-	kfree(p);
- err:
-	return -ENOMEM;
 }
 
-void dv1394_devfs_del( char *name)
+void dv1394_devfs_del(char *name)
 {
-	struct dv1394_devfs_entry *p = dv1394_devfs_find(name);
-	if (p != NULL) {
-		devfs_unregister(p->devfs);
-		
-		spin_lock( &dv1394_devfs_lock);
-		list_del(&p->list);
-		spin_unlock( &dv1394_devfs_lock);
-		kfree(p);
-	}
+	devfs_remove("ieee1394/%s", name);
 }
 #endif /* CONFIG_DEVFS_FS */
 
@@ -2874,15 +2770,12 @@
 #endif
 
 #ifdef CONFIG_DEVFS_FS
-{
-	struct dv1394_devfs_entry *devfs_entry = dv1394_devfs_find("dv");
-	if (devfs_entry != NULL) {
-		snprintf(buf, sizeof(buf), "host%d", ohci->id);
-		dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry);
-		dv1394_devfs_add_dir("NTSC", devfs_entry, NULL);
-		dv1394_devfs_add_dir("PAL", devfs_entry, NULL);
-	}
-}
+	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d", ohci->id);
+	dv1394_devfs_add_dir(buf);
+	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/NTSC", ohci->id);
+	dv1394_devfs_add_dir(buf);
+	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/PAL", ohci->id);
+	dv1394_devfs_add_dir(buf);
 #endif
 	
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
@@ -3042,7 +2935,7 @@
 	}
 
 #ifdef CONFIG_DEVFS_FS
-	if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
+	if (dv1394_devfs_add_dir("ieee1394/dv") < 0) {
 		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 		return -ENOMEM;
diff -Nru a/drivers/input/Kconfig b/drivers/input/Kconfig
--- a/drivers/input/Kconfig	Sun Nov 17 20:30:03 2002
+++ b/drivers/input/Kconfig	Sun Nov 17 20:30:03 2002
@@ -5,7 +5,7 @@
 menu "Input device support"
 
 config INPUT
-	tristate
+	tristate "Input devices (needed for keyboard, mouse, ...)"
 	default y
 	---help---
 	  Say Y here if you have any input device (mouse, keyboard, tablet,
@@ -28,6 +28,7 @@
 
 config INPUT_MOUSEDEV
 	tristate "Mouse interface"
+	default y
 	depends on INPUT
 	---help---
 	  Say Y here if you want your mouse to be accessible as char devices
@@ -45,6 +46,7 @@
 
 config INPUT_MOUSEDEV_PSAUX
 	bool "Provide legacy /dev/psaux device"
+	default y
 	depends on INPUT_MOUSEDEV
 
 config INPUT_MOUSEDEV_SCREEN_X
diff -Nru a/drivers/input/evbug.c b/drivers/input/evbug.c
--- a/drivers/input/evbug.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/input/evbug.c	Sun Nov 17 20:30:13 2002
@@ -95,7 +95,12 @@
 
 int __init evbug_init(void)
 {
-	interface_register(&evbug_intf);
+	int retval;
+
+	retval = interface_register(&evbug_intf);
+	if(retval < 0)
+		return retval;
+
 	input_register_handler(&evbug_handler);
 	return 0;
 }
@@ -103,7 +108,7 @@
 void __exit evbug_exit(void)
 {
 	input_unregister_handler(&evbug_handler);
-	interface_register(&evbug_intf);
+	interface_unregister(&evbug_intf);
 }
 
 module_init(evbug_init);
diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/evdev.c	Sun Nov 17 20:30:15 2002
@@ -442,7 +442,12 @@
 
 static int __init evdev_init(void)
 {
-	interface_register(&evdev_intf);
+	int retval;
+
+	retval = interface_register(&evdev_intf);
+	if(retval < 0)
+		return retval;
+
 	input_register_handler(&evdev_handler);
 	return 0;
 }
@@ -450,7 +455,7 @@
 static void __exit evdev_exit(void)
 {
 	input_unregister_handler(&evdev_handler);
-	interface_register(&evdev_intf);
+	interface_unregister(&evdev_intf);
 }
 
 module_init(evdev_init);
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- a/drivers/input/gameport/emu10k1-gp.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/input/gameport/emu10k1-gp.c	Sun Nov 17 20:30:14 2002
@@ -84,7 +84,7 @@
 	emu->dev = pdev;
 
 	emu->gameport.io = ioport;
-	emu->gameport.name = pdev->name;
+	emu->gameport.name = pdev->dev.name;
 	emu->gameport.phys = emu->phys;
 	emu->gameport.id.bustype = BUS_PCI;
 	emu->gameport.id.vendor = pdev->vendor;
@@ -95,7 +95,7 @@
 	gameport_register_port(&emu->gameport);
 
 	printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
-		pdev->name, pdev->slot_name, emu->gameport.speed);
+		pdev->dev.name, pdev->slot_name, emu->gameport.speed);
 
 	return 0;
 }
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/input/joydev.c	Sun Nov 17 20:30:14 2002
@@ -499,7 +499,12 @@
 
 static int __init joydev_init(void)
 {
-	interface_register(&joydev_intf);
+	int retval;
+
+	retval = interface_register(&joydev_intf);
+	if(retval < 0)
+		return retval;
+
 	input_register_handler(&joydev_handler);
 	return 0;
 }
diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
--- a/drivers/input/keyboard/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/keyboard/Kconfig	Sun Nov 17 20:30:15 2002
@@ -3,6 +3,7 @@
 #
 config INPUT_KEYBOARD
 	bool "Keyboards"
+	default y
 	depends on INPUT
 	help
 	  Say Y here, and a list of supported keyboards will be displayed.
@@ -12,12 +13,13 @@
 
 config KEYBOARD_ATKBD
 	tristate "AT keyboard support"
+	default y
 	depends on INPUT && INPUT_KEYBOARD && SERIO
-	---help---
-	  Say Y here if you want to use the standard AT keyboard. Usually
-	  you'll need this, unless you have a different type keyboard (USB,
-	  ADB or other). This also works for AT keyboards connected over
-	  a PS/2 to serial converter.
+	help
+	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
+	  you'll need this, unless you have a different type keyboard (USB, ADB
+	  or other). This also works for AT and PS/2 keyboards connected over a
+	  PS/2 to serial converter.
 
 	  If unsure, say Y.
 
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/keyboard/atkbd.c	Sun Nov 17 20:30:15 2002
@@ -380,30 +380,39 @@
 			printk(KERN_WARNING "atkbd.c: keyboard reset failed\n");
 
 /*
- * Next we check we can set LEDs on the keyboard. This should work on every
- * keyboard out there. It also turns the LEDs off, which we want anyway.
- */
-
-	param[0] = 0;
-	if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
-		return -1;
-
-/*
  * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
  * Some keyboards report different values, but the first byte is always 0xab or
  * 0xac. Some old AT keyboards don't report anything.
  */
 
 	if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) {
+
+/*
+ * If the get ID command failed, we check if we can at least set the LEDs on
+ * the keyboard. This should work on every keyboard out there. It also turns
+ * the LEDs off, which we want anyway.
+ */
+		param[0] = 0;
+		if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+			return -1;
 		atkbd->id = 0xabba;
 		return 0;
 	}
+
 	if (param[0] != 0xab && param[0] != 0xac)
 		return -1;
 	atkbd->id = param[0] << 8;
 	if (atkbd_command(atkbd, param, ATKBD_CMD_GETID2))
 		return -1;
 	atkbd->id |= param[0];
+
+/*
+ * Set the LEDs to a defined state.
+ */
+
+	param[0] = 0;
+	if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+		return -1;
 
 /*
  * Disable autorepeat. We don't need it, as we do it in software anyway,
diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
--- a/drivers/input/misc/uinput.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/misc/uinput.c	Sun Nov 17 20:30:15 2002
@@ -111,8 +111,6 @@
 	struct uinput_device	*newdev;
 	struct input_dev	*newinput;
 
-	MOD_INC_USE_COUNT;
-
 	newdev = kmalloc(sizeof(struct uinput_device), GFP_KERNEL);
 	if (!newdev)
 		goto error;
@@ -131,7 +129,6 @@
 cleanup:
 	kfree(newdev);
 error:
-	MOD_DEC_USE_COUNT;
 	return -ENOMEM;
 }
 
@@ -296,11 +293,7 @@
 
 static int uinput_close(struct inode *inode, struct file *file)
 {
-	int	retval;
-
-	retval = uinput_burn_device((struct uinput_device *)file->private_data);
-	MOD_DEC_USE_COUNT;
-	return retval;
+	return uinput_burn_device((struct uinput_device *)file->private_data);
 }
 
 static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
--- a/drivers/input/mouse/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/mouse/Kconfig	Sun Nov 17 20:30:15 2002
@@ -3,6 +3,7 @@
 #
 config INPUT_MOUSE
 	bool "Mice"
+	default y
 	depends on INPUT
 	help
 	  Say Y here, and a list of supported mice will be displayed.
@@ -12,6 +13,7 @@
 
 config MOUSE_PS2
 	tristate "PS/2 mouse"
+	default y
 	depends on INPUT && INPUT_MOUSE && SERIO
 	---help---
 	  Say Y here if you have a PS/2 mouse connected to your system. This
diff -Nru a/drivers/input/mouse/psmouse.c b/drivers/input/mouse/psmouse.c
--- a/drivers/input/mouse/psmouse.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/input/mouse/psmouse.c	Sun Nov 17 20:30:12 2002
@@ -312,6 +312,26 @@
 		return PSMOUSE_PS2;
 
 /*
+ * Try Synaptics TouchPad magic ID
+ */
+
+       param[0] = 0;
+       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+       psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+       if (param[1] == 0x47) {
+               /* We could do more here. But it's sufficient just
+                  to stop the subsequent probes from screwing the
+                  thing up. */
+               psmouse->vendor = "Synaptics";
+               psmouse->name = "TouchPad";
+               return PSMOUSE_PS2;
+       }
+
+/*
  * Try Genius NetMouse magic init.
  */
 
@@ -348,7 +368,7 @@
 
 		int i;
 		static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
-		static int logitech_wheel[] = { 52, 75, 76, 80, 81, 83, 88, -1 };
+		static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, -1 };
 		static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
 							76, 80, 81, 83, 88, 96, 97, -1 };
 		psmouse->vendor = "Logitech";
diff -Nru a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
--- a/drivers/input/mouse/rpcmouse.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/input/mouse/rpcmouse.c	Sun Nov 17 20:30:13 2002
@@ -2,7 +2,7 @@
  *  Acorn RiscPC mouse driver for Linux/ARM
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik
- *  Copyright (C) 1996-1998 Russell King
+ *  Copyright (C) 1996-2002 Russell King
  *
  */
 
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/input/mousedev.c	Sun Nov 17 20:30:15 2002
@@ -41,6 +41,7 @@
 	int exist;
 	int open;
 	int minor;
+	int misc;
 	char name[16];
 	wait_queue_head_t wait;
 	struct list_head list;
@@ -489,7 +490,11 @@
 
 static int __init mousedev_init(void)
 {
-	interface_register(&mousedev_intf);
+	int retval;
+
+	if((retval = interface_register(&mousedev_intf)) < 0)
+		return retval;
+
 	input_register_handler(&mousedev_handler);
 
 	memset(&mousedev_mix, 0, sizeof(struct mousedev));
@@ -499,8 +504,10 @@
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 	mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
+
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
-	misc_register(&psaux_mouse);
+	if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
+		printk(KERN_WARNING "mice: could not misc_register the device\n");
 #endif
 
 	printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n");
@@ -511,7 +518,8 @@
 static void __exit mousedev_exit(void)
 {
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
-	misc_deregister(&psaux_mouse);
+	if (mousedev_mix.misc)
+		misc_deregister(&psaux_mouse);
 #endif
 	input_unregister_minor(mousedev_mix.devfs);
 	input_unregister_handler(&mousedev_handler);
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/drivers/input/serio/Kconfig	Sun Nov 17 20:30:14 2002
@@ -2,7 +2,8 @@
 # Input core configuration
 #
 config SERIO
-	tristate "Serial i/o support"
+	tristate "Serial i/o support (needed for keyboard and mouse)"
+	default y
 	---help---
 	  Say Yes here if you have any input device that uses serial I/O to
 	  communicate with the system. This includes the 
@@ -19,6 +20,7 @@
 
 config SERIO_I8042
 	tristate "i8042 PC Keyboard controller"
+	default y
 	depends on SERIO
 	---help---
 	  i8042 is the chip over which the standard AT keyboard and PS/2
@@ -34,6 +36,7 @@
 
 config SERIO_SERPORT
 	tristate "Serial port line discipline"
+	default y
 	depends on SERIO
 	---help---
 	  Say Y here if you plan to use an input device (mouse, joystick,
diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
--- a/drivers/input/serio/i8042.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/input/serio/i8042.c	Sun Nov 17 20:30:03 2002
@@ -10,16 +10,16 @@
  * the Free Software Foundation.
  */
 
-#include <asm/io.h>
-
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/config.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/serio.h>
-#include <linux/sched.h>
+
+#include <asm/io.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
diff -Nru a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
--- a/drivers/input/serio/rpckbd.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/input/serio/rpckbd.c	Sun Nov 17 20:30:02 2002
@@ -2,11 +2,7 @@
  * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Russell King
- *
- * Fixes by Russell King.
+ *  Copyright (c) 2002 Russell King
  */
 
 /*
@@ -44,7 +40,7 @@
 #include <asm/hardware/iomd.h>
 #include <asm/system.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- a/drivers/input/serio/serio.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/input/serio/serio.c	Sun Nov 17 20:30:02 2002
@@ -115,7 +115,7 @@
 			refrigerator(PF_IOTHREAD);
 	} while (!signal_pending(current));
 
-	printk(KERN_DEBUG "serio: kseriod exiting");
+	printk(KERN_DEBUG "serio: kseriod exiting\n");
 
 	unlock_kernel();
 	complete_and_exit(&serio_exited, 0);
@@ -139,8 +139,9 @@
 {       
         if (serio->dev && serio->dev->interrupt) 
                 serio->dev->interrupt(serio, data, flags);
-	else
-		serio_rescan(serio);
+	else 
+		if (!flags)
+			serio_rescan(serio);
 }
 
 void serio_register_port(struct serio *serio)
diff -Nru a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
--- a/drivers/isdn/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/Kconfig	Sun Nov 17 20:30:15 2002
@@ -41,7 +41,9 @@
 	  Therefore the old ISDN4Linux layer is becoming obsolete. It is 
 	  still usable, though, if you select this option.
 
+if ISDN
 source "drivers/isdn/i4l/Kconfig"
+endif
 
 endmenu
 
diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
--- a/drivers/isdn/capi/capi.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/capi/capi.c	Sun Nov 17 20:30:15 2002
@@ -1527,7 +1527,7 @@
 	proc_exit();
 
 	unregister_chrdev(capi_major, "capi20");
-	devfs_find_and_unregister(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0);
+	devfs_remove("isdn/capi20");
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	capinc_tty_exit();
diff -Nru a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig
--- a/drivers/isdn/hardware/avm/Kconfig	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/hardware/avm/Kconfig	Sun Nov 17 20:30:12 2002
@@ -12,7 +12,7 @@
 
 config ISDN_DRV_AVMB1_B1ISA
 	tristate "AVM B1 ISA support"
-	depends on CAPI_AVM && ISDN_CAPI && SA
+	depends on CAPI_AVM && ISDN_CAPI && ISA
 	help
 	  Enable support for the ISA version of the AVM B1 card.
 
diff -Nru a/drivers/isdn/hardware/eicon/adapter.h b/drivers/isdn/hardware/eicon/adapter.h
--- a/drivers/isdn/hardware/eicon/adapter.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/adapter.h	Sun Nov 17 20:30:15 2002
@@ -5,14 +5,13 @@
 
 #define DIVA_UM_IDI_ADAPTER_REMOVED 0x00000001
 
-typedef struct _diva_um_idi_adapter  {
-  diva_entity_link_t          link;
-  DESCRIPTOR                  d;
-  int                         adapter_nr;
-  diva_entity_queue_t         entity_q; /* entities linked to this adapter */
-  dword                       status;
+typedef struct _diva_um_idi_adapter {
+	diva_entity_link_t link;
+	DESCRIPTOR d;
+	int adapter_nr;
+	diva_entity_queue_t entity_q;	/* entities linked to this adapter */
+	dword status;
 } diva_um_idi_adapter_t;
 
 
 #endif
-
diff -Nru a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
--- a/drivers/isdn/hardware/eicon/capifunc.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/capifunc.c	Sun Nov 17 20:30:15 2002
@@ -31,33 +31,35 @@
 char DRIVERRELEASE[32];
 
 extern void AutomaticLaw(DIVA_CAPI_ADAPTER *);
-extern void callback (ENTITY *);
+extern void callback(ENTITY *);
 extern word api_remove_start(void);
 extern word CapiRelease(word);
 extern word CapiRegister(word);
-extern word api_put (APPL *, CAPI_MSG *);
+extern word api_put(APPL *, CAPI_MSG *);
 
 static diva_os_spin_lock_t api_lock;
 static diva_os_spin_lock_t ll_lock;
 
 static diva_card *cards;
 static dword notify_handle;
-static void DIRequest (ENTITY* e);
+static void DIRequest(ENTITY * e);
 static DESCRIPTOR MAdapter;
 static DESCRIPTOR DAdapter;
 static byte max_adapter = 0;
 static byte ControllerMap[MAX_DESCRIPTORS + 1];
 
 
-static void diva_register_appl(struct capi_ctr *, __u16 , capi_register_params *);
+static void diva_register_appl(struct capi_ctr *, __u16,
+			       capi_register_params *);
 static void diva_release_appl(struct capi_ctr *, __u16);
 static char *diva_procinfo(struct capi_ctr *);
-static u16 diva_send_message(struct capi_ctr *, diva_os_message_buffer_s *);
+static u16 diva_send_message(struct capi_ctr *,
+			     diva_os_message_buffer_s *);
 extern void diva_os_set_controller_struct(struct capi_ctr *);
 
 extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
 
-static void no_printf (unsigned char *, ...);
+static void no_printf(unsigned char *, ...);
 
 DIVA_DI_PRINTF dprintf = no_printf;
 
@@ -65,22 +67,20 @@
  * debug
  */
 #include "debuglib.c"
-void xlog (char * x, ...)
+void xlog(char *x, ...)
 {
-  va_list ap;
-  if ( myDriverDebugHandle.dbgMask & DL_XLOG )
-  {
-    va_start (ap, x) ;
-    if ( myDriverDebugHandle.dbg_irq )
-    {
-      myDriverDebugHandle.dbg_irq (myDriverDebugHandle.id, DLI_XLOG, x, ap);
-    }
-    else if ( myDriverDebugHandle.dbg_old )
-    {
-      myDriverDebugHandle.dbg_old (myDriverDebugHandle.id, x, ap) ;
-    }
-    va_end (ap) ;
-  }
+	va_list ap;
+	if (myDriverDebugHandle.dbgMask & DL_XLOG) {
+		va_start(ap, x);
+		if (myDriverDebugHandle.dbg_irq) {
+			myDriverDebugHandle.dbg_irq(myDriverDebugHandle.id,
+						    DLI_XLOG, x, ap);
+		} else if (myDriverDebugHandle.dbg_old) {
+			myDriverDebugHandle.dbg_old(myDriverDebugHandle.id,
+						    x, ap);
+		}
+		va_end(ap);
+	}
 }
 
 /*
@@ -88,23 +88,23 @@
  */
 static char *diva_procinfo(struct capi_ctr *ctrl)
 {
-		return(ctrl->serial);
-} 
+	return (ctrl->serial);
+}
 
 /*
  * stop debugging
  */
 static void stop_dbg(void)
 {
-		DbgDeregister();
-		memset(&MAdapter, 0, sizeof(MAdapter));
-		dprintf = no_printf;
+	DbgDeregister();
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
 
 /*
  * dummy debug function
  */
-static void no_printf (unsigned char * x ,...)
+static void no_printf(unsigned char *x, ...)
 {
 }
 
@@ -113,24 +113,21 @@
  */
 static byte MapController(byte Controller)
 {
-  byte i;
-  byte MappedController = 0;
-  byte ctrl = Controller & 0x7f;  /* mask external controller bit off */
-
-  for (i = 1; i < max_adapter + 1; i++)
-  {
-    if (ctrl == ControllerMap[i])
-    {
-      MappedController = (byte) i;
-      break;
-    }
-  }
-  if (i > max_adapter)
-  {
-    ControllerMap[0] = ctrl;
-    MappedController = 0;
-  }
-  return (MappedController | (Controller & 0x80)); /* put back external controller bit */
+	byte i;
+	byte MappedController = 0;
+	byte ctrl = Controller & 0x7f;	/* mask external controller bit off */
+
+	for (i = 1; i < max_adapter + 1; i++) {
+		if (ctrl == ControllerMap[i]) {
+			MappedController = (byte) i;
+			break;
+		}
+	}
+	if (i > max_adapter) {
+		ControllerMap[0] = ctrl;
+		MappedController = 0;
+	}
+	return (MappedController | (Controller & 0x80));	/* put back external controller bit */
 }
 
 /*
@@ -138,19 +135,16 @@
  */
 byte UnMapController(byte MappedController)
 {
-  byte Controller;
-  byte ctrl = MappedController & 0x7f;  /* mask external controller bit off */
+	byte Controller;
+	byte ctrl = MappedController & 0x7f;	/* mask external controller bit off */
 
-  if (ctrl <= max_adapter)
-  {
-    Controller = ControllerMap[ctrl];
-  }
-  else
-  {
-    Controller = 0;
-  }
+	if (ctrl <= max_adapter) {
+		Controller = ControllerMap[ctrl];
+	} else {
+		Controller = 0;
+	}
 
-  return (Controller | (MappedController & 0x80)); /* put back external controller bit */
+	return (Controller | (MappedController & 0x80));	/* put back external controller bit */
 }
 
 /*
@@ -158,76 +152,78 @@
  */
 static int find_free_id(void)
 {
-  int num = 0;
-  diva_card *p;
+	int num = 0;
+	diva_card *p;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "find free id");
-  while(num < 100) {
-    num++;
-    p = cards;
-    while (p) {
-      if (p->Id == num)
-        goto next_id;
-      p = p->next;
-    }
-		diva_os_leave_spin_lock (&ll_lock, &old_irql, "find free id");
-    return(num);
-next_id:;
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "find free id");
-  return(999);
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "find free id");
+	while (num < 100) {
+		num++;
+		p = cards;
+		while (p) {
+			if (p->Id == num)
+				goto next_id;
+			p = p->next;
+		}
+		diva_os_leave_spin_lock(&ll_lock, &old_irql,
+					"find free id");
+		return (num);
+	      next_id:
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "find free id");
+	return (999);
 }
 
 /*
  * find a card structure by controller number
  */
-static diva_card * find_card_by_ctrl(word controller)
+static diva_card *find_card_by_ctrl(word controller)
 {
-  diva_card *p;
+	diva_card *p;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "find card ctrl");
-  p = cards;
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card ctrl");
+	p = cards;
 
-  while (p) {
-    if (ControllerMap[p->Id] == controller) {
-			diva_os_leave_spin_lock (&ll_lock, &old_irql, "find card ctrl");
-      return p;
-    }
-    p = p->next;
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "find card ctrl");
-  return (diva_card *) 0;
+	while (p) {
+		if (ControllerMap[p->Id] == controller) {
+			diva_os_leave_spin_lock(&ll_lock, &old_irql,
+						"find card ctrl");
+			return p;
+		}
+		p = p->next;
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card ctrl");
+	return (diva_card *) 0;
 }
 
 /*
  * Buffer RX/TX 
  */
-void *TransmitBufferSet(APPL *appl, dword ref)
+void *TransmitBufferSet(APPL * appl, dword ref)
 {
-  appl->xbuffer_used[ref] = TRUE;
-  DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
-  return (void *) ref;
+	appl->xbuffer_used[ref] = TRUE;
+	DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
+	    return (void *) ref;
 }
 
-void *TransmitBufferGet(APPL *appl, void *p)
+void *TransmitBufferGet(APPL * appl, void *p)
 {
-  if(appl->xbuffer_internal[(dword)p])
-    return appl->xbuffer_internal[(dword)p];
+	if (appl->xbuffer_internal[(dword) p])
+		return appl->xbuffer_internal[(dword) p];
 
-  return appl->xbuffer_ptr[(dword)p];
+	return appl->xbuffer_ptr[(dword) p];
 }
 
-void TransmitBufferFree(APPL *appl, void *p)
+void TransmitBufferFree(APPL * appl, void *p)
 {
-  appl->xbuffer_used[(dword) p] = FALSE;
-  DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
+	appl->xbuffer_used[(dword) p] = FALSE;
+	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
 }
 
-void *ReceiveBufferGet(APPL *appl, int Num)
+void *ReceiveBufferGet(APPL * appl, int Num)
 {
-  return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
+	return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
 }
 
 /*
@@ -235,127 +231,125 @@
  */
 void api_remove_complete(void)
 {
-    DBG_PRV1(("api_remove_complete"))
+	DBG_PRV1(("api_remove_complete"))
 }
 
 /*
  * main function called by message.c
  */
-void sendf(APPL *appl, word command, dword Id, word Number, byte *format, ...)
+void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
 {
-  word i, j;
-  word length = 12, dlength = 0;
-  byte *write;
-  CAPI_MSG msg;
-  byte *string = 0;
-  va_list ap;
-  diva_os_message_buffer_s *dmb;
-  diva_card *card = NULL;
-  dword tmp;
-
-  if(!appl) return;
-
-  DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
-             appl->Id,command,(byte *)format))
-
-  WRITE_WORD(&msg.header.appl_id, appl->Id);
-  WRITE_WORD(&msg.header.command, command);
-  if((byte)(command>>8) == 0x82)
-    Number = appl->Number++;
-  WRITE_WORD(&msg.header.number, Number);
-
-  WRITE_DWORD(((byte *)&msg.header.controller), Id);
-  write = (byte *) &msg;
-  write += 12;
-
-  va_start(ap,format);
-  for(i=0; format[i]; i++) {
-    switch(format[i]) {
-      case 'b':
-        tmp = va_arg(ap,dword);
-        *(byte *)write = (byte)(tmp & 0xff);
-        write += 1;
-        length += 1;
-        break;
-      case 'w':
-        tmp = va_arg(ap,dword);
-        WRITE_WORD (write, (tmp & 0xffff));
-        write += 2;
-        length += 2;
-        break;
-      case 'd':
-        tmp = va_arg(ap,dword);
-        WRITE_DWORD(write, tmp);
-        write += 4;
-        length += 4;
-        break;
-      case 's':
-      case 'S':
-        string = va_arg(ap,byte *);
-        length += string[0]+1;
-        for(j = 0; j <= string[0]; j++)
-          *write++ = string[j];
-        break;
-    }
-  }
-  va_end(ap);
-
-  WRITE_WORD(&msg.header.length, length);
-  msg.header.controller = UnMapController(msg.header.controller);
-
-  if (command == _DATA_B3_I)
-    dlength = READ_WORD(((byte*)&msg.info.data_b3_ind.Data_Length));
-
-	if (!(dmb = diva_os_alloc_message_buffer(length + dlength, (void **)&write))) {
-    DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped."))
-    return;
-  }
-	
-  /* copy msg header to sk_buff */
-  memcpy(write, (byte *)&msg, length);
-
-  /* if DATA_B3_IND, copy data too */
-  if (command == _DATA_B3_I) {
-    dword data = READ_DWORD(((byte*)&msg.info.data_b3_ind.Data));
-    memcpy (write + length, (void *)data, dlength);
-  }
-
-  if ( myDriverDebugHandle.dbgMask & DL_XLOG )
-  {
-    switch ( command )
-    {
-      default:
-        xlog ("\x00\x02", &msg, 0x81, length) ;
-        break ;
-       case _DATA_B3_R|CONFIRM:
-        if ( myDriverDebugHandle.dbgMask & DL_BLK)
-          xlog ("\x00\x02", &msg, 0x81, length) ;
-        break ;
-       case _DATA_B3_I:
-        if ( myDriverDebugHandle.dbgMask & DL_BLK)
-        {
-          xlog ("\x00\x02", &msg, 0x81, length) ;
-          for (i = 0; i < dlength; i += 256)
-          {
-            DBG_BLK((((char *)msg.info.data_b3_ind.Data) + i,
-              ((dlength - i) < 256) ?
-               (dlength - i) : 256  ))
-            if ( !(myDriverDebugHandle.dbgMask & DL_PRV0) )
-              break ; // not more if not explicitely requested
-          }
-        }
-        break ;
-    }
-  }
-
-  /* find the card structure for this controller */
-  if(!(card = find_card_by_ctrl(write[8] & 0x7f))) {
-    DBG_ERR(("sendf - controller %d not found, incoming msg dropped", write[8] & 0x7f))
-    diva_os_free_message_buffer(dmb);
-    return;
-  }
-    
-  /* send capi msg to capi layer */
+	word i, j;
+	word length = 12, dlength = 0;
+	byte *write;
+	CAPI_MSG msg;
+	byte *string = 0;
+	va_list ap;
+	diva_os_message_buffer_s *dmb;
+	diva_card *card = NULL;
+	dword tmp;
+
+	if (!appl)
+		return;
+
+	DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
+		  appl->Id, command, (byte *) format))
+
+	    WRITE_WORD(&msg.header.appl_id, appl->Id);
+	WRITE_WORD(&msg.header.command, command);
+	if ((byte) (command >> 8) == 0x82)
+		Number = appl->Number++;
+	WRITE_WORD(&msg.header.number, Number);
+
+	WRITE_DWORD(((byte *) & msg.header.controller), Id);
+	write = (byte *) & msg;
+	write += 12;
+
+	va_start(ap, format);
+	for (i = 0; format[i]; i++) {
+		switch (format[i]) {
+		case 'b':
+			tmp = va_arg(ap, dword);
+			*(byte *) write = (byte) (tmp & 0xff);
+			write += 1;
+			length += 1;
+			break;
+		case 'w':
+			tmp = va_arg(ap, dword);
+			WRITE_WORD(write, (tmp & 0xffff));
+			write += 2;
+			length += 2;
+			break;
+		case 'd':
+			tmp = va_arg(ap, dword);
+			WRITE_DWORD(write, tmp);
+			write += 4;
+			length += 4;
+			break;
+		case 's':
+		case 'S':
+			string = va_arg(ap, byte *);
+			length += string[0] + 1;
+			for (j = 0; j <= string[0]; j++)
+				*write++ = string[j];
+			break;
+		}
+	}
+	va_end(ap);
+
+	WRITE_WORD(&msg.header.length, length);
+	msg.header.controller = UnMapController(msg.header.controller);
+
+	if (command == _DATA_B3_I)
+		dlength = READ_WORD(
+			      ((byte *) & msg.info.data_b3_ind.Data_Length));
+
+	if (!(dmb = diva_os_alloc_message_buffer(length + dlength,
+					  (void **) &write))) {
+		DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped."))
+		return;
+	}
+
+	/* copy msg header to sk_buff */
+	memcpy(write, (byte *) & msg, length);
+
+	/* if DATA_B3_IND, copy data too */
+	if (command == _DATA_B3_I) {
+		dword data = READ_DWORD(((byte *) & msg.info.data_b3_ind.Data));
+		memcpy(write + length, (void *) data, dlength);
+	}
+
+	if (myDriverDebugHandle.dbgMask & DL_XLOG) {
+		switch (command) {
+		default:
+			xlog("\x00\x02", &msg, 0x81, length);
+			break;
+		case _DATA_B3_R | CONFIRM:
+			if (myDriverDebugHandle.dbgMask & DL_BLK)
+				xlog("\x00\x02", &msg, 0x81, length);
+			break;
+		case _DATA_B3_I:
+			if (myDriverDebugHandle.dbgMask & DL_BLK) {
+				xlog("\x00\x02", &msg, 0x81, length);
+				for (i = 0; i < dlength; i += 256) {
+				  DBG_BLK((((char *) msg.info.data_b3_ind.
+					 Data) + i, ((dlength - i) < 256) ? (dlength - i) : 256))
+				  if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
+					  break; /* not more if not explicitely requested */
+				}
+			}
+			break;
+		}
+	}
+
+	/* find the card structure for this controller */
+	if (!(card = find_card_by_ctrl(write[8] & 0x7f))) {
+		DBG_ERR(("sendf - controller %d not found, incoming msg dropped",
+			 write[8] & 0x7f))
+		diva_os_free_message_buffer(dmb);
+		return;
+	}
+	/* send capi msg to capi layer */
 	capi_ctr_handle_message(&card->capi_ctrl, appl->Id, dmb);
 }
 
@@ -364,62 +358,54 @@
  */
 static void clean_adapter(int id)
 {
-  DIVA_CAPI_ADAPTER *a;
+	DIVA_CAPI_ADAPTER *a;
 #if IMPLEMENT_LINE_INTERCONNECT2
-  int i, k;
-#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
+	int i, k;
+#endif				/* IMPLEMENT_LINE_INTERCONNECT2 */
 
-  a = &adapter[id];
+	a = &adapter[id];
 #if IMPLEMENT_LINE_INTERCONNECT
-  if (a->li_pri)
-    {
-      if(a->li_config.pri)
-        diva_os_free(0, a->li_config.pri);
-    }
-  else
-    {
-      if(a->li_config.bri)
-        diva_os_free(0, a->li_config.bri);
-    }
-#endif /* IMPLEMENT_LINE_INTERCONNECT */
+	if (a->li_pri) {
+		if (a->li_config.pri)
+			diva_os_free(0, a->li_config.pri);
+	} else {
+		if (a->li_config.bri)
+			diva_os_free(0, a->li_config.bri);
+	}
+#endif				/* IMPLEMENT_LINE_INTERCONNECT */
 #if IMPLEMENT_LINE_INTERCONNECT2
-  k = li_total_channels - a->li_channels;
-  if (k == 0)
-  {
-    diva_os_free(0, li_config_table);
-    li_config_table = NULL;
-  }
-  else
-  {
-    if (a->li_base < k)
-    {
-      memmove(&li_config_table[a->li_base],
-              &li_config_table[a->li_base + a->li_channels],
-              (k - a->li_base) * sizeof(LI_CONFIG));
-      for (i = 0; i < k; i++)
-      {
-        memmove(&li_config_table[i].flag_table[a->li_base],
-                &li_config_table[i].flag_table[a->li_base + a->li_channels],
-                k - a->li_base);
-        memmove(&li_config_table[i].coef_table[a->li_base],
-                &li_config_table[i].coef_table[a->li_base + a->li_channels],
-                k - a->li_base);
-      }
-    }
-  }
-  li_total_channels = k;
-  for (i = id; i < max_adapter; i++)
-  {
-    if (adapter[i].request)
-      adapter[i].li_base -= a->li_channels;
-  }
-#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
-  if(a->plci)
-    diva_os_free(0, a->plci);
-
-  memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
-  while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
-    max_adapter--;
+	k = li_total_channels - a->li_channels;
+	if (k == 0) {
+		diva_os_free(0, li_config_table);
+		li_config_table = NULL;
+	} else {
+		if (a->li_base < k) {
+			memmove(&li_config_table[a->li_base],
+				&li_config_table[a->li_base + a->li_channels],
+				(k - a->li_base) * sizeof(LI_CONFIG));
+			for (i = 0; i < k; i++) {
+				memmove(&li_config_table[i].flag_table[a->li_base],
+					&li_config_table[i].flag_table[a->li_base + a->li_channels],
+					k - a->li_base);
+				memmove(&li_config_table[i].
+					coef_table[a->li_base],
+					&li_config_table[i].coef_table[a->li_base + a->li_channels],
+					k - a->li_base);
+			}
+		}
+	}
+	li_total_channels = k;
+	for (i = id; i < max_adapter; i++) {
+		if (adapter[i].request)
+			adapter[i].li_base -= a->li_channels;
+	}
+#endif				/* IMPLEMENT_LINE_INTERCONNECT2 */
+	if (a->plci)
+		diva_os_free(0, a->plci);
+
+	memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
+	while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
+		max_adapter--;
 }
 
 /*
@@ -427,497 +413,486 @@
  */
 static void DIVA_EXIT_FUNCTION divacapi_remove_cards(void)
 {
-  diva_card *last;
-  diva_card *card;
+	diva_card *last;
+	diva_card *card;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "remove cards");
-  card = cards;
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove cards");
+	card = cards;
 
-  while(card) {
+	while (card) {
 		detach_capi_ctr(&card->capi_ctrl);
-    clean_adapter(card->Id - 1);
-    DBG_TRC(("adapter remove, max_adapter=%d", max_adapter));
-    card = card->next;
-  }
-
-  card = cards;
-  while (card) {
-    last = card;
-    card = card->next;
-    diva_os_free(0, last);
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "remove cards");
+		clean_adapter(card->Id - 1);
+		DBG_TRC(("adapter remove, max_adapter=%d", max_adapter));
+		card = card->next;
+	}
+
+	card = cards;
+	while (card) {
+		last = card;
+		card = card->next;
+		diva_os_free(0, last);
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove cards");
 }
 
 /*
  * remove a card
  */
-static void divacapi_remove_card(DESCRIPTOR *d)
+static void divacapi_remove_card(DESCRIPTOR * d)
 {
-  diva_card *last;
-  diva_card *card;
+	diva_card *last;
+	diva_card *card;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "remove card");
-  last = card = cards;
-  while(card) {
-    if (card->d.request == d->request)
-    {
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");
+	last = card = cards;
+	while (card) {
+		if (card->d.request == d->request) {
 			detach_capi_ctr(&card->capi_ctrl);
-      clean_adapter(card->Id - 1);
-      DBG_TRC(("DelAdapterMap (%d) -> (%d)", ControllerMap[card->Id], card->Id))
-      ControllerMap[card->Id] = 0;
-      DBG_TRC(("adapter remove, max_adapter=%d", max_adapter));
-      if (card == last)
-        cards = card->next;
-      else
-        last->next = card->next;
-
-      diva_os_free(0, card);
-      break;
-    }
-    last = card;
-    card = card->next;
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "remove card");
+			clean_adapter(card->Id - 1);
+			DBG_TRC(
+				("DelAdapterMap (%d) -> (%d)",
+				 ControllerMap[card->Id], card->Id))
+			    ControllerMap[card->Id] = 0;
+			DBG_TRC(
+				("adapter remove, max_adapter=%d",
+				 max_adapter));
+			if (card == last)
+				cards = card->next;
+			else
+				last->next = card->next;
+
+			diva_os_free(0, card);
+			break;
+		}
+		last = card;
+		card = card->next;
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");
 }
 
 /*
  * sync_callback
  */
-static void sync_callback(ENTITY *e)
+static void sync_callback(ENTITY * e)
 {
 	diva_os_spin_lock_magic_t old_irql;
 
 	DBG_TRC(("cb:Id=%x,Rc=%x,Ind=%x", e->Id, e->Rc, e->Ind))
 
-	diva_os_enter_spin_lock (&api_lock, &old_irql, "sync_callback");
+	diva_os_enter_spin_lock(&api_lock, &old_irql, "sync_callback");
 	callback(e);
-	diva_os_leave_spin_lock (&api_lock, &old_irql, "sync_callback");
-} 
+	diva_os_leave_spin_lock(&api_lock, &old_irql, "sync_callback");
+}
 
 /*
  * add a new card
  */
-static int diva_add_card(DESCRIPTOR *d)
+static int diva_add_card(DESCRIPTOR * d)
 {
-  int k = 0, i = 0;
+	int k = 0, i = 0;
 	diva_os_spin_lock_magic_t old_irql;
-  diva_card *card = NULL;
-  struct capi_ctr *ctrl = NULL;
-  DIVA_CAPI_ADAPTER *a = NULL;
-  IDI_SYNC_REQ sync_req;
-  char serial[16];
+	diva_card *card = NULL;
+	struct capi_ctr *ctrl = NULL;
+	DIVA_CAPI_ADAPTER *a = NULL;
+	IDI_SYNC_REQ sync_req;
+	char serial[16];
 #if IMPLEMENT_LINE_INTERCONNECT2
-  LI_CONFIG *new_li_config_table;
-  int j;
-#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
-
-  if (!(card = (diva_card *) diva_os_malloc(0, sizeof(diva_card)))) {
-    DBG_ERR(("diva_add_card: failed to allocate card struct."))
-    return(0);
-  }
-  memset((char *)card, 0x00, sizeof(diva_card));
-  memcpy(&card->d, d, sizeof(DESCRIPTOR));
-  sync_req.GetName.Req = 0;
-  sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
-  card->d.request((ENTITY *)&sync_req);
-  strncpy(card->name, sync_req.GetName.name, sizeof(card->name));
-  ctrl = &card->capi_ctrl;
+	LI_CONFIG *new_li_config_table;
+	int j;
+#endif				/* IMPLEMENT_LINE_INTERCONNECT2 */
+
+	if (!(card = (diva_card *) diva_os_malloc(0, sizeof(diva_card)))) {
+		DBG_ERR(("diva_add_card: failed to allocate card struct."))
+		    return (0);
+	}
+	memset((char *) card, 0x00, sizeof(diva_card));
+	memcpy(&card->d, d, sizeof(DESCRIPTOR));
+	sync_req.GetName.Req = 0;
+	sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
+	card->d.request((ENTITY *) & sync_req);
+	strncpy(card->name, sync_req.GetName.name, sizeof(card->name));
+	ctrl = &card->capi_ctrl;
 	strcpy(ctrl->name, card->name);
 	ctrl->register_appl = diva_register_appl;
-	ctrl->release_appl  = diva_release_appl;
-	ctrl->send_message  = diva_send_message;
-	ctrl->procinfo      = diva_procinfo;
-	ctrl->driverdata    = card;
+	ctrl->release_appl = diva_release_appl;
+	ctrl->send_message = diva_send_message;
+	ctrl->procinfo = diva_procinfo;
+	ctrl->driverdata = card;
 	diva_os_set_controller_struct(ctrl);
 
 	if (attach_capi_ctr(ctrl)) {
-			DBG_ERR(("diva_add_card: failed to attach controller."))
-			diva_os_free(0, card);
-			return(0);
+		DBG_ERR(("diva_add_card: failed to attach controller."))
+		    diva_os_free(0, card);
+		return (0);
+	}
+	card->Id = find_free_id();
+	strncpy(ctrl->manu, M_COMPANY, CAPI_MANUFACTURER_LEN);
+	ctrl->version.majorversion = 2;
+	ctrl->version.minorversion = 0;
+	ctrl->version.majormanuversion = DRRELMAJOR;
+	ctrl->version.minormanuversion = DRRELMINOR;
+	sync_req.GetSerial.Req = 0;
+	sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
+	sync_req.GetSerial.serial = 0;
+	card->d.request((ENTITY *) & sync_req);
+	if ((i = ((sync_req.GetSerial.serial & 0xff000000) >> 24))) {
+		sprintf(serial, "%ld-%d",
+			sync_req.GetSerial.serial & 0x00ffffff, i + 1);
+	} else {
+		sprintf(serial, "%ld", sync_req.GetSerial.serial);
+	}
+	serial[CAPI_SERIAL_LEN - 1] = 0;
+	strncpy(ctrl->serial, serial, CAPI_SERIAL_LEN);
+
+	a = &adapter[card->Id - 1];
+	card->adapter = a;
+	a->os_card = card;
+	ControllerMap[card->Id] = (byte) (ctrl->cnr);
+
+	DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl->cnr, card->Id))
+
+	    sync_req.xdi_capi_prms.Req = 0;
+	sync_req.xdi_capi_prms.Rc = IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS;
+	sync_req.xdi_capi_prms.info.structure_length =
+	    sizeof(diva_xdi_get_capi_parameters_t);
+	card->d.request((ENTITY *) & sync_req);
+	a->flag_dynamic_l1_down =
+	    sync_req.xdi_capi_prms.info.flag_dynamic_l1_down;
+	a->group_optimization_enabled =
+	    sync_req.xdi_capi_prms.info.group_optimization_enabled;
+	a->request = DIRequest;	/* card->d.request; */
+	a->max_plci = card->d.channels + 30;
+	a->max_listen = (card->d.channels > 2) ? 8 : 2;
+	if (!
+	    (a->plci =
+	     (PLCI *) diva_os_malloc(0, sizeof(PLCI) * a->max_plci))) {
+		DBG_ERR(("diva_add_card: failed alloc plci struct."))
+		    memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
+		return (0);
+	}
+	memset(a->plci, 0, sizeof(PLCI) * a->max_plci);
+
+	for (k = 0; k < a->max_plci; k++) {
+		a->Id = (byte) card->Id;
+		a->plci[k].Sig.callback = sync_callback;
+		a->plci[k].Sig.XNum = 1;
+		a->plci[k].Sig.X = a->plci[k].XData;
+		a->plci[k].Sig.user[0] = (word) (card->Id - 1);
+		a->plci[k].Sig.user[1] = (word) k;
+		a->plci[k].NL.callback = sync_callback;
+		a->plci[k].NL.XNum = 1;
+		a->plci[k].NL.X = a->plci[k].XData;
+		a->plci[k].NL.user[0] = (word) ((card->Id - 1) | 0x8000);
+		a->plci[k].NL.user[1] = (word) k;
+		a->plci[k].adapter = a;
 	}
-  card->Id = find_free_id();
-  strncpy(ctrl->manu, M_COMPANY, CAPI_MANUFACTURER_LEN);
-  ctrl->version.majorversion = 2;
-  ctrl->version.minorversion = 0;
-  ctrl->version.majormanuversion = DRRELMAJOR;
-  ctrl->version.minormanuversion = DRRELMINOR;
-  sync_req.GetSerial.Req = 0;
-  sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
-  sync_req.GetSerial.serial = 0;
-  card->d.request((ENTITY *)&sync_req);
-  if ((i = ((sync_req.GetSerial.serial & 0xff000000) >> 24))) {
-    sprintf(serial, "%ld-%d",
-            sync_req.GetSerial.serial & 0x00ffffff, i + 1);
-  } else {
-    sprintf(serial, "%ld", sync_req.GetSerial.serial);
-  }
-  serial[CAPI_SERIAL_LEN-1] = 0;
-  strncpy(ctrl->serial, serial, CAPI_SERIAL_LEN);
-
-  a = &adapter[card->Id - 1];
-  card->adapter = a;
-  a->os_card = card;
-  ControllerMap[card->Id] = (byte)(ctrl->cnr);
-
-  DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl->cnr, card->Id))
-
-  sync_req.xdi_capi_prms.Req = 0;
-  sync_req.xdi_capi_prms.Rc = IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS;
-  sync_req.xdi_capi_prms.info.structure_length = sizeof(diva_xdi_get_capi_parameters_t);
-  card->d.request((ENTITY *)&sync_req);
-  a->flag_dynamic_l1_down = sync_req.xdi_capi_prms.info.flag_dynamic_l1_down;
-  a->group_optimization_enabled = sync_req.xdi_capi_prms.info.group_optimization_enabled;
-  a->request = DIRequest; /* card->d.request; */
-  a->max_plci = card->d.channels + 30;
-  a->max_listen = (card->d.channels > 2) ? 8 : 2;
-  if (!(a->plci = (PLCI *) diva_os_malloc(0, sizeof(PLCI) * a->max_plci))) {
-    DBG_ERR(("diva_add_card: failed alloc plci struct."))
-    memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
-    return(0);
-  }
-  memset(a->plci, 0, sizeof(PLCI) * a->max_plci);
-
-  for (k = 0; k < a->max_plci; k++)
-    {
-      a->Id = (byte)card->Id;
-      a->plci[k].Sig.callback = sync_callback;
-      a->plci[k].Sig.XNum = 1;
-      a->plci[k].Sig.X = a->plci[k].XData;
-      a->plci[k].Sig.user[0] = (word) (card->Id - 1);
-      a->plci[k].Sig.user[1] = (word) k;
-      a->plci[k].NL.callback = sync_callback;
-      a->plci[k].NL.XNum = 1;
-      a->plci[k].NL.X = a->plci[k].XData;
-      a->plci[k].NL.user[0] = (word) ((card->Id - 1) | 0x8000);
-      a->plci[k].NL.user[1] = (word) k;
-      a->plci[k].adapter = a;
-    }
-
-  a->profile.Number = card->Id;
-  a->profile.Channels = card->d.channels;
-  if (card->d.features & DI_FAX3)
-    {
-      a->profile.Global_Options = 0x71;
-      if (card->d.features & DI_CODEC)
-        a->profile.Global_Options |= 0x6;
+
+	a->profile.Number = card->Id;
+	a->profile.Channels = card->d.channels;
+	if (card->d.features & DI_FAX3) {
+		a->profile.Global_Options = 0x71;
+		if (card->d.features & DI_CODEC)
+			a->profile.Global_Options |= 0x6;
 #if IMPLEMENT_DTMF
-      a->profile.Global_Options |= 0x8;
-#endif /* IMPLEMENT_DTMF */
+		a->profile.Global_Options |= 0x8;
+#endif				/* IMPLEMENT_DTMF */
 #if (IMPLEMENT_LINE_INTERCONNECT || IMPLEMENT_LINE_INTERCONNECT2)
-      a->profile.Global_Options |= 0x80;
-#endif /* (IMPLEMENT_LINE_INTERCONNECT || IMPLEMENT_LINE_INTERCONNECT2) */
+		a->profile.Global_Options |= 0x80;
+#endif				/* (IMPLEMENT_LINE_INTERCONNECT || IMPLEMENT_LINE_INTERCONNECT2) */
 #if IMPLEMENT_ECHO_CANCELLER
-      a->profile.Global_Options |= 0x100;
-#endif /* IMPLEMENT_ECHO_CANCELLER */
-      a->profile.B1_Protocols = 0xdf;
-      a->profile.B2_Protocols = 0x1fdb;
-      a->profile.B3_Protocols = 0xb7;
-      a->manufacturer_features = MANUFACTURER_FEATURE_HARDDTMF;
-    }
-  else
-    {
-      a->profile.Global_Options = 0x71;
-      if (card->d.features & DI_CODEC)
-        a->profile.Global_Options |= 0x2;
-      a->profile.B1_Protocols = 0x43;
-      a->profile.B2_Protocols = 0x1f0f;
-      a->profile.B3_Protocols = 0x07;
-      a->manufacturer_features = 0;
-    }
+		a->profile.Global_Options |= 0x100;
+#endif				/* IMPLEMENT_ECHO_CANCELLER */
+		a->profile.B1_Protocols = 0xdf;
+		a->profile.B2_Protocols = 0x1fdb;
+		a->profile.B3_Protocols = 0xb7;
+		a->manufacturer_features = MANUFACTURER_FEATURE_HARDDTMF;
+	} else {
+		a->profile.Global_Options = 0x71;
+		if (card->d.features & DI_CODEC)
+			a->profile.Global_Options |= 0x2;
+		a->profile.B1_Protocols = 0x43;
+		a->profile.B2_Protocols = 0x1f0f;
+		a->profile.B3_Protocols = 0x07;
+		a->manufacturer_features = 0;
+	}
 
 #if IMPLEMENT_LINE_INTERCONNECT
-  a->li_pri = (a->profile.Channels > 2);
-  if (a->li_pri)
-    {
-      if (!(a->li_config.pri = (LI_CONFIG_PRI *) diva_os_malloc(0, sizeof(LI_CONFIG_PRI)))) {
-        DBG_ERR(("diva_add_card: failed alloc li_config.pri struct."))
-        memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
-        return(0);
-      }
-      memset(a->li_config.pri, 0, sizeof(LI_CONFIG_PRI));
-    }
-  else
-    {
-      if (!(a->li_config.bri = (LI_CONFIG_BRI *) diva_os_malloc(0, sizeof(LI_CONFIG_BRI)))) {
-        DBG_ERR(("diva_add_card: failed alloc li_config.bri struct."))
-        memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
-        return(0);
-      }
-      memset(a->li_config.bri, 0, sizeof(LI_CONFIG_BRI));
-    }
-#endif /* IMPLEMENT_LINE_INTERCONNECT */
+	a->li_pri = (a->profile.Channels > 2);
+	if (a->li_pri) {
+		if (!(a->li_config.pri = (LI_CONFIG_PRI *) diva_os_malloc(0, sizeof(LI_CONFIG_PRI)))) {
+			DBG_ERR(("diva_add_card: failed alloc li_config.pri struct."))
+			memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
+			return (0);
+		}
+		memset(a->li_config.pri, 0, sizeof(LI_CONFIG_PRI));
+	} else 
+		if (!(a->li_config.bri = (LI_CONFIG_BRI *) diva_os_malloc(0, sizeof(LI_CONFIG_BRI)))) {
+			DBG_ERR(("diva_add_card: failed alloc li_config.bri struct."))
+			memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
+			return (0);
+		}
+		memset(a->li_config.bri, 0, sizeof(LI_CONFIG_BRI));
+	}
+#endif				/* IMPLEMENT_LINE_INTERCONNECT */
 #if IMPLEMENT_LINE_INTERCONNECT2
-  a->li_pri = (a->profile.Channels > 2);
-  a->li_channels = a->li_pri ? MIXER_CHANNELS_PRI : MIXER_CHANNELS_BRI;
-  a->li_base = 0;
-  for (i = 0; &adapter[i] != a; i++)
-  {
-    if (adapter[i].request)
-      a->li_base = adapter[i].li_base + adapter[i].li_channels;
-  }
-  k = li_total_channels + a->li_channels;
-  new_li_config_table = (LI_CONFIG *) diva_os_malloc(0,
-    ((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * k) * ((k + 3) & ~3));
-  if (new_li_config_table == NULL)
-  {
-    DBG_ERR(("diva_add_card: failed alloc li_config table."))
-    memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
-    return(0);
-  }
-  j = 0;
-  for (i = 0; i < k; i++)
-  {
-    if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
-      memset(&new_li_config_table[i], 0, sizeof(LI_CONFIG));
-    else
-      memcpy(&new_li_config_table[i], &li_config_table[j], sizeof(LI_CONFIG));
-    new_li_config_table[i].flag_table = ((byte *) new_li_config_table) +
-      (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i) * ((k + 3) & ~3));
-    new_li_config_table[i].coef_table = ((byte *) new_li_config_table) +
-      (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i + 1) * ((k + 3) & ~3));
-    if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
-    {
-      new_li_config_table[i].adapter = a;
-      memset(&new_li_config_table[i].flag_table[0], 0, k);
-      memset(&new_li_config_table[i].coef_table[0], 0, k);
-    }
-    else
-    {
-      if (a->li_base != 0)
-      {
-        memcpy(&new_li_config_table[i].flag_table[0],
-               &li_config_table[j].flag_table[0],
-               a->li_base);
-        memcpy(&new_li_config_table[i].coef_table[0],
-               &li_config_table[j].coef_table[0],
-               a->li_base);
-      }
-      memset(&new_li_config_table[i].flag_table[a->li_base], 0, a->li_channels);
-      memset(&new_li_config_table[i].coef_table[a->li_base], 0, a->li_channels);
-      if (a->li_base + a->li_channels < k)
-      {
-        memcpy(&new_li_config_table[i].flag_table[a->li_base + a->li_channels],
-               &li_config_table[j].flag_table[a->li_base],
-               k - (a->li_base + a->li_channels));
-        memcpy(&new_li_config_table[i].coef_table[a->li_base + a->li_channels],
-               &li_config_table[j].coef_table[a->li_base],
-               k - (a->li_base + a->li_channels));
-      }
-      j++;
-    }
-  }
-  li_total_channels = k;
-
-  if (li_config_table != NULL)
-    diva_os_free(0, li_config_table);
-		
-  li_config_table = new_li_config_table;
-  for (i = card->Id; i < max_adapter; i++)
-  {
-    if (adapter[i].request)
-      adapter[i].li_base += a->li_channels;
-  }
-#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
-
-  if (a == &adapter[max_adapter])
-    max_adapter++;
-		
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "add card");
+	a->li_pri = (a->profile.Channels > 2);
+	a->li_channels = a->li_pri ? MIXER_CHANNELS_PRI : MIXER_CHANNELS_BRI;
+	a->li_base = 0;
+	for (i = 0; &adapter[i] != a; i++) {
+		if (adapter[i].request)
+			a->li_base = adapter[i].li_base + adapter[i].li_channels;
+	}
+	k = li_total_channels + a->li_channels;
+	new_li_config_table =
+		(LI_CONFIG *) diva_os_malloc(0, ((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * k) * ((k + 3) & ~3));
+	if (new_li_config_table == NULL) {
+		DBG_ERR(("diva_add_card: failed alloc li_config table."))
+		memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
+		return (0);
+	}
+	j = 0;
+	for (i = 0; i < k; i++) {
+		if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
+			memset(&new_li_config_table[i], 0, sizeof(LI_CONFIG));
+		else
+			memcpy(&new_li_config_table[i], &li_config_table[j], sizeof(LI_CONFIG));
+		new_li_config_table[i].flag_table =
+			((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i) * ((k + 3) & ~3));
+		new_li_config_table[i].coef_table =
+			((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i + 1) * ((k + 3) & ~3));
+		if ((i >= a->li_base) && (i < a->li_base + a->li_channels)) {
+			new_li_config_table[i].adapter = a;
+			memset(&new_li_config_table[i].flag_table[0], 0, k);
+			memset(&new_li_config_table[i].coef_table[0], 0, k);
+		} else {
+			if (a->li_base != 0) {
+				memcpy(&new_li_config_table[i].flag_table[0],
+				       &li_config_table[j].flag_table[0],
+				       a->li_base);
+				memcpy(&new_li_config_table[i].coef_table[0],
+				       &li_config_table[j].coef_table[0],
+				       a->li_base);
+			}
+			memset(&new_li_config_table[i].flag_table[a->li_base], 0, a->li_channels);
+			memset(&new_li_config_table[i].coef_table[a->li_base], 0, a->li_channels);
+			if (a->li_base + a->li_channels < k) {
+				memcpy(&new_li_config_table[i].flag_table[a->li_base +
+				       a->li_channels],
+				       &li_config_table[j].flag_table[a->li_base],
+				       k - (a->li_base + a->li_channels));
+				memcpy(&new_li_config_table[i].coef_table[a->li_base +
+				       a->li_channels],
+				       &li_config_table[j].coef_table[a->li_base],
+				       k - (a->li_base + a->li_channels));
+			}
+			j++;
+		}
+	}
+	li_total_channels = k;
+
+	if (li_config_table != NULL)
+		diva_os_free(0, li_config_table);
+
+	li_config_table = new_li_config_table;
+	for (i = card->Id; i < max_adapter; i++) {
+		if (adapter[i].request)
+			adapter[i].li_base += a->li_channels;
+	}
+#endif				/* IMPLEMENT_LINE_INTERCONNECT2 */
+
+	if (a == &adapter[max_adapter])
+		max_adapter++;
+
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");
 	card->next = cards;
 	cards = card;
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "add card");
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");
 
-  AutomaticLaw(a);
+	AutomaticLaw(a);
 	i = 0;
-  while(i++ < 30) {
-    if (a->automatic_law > 3)
-      break;
+	while (i++ < 30) {
+		if (a->automatic_law > 3)
+			break;
 		diva_os_sleep(10);
-  }
+	}
 
-  /* profile information */
-  ctrl->profile.nbchannel = card->d.channels;
-  ctrl->profile.goptions = a->profile.Global_Options;
-  ctrl->profile.support1 = a->profile.B1_Protocols;
-  ctrl->profile.support2 = a->profile.B2_Protocols;
-  ctrl->profile.support3 = a->profile.B3_Protocols;
-  /* manufacturer profile information */
-  ctrl->profile.manu[0] = a->man_profile.private_options;
-  ctrl->profile.manu[1] = a->man_profile.rtp_primary_payloads;
-  ctrl->profile.manu[2] = a->man_profile.rtp_additional_payloads;
-  ctrl->profile.manu[3] = 0;
-  ctrl->profile.manu[4] = 0;
+	/* profile information */
+	ctrl->profile.nbchannel = card->d.channels;
+	ctrl->profile.goptions = a->profile.Global_Options;
+	ctrl->profile.support1 = a->profile.B1_Protocols;
+	ctrl->profile.support2 = a->profile.B2_Protocols;
+	ctrl->profile.support3 = a->profile.B3_Protocols;
+	/* manufacturer profile information */
+	ctrl->profile.manu[0] = a->man_profile.private_options;
+	ctrl->profile.manu[1] = a->man_profile.rtp_primary_payloads;
+	ctrl->profile.manu[2] = a->man_profile.rtp_additional_payloads;
+	ctrl->profile.manu[3] = 0;
+	ctrl->profile.manu[4] = 0;
 
-  capi_ctr_ready(ctrl);
+	capi_ctr_ready(ctrl);
 
-  DBG_TRC(("adapter added, max_adapter=%d", max_adapter));
-  return(1);
+	DBG_TRC(("adapter added, max_adapter=%d", max_adapter));
+	return (1);
 }
 
 /*
  *  register appl
  */
-static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
+static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl,
+			       capi_register_params * rp)
 {
-  APPL *this;
-  word bnum, xnum;
-  int i = 0, j = 0;
-  void * DataNCCI, * DataFlags, * ReceiveBuffer, * xbuffer_used; 
-  void ** xbuffer_ptr, ** xbuffer_internal;
+	APPL *this;
+	word bnum, xnum;
+	int i = 0, j = 0;
+	void *DataNCCI, *DataFlags, *ReceiveBuffer, *xbuffer_used;
+	void **xbuffer_ptr, **xbuffer_internal;
 	diva_os_spin_lock_magic_t old_irql;
 
-  DIVA_LOCK_MODULE;
+	DIVA_LOCK_MODULE;
+
+	if (diva_os_in_irq()) {
+		DBG_ERR(("CAPI_REGISTER - in irq context !"))
+		return;
+	}
+
+	DBG_TRC(("application register"))
 
-  if(diva_os_in_irq()) {
-    DBG_ERR(("CAPI_REGISTER - in irq context !"))
-    return;
-  }
-
-  DBG_TRC(("application register"))
-
-  if(appl > MAX_APPL) {
-    DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
-    return; 
-  }
-
-  if (rp->level3cnt < 1 ||
-      rp->level3cnt > 255 ||
-      rp->datablklen < 80 ||
-      rp->datablklen > 2150 ||
-      rp->datablkcnt > 255)
-  {
-    DBG_ERR(("CAPI_REGISTER - invalid parameters"))
-    return; 
-  }
-
-  if (application[appl - 1].Id == appl) {
-    DBG_ERR(("CAPI_REGISTER - appl already registered"))
-    return; /* appl already registered */
-  }
-
-  /* alloc memory */
-
-  bnum = rp->level3cnt * rp->datablkcnt;
-  xnum = rp->level3cnt * MAX_DATA_B3;
-
-  if(!(DataNCCI = diva_os_malloc(0, bnum * sizeof(word)))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    return;
-  }
-  memset(DataNCCI, 0, bnum * sizeof(word));
-
-  if(!(DataFlags = diva_os_malloc(0, bnum * sizeof(word)))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    diva_os_free(0, DataNCCI);
-    return;
-  }
-  memset(DataFlags, 0, bnum * sizeof(word));
-
-  if(!(ReceiveBuffer = diva_os_malloc(0, bnum * rp->datablklen))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    diva_os_free(0, DataNCCI);
-    diva_os_free(0, DataFlags);
-    return;
-  }
-  memset(ReceiveBuffer, 0, bnum * rp->datablklen);
-
-  if(!(xbuffer_used = (byte *) diva_os_malloc(0, xnum))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    diva_os_free(0, DataNCCI);
-    diva_os_free(0, DataFlags);
-    diva_os_free(0, ReceiveBuffer);
-    return;
-  }
-  memset(xbuffer_used, 0, xnum);
-
-  if(!(xbuffer_ptr = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    diva_os_free(0, DataNCCI);
-    diva_os_free(0, DataFlags);
-    diva_os_free(0, ReceiveBuffer);
-    diva_os_free(0, xbuffer_used);
-    return;
-  }
-  memset(xbuffer_ptr, 0, xnum * sizeof(void *));
-
-  if(!(xbuffer_internal = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) {
-    DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-    diva_os_free(0, DataNCCI);
-    diva_os_free(0, DataFlags);
-    diva_os_free(0, ReceiveBuffer);
-    diva_os_free(0, xbuffer_used);
-    diva_os_free(0, xbuffer_ptr);
-    return;
-  }
-  memset(xbuffer_internal, 0, xnum * sizeof(void *));
-
-  for ( i = 0 ; i < xnum ; i++ )
-  {
-    xbuffer_ptr[i] = diva_os_malloc(0, rp->datablklen) ;
-    if ( !xbuffer_ptr[i] )
-    {
-      DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
-      if (i) {
-        for(j = 0; j < i; j++)
-          if(xbuffer_ptr[j])
-            diva_os_free(0, xbuffer_ptr[j]);
-      }
-      diva_os_free(0, DataNCCI);
-      diva_os_free(0, DataFlags);
-      diva_os_free(0, ReceiveBuffer);
-      diva_os_free(0, xbuffer_used);
-      diva_os_free(0, xbuffer_ptr);
-      diva_os_free(0, xbuffer_internal);
-      return;  
-    }
-  }
-
-  DBG_LOG(("CAPI_REGISTER - Id = %d", appl))
-  DBG_LOG(("  MaxLogicalConnections = %d", rp->level3cnt))
-  DBG_LOG(("  MaxBDataBuffers       = %d", rp->datablkcnt))
-  DBG_LOG(("  MaxBDataLength        = %d", rp->datablklen))
-
-  /* initialize application data */
-
-	diva_os_enter_spin_lock (&api_lock, &old_irql, "register_appl");
-
-  this = &application[appl - 1] ;
-  memset(this, 0, sizeof (APPL));
-
-  this->Id = appl;
-
-  /* We do not need a list */
-  /* InitializeListHead(&this->s_function); */
-
-  for (i = 0; i < max_adapter; i++)
-  {
-    adapter[i].CIP_Mask[appl - 1] = 0;
-  }
-
-  this->queue_size = 1000;
-
-  this->MaxNCCI = (byte) rp->level3cnt;
-  this->MaxNCCIData = (byte) rp->datablkcnt;
-  this->MaxBuffer = bnum;
-  this->MaxDataLength = rp->datablklen;
-
-  this->DataNCCI         = DataNCCI;
-  this->DataFlags        = DataFlags;
-  this->ReceiveBuffer    = ReceiveBuffer;
-  this->xbuffer_used     = xbuffer_used;
-  this->xbuffer_ptr      = xbuffer_ptr;
-  this->xbuffer_internal = xbuffer_internal;
-  for ( i = 0 ; i < xnum ; i++ ) {
-    this->xbuffer_ptr[i] = xbuffer_ptr[i];
-  }
-
-  CapiRegister(this->Id);
-	diva_os_leave_spin_lock (&api_lock, &old_irql, "register_appl");
-	
-} 
+	if (appl > MAX_APPL) {
+		DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
+		return;
+	}
+
+	if (rp->level3cnt < 1 ||
+	    rp->level3cnt > 255 ||
+	    rp->datablklen < 80 ||
+	    rp->datablklen > 2150 || rp->datablkcnt > 255) {
+		DBG_ERR(("CAPI_REGISTER - invalid parameters"))
+		return;
+	}
+
+	if (application[appl - 1].Id == appl) {
+		DBG_ERR(("CAPI_REGISTER - appl already registered"))
+		return;	/* appl already registered */
+	}
+
+	/* alloc memory */
+
+	bnum = rp->level3cnt * rp->datablkcnt;
+	xnum = rp->level3cnt * MAX_DATA_B3;
+
+	if (!(DataNCCI = diva_os_malloc(0, bnum * sizeof(word)))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		return;
+	}
+	memset(DataNCCI, 0, bnum * sizeof(word));
+
+	if (!(DataFlags = diva_os_malloc(0, bnum * sizeof(word)))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		diva_os_free(0, DataNCCI);
+		return;
+	}
+	memset(DataFlags, 0, bnum * sizeof(word));
+
+	if (!(ReceiveBuffer = diva_os_malloc(0, bnum * rp->datablklen))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		diva_os_free(0, DataNCCI);
+		diva_os_free(0, DataFlags);
+		return;
+	}
+	memset(ReceiveBuffer, 0, bnum * rp->datablklen);
+
+	if (!(xbuffer_used = (byte *) diva_os_malloc(0, xnum))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		diva_os_free(0, DataNCCI);
+		diva_os_free(0, DataFlags);
+		diva_os_free(0, ReceiveBuffer);
+		return;
+	}
+	memset(xbuffer_used, 0, xnum);
+
+	if (!(xbuffer_ptr = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		diva_os_free(0, DataNCCI);
+		diva_os_free(0, DataFlags);
+		diva_os_free(0, ReceiveBuffer);
+		diva_os_free(0, xbuffer_used);
+		return;
+	}
+	memset(xbuffer_ptr, 0, xnum * sizeof(void *));
+
+	if (!(xbuffer_internal = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) {
+		DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+		diva_os_free(0, DataNCCI);
+		diva_os_free(0, DataFlags);
+		diva_os_free(0, ReceiveBuffer);
+		diva_os_free(0, xbuffer_used);
+		diva_os_free(0, xbuffer_ptr);
+		return;
+	}
+	memset(xbuffer_internal, 0, xnum * sizeof(void *));
+
+	for (i = 0; i < xnum; i++) {
+		xbuffer_ptr[i] = diva_os_malloc(0, rp->datablklen);
+		if (!xbuffer_ptr[i]) {
+			DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
+			if (i) {
+				for (j = 0; j < i; j++)
+					if (xbuffer_ptr[j])
+						diva_os_free(0, xbuffer_ptr [j]);
+			}
+			diva_os_free(0, DataNCCI);
+			diva_os_free(0, DataFlags);
+			diva_os_free(0, ReceiveBuffer);
+			diva_os_free(0, xbuffer_used);
+			diva_os_free(0, xbuffer_ptr);
+			diva_os_free(0, xbuffer_internal);
+			return;
+		}
+	}
+
+	DBG_LOG(("CAPI_REGISTER - Id = %d", appl))
+	DBG_LOG(("  MaxLogicalConnections = %d", rp->level3cnt))
+	DBG_LOG(("  MaxBDataBuffers       = %d", rp->datablkcnt))
+	DBG_LOG(("  MaxBDataLength        = %d", rp->datablklen))
+
+	/* initialize application data */
+	diva_os_enter_spin_lock(&api_lock, &old_irql, "register_appl");
+
+	this = &application[appl - 1];
+	memset(this, 0, sizeof(APPL));
+
+	this->Id = appl;
+
+	/* We do not need a list */
+	/* InitializeListHead(&this->s_function); */
+
+	for (i = 0; i < max_adapter; i++) {
+		adapter[i].CIP_Mask[appl - 1] = 0;
+	}
+
+	this->queue_size = 1000;
+
+	this->MaxNCCI = (byte) rp->level3cnt;
+	this->MaxNCCIData = (byte) rp->datablkcnt;
+	this->MaxBuffer = bnum;
+	this->MaxDataLength = rp->datablklen;
+
+	this->DataNCCI = DataNCCI;
+	this->DataFlags = DataFlags;
+	this->ReceiveBuffer = ReceiveBuffer;
+	this->xbuffer_used = xbuffer_used;
+	this->xbuffer_ptr = xbuffer_ptr;
+	this->xbuffer_internal = xbuffer_internal;
+	for (i = 0; i < xnum; i++) {
+		this->xbuffer_ptr[i] = xbuffer_ptr[i];
+	}
+
+	CapiRegister(this->Id);
+	diva_os_leave_spin_lock(&api_lock, &old_irql, "register_appl");
+
+}
 
 /*
  *  release appl
@@ -925,200 +900,197 @@
 static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
 {
 	diva_os_spin_lock_magic_t old_irql;
-  APPL *this = &application[appl - 1] ;
-  int i = 0;
+	APPL *this = &application[appl - 1];
+	int i = 0;
+
+	if (diva_os_in_irq()) {
+		DBG_ERR(("CAPI_RELEASE - in irq context !"))
+		return;
+	}
+	if (this->Id) {
+		DBG_TRC(("application %d cleanup", this->Id))
+	}
 
-  if(diva_os_in_irq()) {
-    DBG_ERR(("CAPI_RELEASE - in irq context !"))
-    return;
-  }
-  if (this->Id) {
-    DBG_TRC(("application %d cleanup", this->Id))
-  }
-
-	diva_os_enter_spin_lock (&api_lock, &old_irql, "release_appl");
-  if (this->Id)
-  {
-    CapiRelease(this->Id);
-    if (this->DataNCCI) diva_os_free(0, this->DataNCCI);
-    if (this->DataFlags) diva_os_free(0, this->DataFlags);
-    if (this->ReceiveBuffer) diva_os_free(0, this->ReceiveBuffer);
-    if (this->xbuffer_ptr)
-    {
-      for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI); i++)
-      {
-        if (this->xbuffer_ptr[i]) diva_os_free(0, this->xbuffer_ptr[i]);
-      }
-      diva_os_free(0, this->xbuffer_ptr);
-    }
-    if (this->xbuffer_internal) diva_os_free(0, this->xbuffer_internal);
-    if (this->xbuffer_used) diva_os_free(0, this->xbuffer_used);
-    this->Id = 0;
-  }
-	diva_os_leave_spin_lock (&api_lock, &old_irql, "release_appl");
+	diva_os_enter_spin_lock(&api_lock, &old_irql, "release_appl");
+	if (this->Id) {
+		CapiRelease(this->Id);
+		if (this->DataNCCI)
+			diva_os_free(0, this->DataNCCI);
+		if (this->DataFlags)
+			diva_os_free(0, this->DataFlags);
+		if (this->ReceiveBuffer)
+			diva_os_free(0, this->ReceiveBuffer);
+		if (this->xbuffer_ptr) {
+			for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI); i++) {
+				if (this->xbuffer_ptr[i])
+					diva_os_free(0, this->xbuffer_ptr[i]);
+			}
+			diva_os_free(0, this->xbuffer_ptr);
+		}
+		if (this->xbuffer_internal)
+			diva_os_free(0, this->xbuffer_internal);
+		if (this->xbuffer_used)
+			diva_os_free(0, this->xbuffer_used);
+		this->Id = 0;
+	}
+	diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl");
 
-  DIVA_UNLOCK_MODULE;
-} 
+	DIVA_UNLOCK_MODULE;
+}
 
 /*
  *  send message
  */
-static u16 diva_send_message(struct capi_ctr *ctrl, diva_os_message_buffer_s *dmb)
+static u16 diva_send_message(struct capi_ctr *ctrl,
+			     diva_os_message_buffer_s * dmb)
 {
-  int i = 0, j = 0;
-  word ret = 0;
+	int i = 0, j = 0;
+	word ret = 0;
 	diva_os_spin_lock_magic_t old_irql;
-  CAPI_MSG *msg = (CAPI_MSG *)DIVA_MESSAGE_BUFFER_DATA(dmb);
-  APPL *this = &application[READ_WORD(&msg->header.appl_id) - 1];
-  diva_card *card = ctrl->driverdata;
-  __u32 length = DIVA_MESSAGE_BUFFER_LEN(dmb);
+	CAPI_MSG *msg = (CAPI_MSG *) DIVA_MESSAGE_BUFFER_DATA(dmb);
+	APPL *this = &application[READ_WORD(&msg->header.appl_id) - 1];
+	diva_card *card = ctrl->driverdata;
+	__u32 length = DIVA_MESSAGE_BUFFER_LEN(dmb);
 	word clength = READ_WORD(&msg->header.length);
 	word command = READ_WORD(&msg->header.command);
+	u16 retval = CAPI_NOERROR;
 
-  if(diva_os_in_irq()) {
-    DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
+	if (diva_os_in_irq()) {
+		DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
 		return CAPI_REGOSRESOURCEERR;
-  }
-  DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
+	}
+	DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
+
+	/* patch controller number */
+	msg->header.controller = ControllerMap[card->Id]
+	    | (msg->header.controller & 0x80);	/* preserve external controller bit */
+
+	diva_os_enter_spin_lock(&api_lock, &old_irql, "send message");
+
+	switch (command) {
+	default:
+		xlog("\x00\x02", msg, 0x80, clength);
+		break;
+
+	case _DATA_B3_I | RESPONSE:
+		if (myDriverDebugHandle.dbgMask & DL_BLK)
+			xlog("\x00\x02", msg, 0x80, clength);
+		break;
+
+	case _DATA_B3_R:
+		if (myDriverDebugHandle.dbgMask & DL_BLK)
+			xlog("\x00\x02", msg, 0x80, clength);
+
+		if (clength == 24)
+			clength = 22;	/* workaround for PPcom bug */
+		/* header is always 22      */
+		if (READ_WORD(&msg->info.data_b3_req.Data_Length) >
+		    this->MaxDataLength
+		    || READ_WORD(&msg->info.data_b3_req.Data_Length) >
+		    (length - clength)) {
+			DBG_ERR(("Write - invalid message size"))
+			retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
+			goto write_end;
+		}
 
-  /* patch controller number */
-  msg->header.controller = ControllerMap[card->Id]
-												| (msg->header.controller &0x80);  /* preserve external controller bit */
-
-	diva_os_enter_spin_lock (&api_lock, &old_irql, "send message");
-
-  switch ( command )
-  {
-    default:
-      xlog ("\x00\x02", msg, 0x80, clength) ;
-      break;
-
-    case _DATA_B3_I|RESPONSE:
-      if ( myDriverDebugHandle.dbgMask & DL_BLK )
-        xlog ("\x00\x02", msg, 0x80, clength) ;
-      break;
-
-    case _DATA_B3_R:
-      if ( myDriverDebugHandle.dbgMask & DL_BLK )
-        xlog ("\x00\x02", msg, 0x80, clength) ;
-
-      if (clength == 24) clength = 22; /* workaround for PPcom bug */
-                                      /* header is always 22      */
-      if (READ_WORD(&msg->info.data_b3_req.Data_Length) > this->MaxDataLength ||
-          READ_WORD(&msg->info.data_b3_req.Data_Length) > (length - clength))
-      {
-        DBG_ERR(("Write - invalid message size"))
-        goto write_end;
-      }
-
-      for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI) && this->xbuffer_used[i]; i++);
-      if (i == (MAX_DATA_B3 * this->MaxNCCI))
-      {
-        DBG_ERR(("Write - too many data pending"))
-        goto write_end;
-      }
-      msg->info.data_b3_req.Data = i;
-
-      this->xbuffer_internal[i] = NULL;
-      memcpy (this->xbuffer_ptr[i],
-					&((__u8 *)msg)[clength],
-					READ_WORD(&msg->info.data_b3_req.Data_Length));
-
-      if ( (myDriverDebugHandle.dbgMask & DL_BLK)
-        && (myDriverDebugHandle.dbgMask & DL_XLOG))
-      {
-        for ( j = 0 ; j < READ_WORD(&msg->info.data_b3_req.Data_Length) ; j += 256 )
-        {
-          DBG_BLK((((char *)this->xbuffer_ptr[i]) + j,
-            ((READ_WORD(&msg->info.data_b3_req.Data_Length) - j) < 256) ?
-             (READ_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256  ))
-          if ( !(myDriverDebugHandle.dbgMask & DL_PRV0) )
-            break ; // not more if not explicitely requested
-        }
-      }
-      break ;
-  }
-
-  memcpy (mapped_msg, msg, (__u32)clength);
-  mapped_msg->header.controller = MapController (mapped_msg->header.controller);
-  mapped_msg->header.length = clength;
-  mapped_msg->header.command = command;
+		for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI)
+		     && this->xbuffer_used[i]; i++);
+		if (i == (MAX_DATA_B3 * this->MaxNCCI)) {
+			DBG_ERR(("Write - too many data pending"))
+			retval = CAPI_SENDQUEUEFULL;
+			goto write_end;
+		}
+		msg->info.data_b3_req.Data = i;
+
+		this->xbuffer_internal[i] = NULL;
+		memcpy(this->xbuffer_ptr[i], &((__u8 *) msg)[clength],
+		       READ_WORD(&msg->info.data_b3_req.Data_Length));
+
+		if ((myDriverDebugHandle.dbgMask & DL_BLK)
+		    && (myDriverDebugHandle.dbgMask & DL_XLOG)) {
+			for (j = 0; j <
+			     READ_WORD(&msg->info.data_b3_req.Data_Length);
+			     j += 256) {
+				DBG_BLK((((char *) this->xbuffer_ptr[i]) + j,
+					((READ_WORD(&msg->info.data_b3_req.Data_Length) - j) <
+					  256) ? (READ_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256))
+				if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
+					break;	/* not more if not explicitely requested */
+			}
+		}
+		break;
+	}
+
+	memcpy(mapped_msg, msg, (__u32) clength);
+	mapped_msg->header.controller = MapController(mapped_msg->header.controller);
+	mapped_msg->header.length = clength;
+	mapped_msg->header.command = command;
 	mapped_msg->header.number = READ_WORD(&msg->header.number);
 
-  ret = api_put (this, mapped_msg);
-  switch (ret)
-  {
-    case 0:
-      break;
-    case _BAD_MSG:
-      DBG_ERR(("Write - bad message"))
-      break;
-    case _QUEUE_FULL:
-      DBG_ERR(("Write - queue full"))
-      break;
-    default:
-      DBG_ERR(("Write - api_put returned unknown error"))
-      break;
-  }
-
-write_end:
-	diva_os_leave_spin_lock (&api_lock, &old_irql, "send message");
-  diva_os_free_message_buffer(dmb);
-	return CAPI_NOERROR;
+	ret = api_put(this, mapped_msg);
+	switch (ret) {
+	case 0:
+		break;
+	case _BAD_MSG:
+		DBG_ERR(("Write - bad message"))
+		retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
+		break;
+	case _QUEUE_FULL:
+		DBG_ERR(("Write - queue full"))
+		retval = CAPI_SENDQUEUEFULL;
+		break;
+	default:
+		DBG_ERR(("Write - api_put returned unknown error"))
+		retval = CAPI_UNKNOWNNOTPAR;
+		break;
+	}
+
+      write_end:
+	diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
+	diva_os_free_message_buffer(dmb);
+	return retval;
 }
 
 
 /*
  * cards request function
  */
-static void DIRequest (ENTITY* e)
+static void DIRequest(ENTITY * e)
 {
-  DIVA_CAPI_ADAPTER *a = &(adapter[(byte)e->user[0]]);
-  diva_card* os_card = (diva_card*)a->os_card;
+	DIVA_CAPI_ADAPTER *a = &(adapter[(byte) e->user[0]]);
+	diva_card *os_card = (diva_card *) a->os_card;
 
-  if (e->Req && (a->FlowControlIdTable[e->ReqCh] == e->Id)) {
-    a->FlowControlSkipTable[e->ReqCh] = 1;
-  }
+	if (e->Req && (a->FlowControlIdTable[e->ReqCh] == e->Id)) {
+		a->FlowControlSkipTable[e->ReqCh] = 1;
+	}
 
-  (*(os_card->d.request))(e);
+	(*(os_card->d.request)) (e);
 }
 
 /*
  * callback function from didd
  */
-static void didd_callback(void *context, DESCRIPTOR* adapter, int removal)
+static void didd_callback(void *context, DESCRIPTOR * adapter, int removal)
 {
-  if (adapter->type == IDI_DADAPTER)
-  {
-    DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
-    return;
-  }
-  else if (adapter->type == IDI_DIMAINT)
-  {
-    if (removal)
-    {
-				stop_dbg();
-    }
-    else
-    {
-      memcpy(&MAdapter, adapter, sizeof(MAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT);
-    }
-  }
-  else if ((adapter->type > 0) &&
-           (adapter->type < 16))
-  {  /* IDI Adapter */
-    if (removal)
-    {
-      divacapi_remove_card(adapter);
-    }
-    else
-    {
-      diva_add_card(adapter);
-    }
-  }
-  return;
+	if (adapter->type == IDI_DADAPTER) {
+		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
+		return;
+	} else if (adapter->type == IDI_DIMAINT) {
+		if (removal) {
+			stop_dbg();
+		} else {
+			memcpy(&MAdapter, adapter, sizeof(MAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT);
+		}
+	} else if ((adapter->type > 0) && (adapter->type < 16)) {	/* IDI Adapter */
+		if (removal) {
+			divacapi_remove_card(adapter);
+		} else {
+			diva_add_card(adapter);
+		}
+	}
+	return;
 }
 
 /*
@@ -1126,54 +1098,47 @@
  */
 static int divacapi_connect_didd(void)
 {
-  int x = 0;
-  int dadapter = 0;
-  IDI_SYNC_REQ req;
-  DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
-
-  DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
-
-	for (x = 0; x < MAX_DESCRIPTORS; x++)
-	{
-			if (DIDD_Table[x].type == IDI_DIMAINT)
-			{	/* MAINT found */
-					memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
-					dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-					DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT);
-					break;
-			}
+	int x = 0;
+	int dadapter = 0;
+	IDI_SYNC_REQ req;
+	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
+	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
+			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT);
+			break;
+		}
 	}
-  for (x = 0; x < MAX_DESCRIPTORS; x++)
-  {
-    if (DIDD_Table[x].type == IDI_DADAPTER)
-    {  /* DADAPTER found */
-      dadapter = 1;
-      memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      req.didd_notify.e.Req = 0;
-      req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
-      req.didd_notify.info.callback = didd_callback;
-      req.didd_notify.info.context = 0;
-      DAdapter.request((ENTITY *)&req);
-      if (req.didd_notify.e.Rc != 0xff)
-			{
-					stop_dbg();
-					return(0);
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
+			dadapter = 1;
+			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			req.didd_notify.e.Req = 0;
+			req.didd_notify.e.Rc =
+			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
+			req.didd_notify.info.callback = didd_callback;
+			req.didd_notify.info.context = 0;
+			DAdapter.request((ENTITY *) & req);
+			if (req.didd_notify.e.Rc != 0xff) {
+				stop_dbg();
+				return (0);
 			}
 			notify_handle = req.didd_notify.info.handle;
-    }
-    else if ((DIDD_Table[x].type > 0) &&
-             (DIDD_Table[x].type < 16))
-    {  /* IDI Adapter found */
-      diva_add_card(&DIDD_Table[x]);
-    }
-  }
+		}
+			else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) {	/* IDI Adapter found */
+			diva_add_card(&DIDD_Table[x]);
+		}
+	}
 
-	if (!dadapter)
-	{
-			stop_dbg();
+	if (!dadapter) {
+		stop_dbg();
 	}
 
-  return(dadapter);
+	return (dadapter);
 }
 
 /*
@@ -1181,23 +1146,23 @@
  */
 static void divacapi_disconnect_didd(void)
 {
-  IDI_SYNC_REQ req;
+	IDI_SYNC_REQ req;
 
 	stop_dbg();
 
-  req.didd_notify.e.Req = 0;
-  req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
-  req.didd_notify.info.handle = notify_handle;
-  DAdapter.request((ENTITY *)&req);
+	req.didd_notify.e.Req = 0;
+	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
+	req.didd_notify.info.handle = notify_handle;
+	DAdapter.request((ENTITY *) & req);
 }
 
 /*
  * we do not provide date/time here,
  * the application should do this. 
  */
-int fax_head_line_time (char *buffer)
+int fax_head_line_time(char *buffer)
 {
-  return (0);
+	return (0);
 }
 
 /*
@@ -1205,27 +1170,27 @@
  */
 static int DIVA_INIT_FUNCTION init_main_structs(void)
 {
-  if(!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
-    DBG_ERR(("init: failed alloc mapped_msg."))
-    return 0;
-  }
-
-  if (!(adapter = diva_os_malloc(0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS))) {
-    DBG_ERR(("init: failed alloc adapter struct."))
-    diva_os_free(0, mapped_msg);
-    return 0;
-  }
-  memset(adapter, 0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS);
-
-  if (!(application = diva_os_malloc(0, sizeof(APPL) * MAX_APPL))) {
-    DBG_ERR(("init: failed alloc application struct."))
-    diva_os_free(0, mapped_msg);
-    diva_os_free(0, adapter);
-    return 0;
-  }
-  memset(application, 0, sizeof(APPL) * MAX_APPL);
+	if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
+		DBG_ERR(("init: failed alloc mapped_msg."))
+		    return 0;
+	}
 
-  return(1);
+	if (!(adapter = diva_os_malloc(0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS))) {
+		DBG_ERR(("init: failed alloc adapter struct."))
+		diva_os_free(0, mapped_msg);
+		return 0;
+	}
+	memset(adapter, 0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS);
+
+	if (!(application = diva_os_malloc(0, sizeof(APPL) * MAX_APPL))) {
+		DBG_ERR(("init: failed alloc application struct."))
+		diva_os_free(0, mapped_msg);
+		diva_os_free(0, adapter);
+		return 0;
+	}
+	memset(application, 0, sizeof(APPL) * MAX_APPL);
+
+	return (1);
 }
 
 /*
@@ -1233,12 +1198,12 @@
  */
 static void remove_main_structs(void)
 {
-		if (application)
-			diva_os_free(0, application);
-		if (adapter)
-			diva_os_free(0, adapter);
-		if (mapped_msg)
-			diva_os_free(0, mapped_msg);
+	if (application)
+		diva_os_free(0, application);
+	if (adapter)
+		diva_os_free(0, adapter);
+	if (mapped_msg)
+		diva_os_free(0, mapped_msg);
 }
 
 /*
@@ -1246,24 +1211,24 @@
  */
 int DIVA_INIT_FUNCTION init_capifunc(void)
 {
-		diva_os_initialize_spin_lock (&ll_lock, "capifunc");
-		diva_os_initialize_spin_lock (&api_lock, "capifunc");
-		memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
-		max_adapter = 0;
+	diva_os_initialize_spin_lock(&ll_lock, "capifunc");
+	diva_os_initialize_spin_lock(&api_lock, "capifunc");
+	memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
+	max_adapter = 0;
 
 
-		if(!init_main_structs()) {
-			DBG_ERR(("init: failed to init main structs."))
-			return(0);
-		}
+	if (!init_main_structs()) {
+		DBG_ERR(("init: failed to init main structs."))
+		return (0);
+	}
 
-		if(!divacapi_connect_didd()) {
-			DBG_ERR(("init: failed to connect to DIDD."))
-			remove_main_structs();
-			return(0);
-		}
+	if (!divacapi_connect_didd()) {
+		DBG_ERR(("init: failed to connect to DIDD."))
+		remove_main_structs();
+		return (0);
+	}
 
-		return(1);
+	return (1);
 }
 
 /*
@@ -1271,20 +1236,18 @@
  */
 void DIVA_EXIT_FUNCTION finit_capifunc(void)
 {
-		int count = 100;
-		word ret = 1;
+	int count = 100;
+	word ret = 1;
 
-		while(ret && count--)
-		{
-    		ret = api_remove_start();
-				diva_os_sleep(10);
-		}
-		if (ret)
-				DBG_ERR(("could not remove signaling ID's"))
-		
-	  divacapi_disconnect_didd();
-	  divacapi_remove_cards();
+	while (ret && count--) {
+		ret = api_remove_start();
+		diva_os_sleep(10);
+	}
+	if (ret)
+		DBG_ERR(("could not remove signaling ID's"))
 
-		remove_main_structs();
-}
+		    divacapi_disconnect_didd();
+	divacapi_remove_cards();
 
+	remove_main_structs();
+}
diff -Nru a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h
--- a/drivers/isdn/hardware/eicon/capifunc.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/capifunc.h	Sun Nov 17 20:30:15 2002
@@ -10,7 +10,7 @@
  * of the GNU General Public License, incorporated herein by reference.
  */
 
-#ifndef __CAPIFUNC_H__ 
+#ifndef __CAPIFUNC_H__
 #define __CAPIFUNC_H__
 
 #define MAX_DESCRIPTORS  32
diff -Nru a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c
--- a/drivers/isdn/hardware/eicon/capimain.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/hardware/eicon/capimain.c	Sun Nov 17 20:30:12 2002
@@ -31,20 +31,20 @@
 
 EXPORT_NO_SYMBOLS;
 
-static char *main_revision = "$Revision: 1.1.2.2 $";
-static char *DRIVERNAME = "Eicon DIVA - CAPI Interface driver (http://www.melware.net)";
+static char *main_revision = "$Revision: 1.1.2.11 $";
+static char *DRIVERNAME =
+    "Eicon DIVA - CAPI Interface driver (http://www.melware.net)";
 static char *DRIVERLNAME = "divacapi";
 
-MODULE_DESCRIPTION(             "CAPI driver for Eicon DIVA cards");
-MODULE_AUTHOR(                  "Cytronics & Melware, Eicon Networks");
-MODULE_SUPPORTED_DEVICE(        "CAPI and DIVA card drivers");
+MODULE_DESCRIPTION("CAPI driver for Eicon DIVA cards");
+MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
+MODULE_SUPPORTED_DEVICE("CAPI and DIVA card drivers");
 MODULE_LICENSE("GPL");
 
 /*
  * get revision number from revision string
  */
-static char *
-getrev(const char *revision)
+static char *getrev(const char *revision)
 {
 	char *rev;
 	char *p;
@@ -52,7 +52,8 @@
 		rev = p + 2;
 		p = strchr(rev, '$');
 		*--p = 0;
-	} else rev = "1.0";
+	} else
+		rev = "1.0";
 	return rev;
 
 }
@@ -60,86 +61,85 @@
 /*
  * sleep for some milliseconds
  */
-void
-diva_os_sleep (dword mSec)
+void diva_os_sleep(dword mSec)
 {
 	unsigned long timeout = HZ * mSec / 1000 + 1;
-			 
+
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(timeout);
 }
 
 /*
  * wait for some milliseconds
- */ 
-void
-diva_os_wait (dword mSec)
+ */
+void diva_os_wait(dword mSec)
 {
-	mdelay (mSec);
-} 
+	mdelay(mSec);
+}
 
 /*
  * alloc memory
  */
-void* diva_os_malloc (unsigned long flags, unsigned long size)
+void *diva_os_malloc(unsigned long flags, unsigned long size)
 {
-		void* ret = NULL;
-		if (size) {
-				ret = (void *)vmalloc((unsigned int)size);
-		}
-		return(ret);
+	void *ret = NULL;
+	if (size) {
+		ret = (void *) vmalloc((unsigned int) size);
+	}
+	return (ret);
 }
 
 /*
  * free memory
  */
-void diva_os_free(unsigned long unused, void* ptr)
+void diva_os_free(unsigned long unused, void *ptr)
 {
-		if (ptr) {
-				vfree(ptr);
-		}
+	if (ptr) {
+		vfree(ptr);
+	}
 }
 
 /*
  * alloc a message buffer
  */
-diva_os_message_buffer_s *
-diva_os_alloc_message_buffer(unsigned long size, void **data_buf)
+diva_os_message_buffer_s *diva_os_alloc_message_buffer(unsigned long size,
+						       void **data_buf)
 {
-		diva_os_message_buffer_s *dmb = alloc_skb(size, GFP_ATOMIC);
-		if (dmb) {
-				*data_buf = skb_put(dmb, size);
-		}
-		return(dmb);
+	diva_os_message_buffer_s *dmb = alloc_skb(size, GFP_ATOMIC);
+	if (dmb) {
+		*data_buf = skb_put(dmb, size);
+	}
+	return (dmb);
 }
 
 /*
  * free a message buffer
  */
-void diva_os_free_message_buffer(diva_os_message_buffer_s *dmb)
+void diva_os_free_message_buffer(diva_os_message_buffer_s * dmb)
 {
-		kfree_skb(dmb);
-} 
+	kfree_skb(dmb);
+}
 
 /*
  * proc function for controller info
  */
-static int diva_ctl_read_proc(char *page, char **start, off_t off,int count, int *eof, struct capi_ctr *ctrl)
+static int diva_ctl_read_proc(char *page, char **start, off_t off,
+			      int count, int *eof, struct capi_ctr *ctrl)
 {
-  diva_card *card = (diva_card *)ctrl->driverdata;
-  int len = 0;
+	diva_card *card = (diva_card *) ctrl->driverdata;
+	int len = 0;
 
-  len += sprintf(page+len, "%s\n", ctrl->name);
-  len += sprintf(page+len, "Serial No. : %s\n", ctrl->serial);
-  len += sprintf(page+len, "Id         : %d\n", card->Id);
-  len += sprintf(page+len, "Channels   : %d\n", card->d.channels);
-
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	len += sprintf(page + len, "%s\n", ctrl->name);
+	len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial);
+	len += sprintf(page + len, "Id         : %d\n", card->Id);
+	len += sprintf(page + len, "Channels   : %d\n", card->d.channels);
+
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
 /*
@@ -147,52 +147,50 @@
  */
 void diva_os_set_controller_struct(struct capi_ctr *ctrl)
 {
-		ctrl->driver_name    = DRIVERLNAME;
-		ctrl->load_firmware  = 0;
-		ctrl->reset_ctr      = 0;
-		ctrl->ctr_read_proc  = diva_ctl_read_proc;
-		SET_MODULE_OWNER(ctrl);
+	ctrl->driver_name = DRIVERLNAME;
+	ctrl->load_firmware = 0;
+	ctrl->reset_ctr = 0;
+	ctrl->ctr_read_proc = diva_ctl_read_proc;
+	SET_MODULE_OWNER(ctrl);
 }
 
 /*
  * module init
  */
-static int DIVA_INIT_FUNCTION
-divacapi_init(void)
+static int DIVA_INIT_FUNCTION divacapi_init(void)
 {
-  char tmprev[32];
-  int ret = 0;      
+	char tmprev[32];
+	int ret = 0;
 
-  MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 
-  sprintf(DRIVERRELEASE, "%d.%d%s", DRRELMAJOR, DRRELMINOR, DRRELEXTRA);
-
-  printk(KERN_INFO "%s\n", DRIVERNAME);
-  printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  printk("%s  Build: %s(%s)\n", getrev(tmprev),
-        diva_capi_common_code_build, DIVA_BUILD);
-
-	if (!(init_capifunc()))
-	{
-    printk(KERN_ERR "%s: failed init capi_driver.\n", DRIVERLNAME);
-    ret = -EIO;
+	sprintf(DRIVERRELEASE, "%d.%d%s", DRRELMAJOR, DRRELMINOR,
+		DRRELEXTRA);
+
+	printk(KERN_INFO "%s\n", DRIVERNAME);
+	printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	printk("%s  Build: %s(%s)\n", getrev(tmprev),
+	       diva_capi_common_code_build, DIVA_BUILD);
+
+	if (!(init_capifunc())) {
+		printk(KERN_ERR "%s: failed init capi_driver.\n",
+		       DRIVERLNAME);
+		ret = -EIO;
 	}
 
-  MOD_DEC_USE_COUNT;
-  return ret;
+	MOD_DEC_USE_COUNT;
+	return ret;
 }
 
 /*
  * module exit
  */
-static void DIVA_EXIT_FUNCTION
-divacapi_exit(void)
+static void DIVA_EXIT_FUNCTION divacapi_exit(void)
 {
-  finit_capifunc();
-  printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
+	finit_capifunc();
+	printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 }
 
 module_init(divacapi_init);
 module_exit(divacapi_exit);
-
diff -Nru a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
--- a/drivers/isdn/hardware/eicon/diddfunc.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/isdn/hardware/eicon/diddfunc.c	Sun Nov 17 20:30:16 2002
@@ -22,7 +22,7 @@
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
 
-extern void DIVA_DIDD_Read (void *, int);
+extern void DIVA_DIDD_Read(void *, int);
 extern char *DRIVERRELEASE;
 static dword notify_handle;
 static DESCRIPTOR _DAdapter;
@@ -30,73 +30,65 @@
 /*
  * didd callback function
  */
-static void *
-didd_callback(void *context, DESCRIPTOR* adapter, int removal)
+static void *didd_callback(void *context, DESCRIPTOR * adapter,
+			   int removal)
 {
-  if (adapter->type == IDI_DADAPTER)
-  {
-    DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."))
-    return(NULL);
-  }
-  else if (adapter->type == IDI_DIMAINT)
-  {
-    if (removal) {
-				DbgDeregister();
+	if (adapter->type == IDI_DADAPTER) {
+		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."))
+		return (NULL);
+	} else if (adapter->type == IDI_DIMAINT) {
+		if (removal) {
+			DbgDeregister();
 		} else {
-				DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT);
+			DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT);
 		}
-  }
-  return(NULL);
+	}
+	return (NULL);
 }
 
 /*
  * connect to didd
  */
-static int DIVA_INIT_FUNCTION
-connect_didd(void)
+static int DIVA_INIT_FUNCTION connect_didd(void)
 {
-  int x = 0;
-  int dadapter = 0;
-  IDI_SYNC_REQ req;
-  DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
-
-  DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
-
-  for (x = 0; x < MAX_DESCRIPTORS; x++)
-  {
-    if (DIDD_Table[x].type == IDI_DADAPTER)
-    {  /* DADAPTER found */
-      dadapter = 1;
-      memcpy(&_DAdapter, &DIDD_Table[x], sizeof(_DAdapter));
-      req.didd_notify.e.Req = 0;
-      req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
-      req.didd_notify.info.callback = didd_callback;
-      req.didd_notify.info.context = 0;
-      _DAdapter.request((ENTITY *)&req);
-      if (req.didd_notify.e.Rc != 0xff)
-        return(0);
-      notify_handle = req.didd_notify.info.handle;
-    }
-    else if (DIDD_Table[x].type == IDI_DIMAINT)
-    {  /* MAINT found */
-      DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT);
-    }
-  }
-  return(dadapter);
+	int x = 0;
+	int dadapter = 0;
+	IDI_SYNC_REQ req;
+	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
+	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
+			dadapter = 1;
+			memcpy(&_DAdapter, &DIDD_Table[x], sizeof(_DAdapter));
+			req.didd_notify.e.Req = 0;
+			req.didd_notify.e.Rc =
+			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
+			req.didd_notify.info.callback = didd_callback;
+			req.didd_notify.info.context = 0;
+			_DAdapter.request((ENTITY *) & req);
+			if (req.didd_notify.e.Rc != 0xff)
+				return (0);
+			notify_handle = req.didd_notify.info.handle;
+		} else if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
+			DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT);
+		}
+	}
+	return (dadapter);
 }
 
 /*
  * disconnect from didd
  */
-static void DIVA_EXIT_FUNCTION
-disconnect_didd(void)
+static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 {
-  IDI_SYNC_REQ req;
+	IDI_SYNC_REQ req;
 
-  req.didd_notify.e.Req = 0;
-  req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
-  req.didd_notify.info.handle = notify_handle;
-  _DAdapter.request((ENTITY *)&req);
+	req.didd_notify.e.Req = 0;
+	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
+	req.didd_notify.info.handle = notify_handle;
+	_DAdapter.request((ENTITY *) & req);
 }
 
 /*
@@ -104,14 +96,14 @@
  */
 int DIVA_INIT_FUNCTION diddfunc_init(void)
 {
-  diva_didd_load_time_init();
+	diva_didd_load_time_init();
 
-  if(!connect_didd()) {
-    DBG_ERR(("init: failed to connect to DIDD."))
-    diva_didd_load_time_finit();
-    return(0);
-  }
-  return(1);
+	if (!connect_didd()) {
+		DBG_ERR(("init: failed to connect to DIDD."))
+		diva_didd_load_time_finit();
+		return (0);
+	}
+	return (1);
 }
 
 /*
@@ -119,8 +111,7 @@
  */
 void DIVA_EXIT_FUNCTION diddfunc_finit(void)
 {
-  DbgDeregister();
-  disconnect_didd();
-  diva_didd_load_time_finit();
+	DbgDeregister();
+	disconnect_didd();
+	diva_didd_load_time_finit();
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
--- a/drivers/isdn/hardware/eicon/diva.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/diva.c	Sun Nov 17 20:30:15 2002
@@ -1,4 +1,4 @@
-/* $Id: diva.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: diva.c,v 1.1.2.5 2001/02/14 21:10:19 armin Exp $ */
 
 #define CARDTYPE_H_WANT_DATA            1
 #define CARDTYPE_H_WANT_IDI_DATA        0
@@ -21,19 +21,19 @@
 #include "diva.h"
 
 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
-  #include "os_pri.h"
+#include "os_pri.h"
 #endif
 #ifdef CONFIG_ISDN_DIVAS_4BRIPCI
-  #include "os_4bri.h"
+#include "os_4bri.h"
 #endif
 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
-  #include "os_bri.h"
+#include "os_bri.h"
 #endif
 
 PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
 extern IDI_CALL Requests[MAX_ADAPTER];
-extern int create_adapter_proc (diva_os_xdi_adapter_t* a);
-extern void remove_adapter_proc (diva_os_xdi_adapter_t* a);
+extern int create_adapter_proc(diva_os_xdi_adapter_t * a);
+extern void remove_adapter_proc(diva_os_xdi_adapter_t * a);
 
 #define DivaIdiReqFunc(N) \
 static void DivaIdiRequest##N(ENTITY *e) \
@@ -83,551 +83,571 @@
 diva_entity_queue_t adapter_queue;
 
 typedef struct _diva_get_xlog {
-  word command;
-  byte req;
-  byte rc;
-  byte data [sizeof(struct mi_pc_maint)];
+	word command;
+	byte req;
+	byte rc;
+	byte data[sizeof(struct mi_pc_maint)];
 } diva_get_xlog_t;
 
 typedef struct _diva_supported_cards_info {
-  int CardOrdinal;
-  diva_init_card_proc_t init_card;
+	int CardOrdinal;
+	diva_init_card_proc_t init_card;
 } diva_supported_cards_info_t;
 
-static diva_supported_cards_info_t divas_supported_cards [] = {
+static diva_supported_cards_info_t divas_supported_cards[] = {
 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
-  /*
-    PRI Cards
-  */
-  { CARDTYPE_DIVASRV_P_30M_PCI,	 diva_pri_init_card },
-  /*
-    PRI Rev.2 Cards
-  */
-  { CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card },
-  /*
-    PRI Rev.2 VoIP Cards
-  */
-  { CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card },
+	/*
+	   PRI Cards
+	 */
+	{CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card},
+	/*
+	   PRI Rev.2 Cards
+	 */
+	{CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card},
+	/*
+	   PRI Rev.2 VoIP Cards
+	 */
+	{CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card},
 #endif
 #ifdef CONFIG_ISDN_DIVAS_4BRIPCI
-  /*
-    4BRI Rev 1 Cards
-  */
-  { CARDTYPE_DIVASRV_Q_8M_PCI,	 diva_4bri_init_card },
-  { CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card },
-  /*
-    4BRI Rev 2 Cards
-  */
-  { CARDTYPE_DIVASRV_Q_8M_V2_PCI,    diva_4bri_init_card },
-  { CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card },
-  /*
-    4BRI Based BRI Rev 2 Cards
-  */
-  { CARDTYPE_DIVASRV_B_2M_V2_PCI,    diva_4bri_init_card },
-  { CARDTYPE_DIVASRV_B_2F_PCI,       diva_4bri_init_card },
-  { CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card },
+	/*
+	   4BRI Rev 1 Cards
+	 */
+	{CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card},
+	{CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card},
+	/*
+	   4BRI Rev 2 Cards
+	 */
+	{CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card},
+	{CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card},
+	/*
+	   4BRI Based BRI Rev 2 Cards
+	 */
+	{CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card},
+	{CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card},
+	{CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card},
 #endif
 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
-  /*
-    BRI
-  */
-  { CARDTYPE_MAESTRA_PCI,		diva_bri_init_card },
+	/*
+	   BRI
+	 */
+	{CARDTYPE_MAESTRA_PCI, diva_bri_init_card},
 #endif
 
-  /*
-    EOL
-  */
-  { -1, 0 }
+	/*
+	   EOL
+	 */
+	{-1, 0}
 };
 
-static void diva_init_request_array (void);
-static void* divas_create_pci_card (int handle, void* pci_dev_handle);
+static void diva_init_request_array(void);
+static void *divas_create_pci_card(int handle, void *pci_dev_handle);
 
 static diva_os_spin_lock_t adapter_lock;
 
-static int diva_find_free_adapters (int base, int nr) {
-  int i;
+static int diva_find_free_adapters(int base, int nr)
+{
+	int i;
 
-  for (i = 0; i < nr; i++) {
-    if (IoAdapters[base+i]) {
-      return (-1);
-    }
-  }
+	for (i = 0; i < nr; i++) {
+		if (IoAdapters[base + i]) {
+			return (-1);
+		}
+	}
 
-  return (0);
+	return (0);
 }
 
 /* --------------------------------------------------------------------------
     Add card to the card list
    -------------------------------------------------------------------------- */
-void* diva_driver_add_card (void* pdev, unsigned long CardOrdinal) {
-  diva_os_spin_lock_magic_t old_irql;
-  diva_os_xdi_adapter_t* pdiva, *pa;
-  int i, j, max, nr;
-
-  for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
-    if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
-      if (!(pdiva = divas_create_pci_card (i, pdev))) {
-        return (0);
-      }
-      switch (CardOrdinal) {
-        case CARDTYPE_DIVASRV_Q_8M_PCI:
-        case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
-        case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
-        case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
-          max = MAX_ADAPTER - 4;
-          nr = 4;
-          break;
-
-        default:
-          max = MAX_ADAPTER;
-          nr  = 1;
-      }
-
-      diva_os_enter_spin_lock (&adapter_lock, &old_irql, "add card");
-
-      for (i = 0; i < max; i++) {
-        if (!diva_find_free_adapters (i, nr)) {
-          pdiva->controller        = i+1;
-          pdiva->xdi_adapter.ANum  = pdiva->controller;
-          IoAdapters[i]            = &pdiva->xdi_adapter;
-          create_adapter_proc (pdiva); /* add adapter to proc file system */
-
-          DBG_LOG(("add %s:%d",
-                  CardProperties[CardOrdinal].Name,
-                  pdiva->controller))
-
-          pa = pdiva;
-          for (j = 1; j < nr; j++) { /* slave adapters, if any */
-            pa = (diva_os_xdi_adapter_t*)diva_q_get_next (&pa->link);
-            if (pa && !pa->interface.cleanup_adapter_proc) {
-              pa->controller       = i+1+j;
-              pa->xdi_adapter.ANum = pa->controller;
-              IoAdapters[i+j]      = &pa->xdi_adapter;
-              DBG_LOG(("add slave adapter (%d)", pa->controller))
-              create_adapter_proc (pa); /* add adapter to proc file system */
-            } else {
-              DBG_ERR(("slave adapter problem"))
-              break;
-            }
-          }
-          
-          diva_os_leave_spin_lock (&adapter_lock, &old_irql, "add card");
-
-          return (pdiva);
-        }
-      }
-
-      diva_os_leave_spin_lock (&adapter_lock, &old_irql, "add card");
-
-      /*
-         Not able to add adapter - remove it and return error
-         */
-      DBG_ERR(("can not alloc request array"))
-      diva_driver_remove_card (pdiva);
-
-      return (0);
-    }
-  }
+void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal)
+{
+	diva_os_spin_lock_magic_t old_irql;
+	diva_os_xdi_adapter_t *pdiva, *pa;
+	int i, j, max, nr;
+
+	for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
+		if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
+			if (!(pdiva = divas_create_pci_card(i, pdev))) {
+				return (0);
+			}
+			switch (CardOrdinal) {
+			case CARDTYPE_DIVASRV_Q_8M_PCI:
+			case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
+			case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
+			case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
+				max = MAX_ADAPTER - 4;
+				nr = 4;
+				break;
+
+			default:
+				max = MAX_ADAPTER;
+				nr = 1;
+			}
+
+			diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
+
+			for (i = 0; i < max; i++) {
+				if (!diva_find_free_adapters(i, nr)) {
+					pdiva->controller = i + 1;
+					pdiva->xdi_adapter.ANum = pdiva->controller;
+					IoAdapters[i] = &pdiva->xdi_adapter;
+					create_adapter_proc(pdiva);	/* add adapter to proc file system */
+
+					DBG_LOG(("add %s:%d",
+						 CardProperties
+						 [CardOrdinal].Name,
+						 pdiva->controller))
+
+					pa = pdiva;
+					for (j = 1; j < nr; j++) {	/* slave adapters, if any */
+						pa = (diva_os_xdi_adapter_t *) diva_q_get_next(&pa->link);
+						if (pa && !pa->interface.cleanup_adapter_proc) {
+							pa->controller = i + 1 + j;
+							pa->xdi_adapter.ANum = pa->controller;
+							IoAdapters[i + j] = &pa->xdi_adapter;
+							DBG_LOG(("add slave adapter (%d)",
+								 pa->controller)) create_adapter_proc(pa);	/* add adapter to proc file system */
+						} else {
+							DBG_ERR(("slave adapter problem"))
+							break;
+						}
+					}
+
+					diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
+					return (pdiva);
+				}
+			}
+
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
+
+			/*
+			   Not able to add adapter - remove it and return error
+			 */
+			DBG_ERR(("can not alloc request array"))
+			diva_driver_remove_card(pdiva);
+
+			return (0);
+		}
+	}
 
-  return (0);
+	return (0);
 }
 
 /* --------------------------------------------------------------------------
     Called on driver load, MAIN, main, DriverEntry
    -------------------------------------------------------------------------- */
-int divasa_xdi_driver_entry (void) {
-  diva_os_initialize_spin_lock (&adapter_lock, "adapter");
-  diva_q_init(&adapter_queue);
-  memset (&IoAdapters[0], 0x00, sizeof(IoAdapters));
-  diva_init_request_array ();
+int divasa_xdi_driver_entry(void)
+{
+	diva_os_initialize_spin_lock(&adapter_lock, "adapter");
+	diva_q_init(&adapter_queue);
+	memset(&IoAdapters[0], 0x00, sizeof(IoAdapters));
+	diva_init_request_array();
 
-  return  (0);
+	return (0);
 }
 
 /* --------------------------------------------------------------------------
     Remove adapter from list
    -------------------------------------------------------------------------- */
-static diva_os_xdi_adapter_t* get_and_remove_from_queue(void) {
-  diva_os_spin_lock_magic_t old_irql;
-  diva_os_xdi_adapter_t* a;
+static diva_os_xdi_adapter_t *get_and_remove_from_queue(void)
+{
+	diva_os_spin_lock_magic_t old_irql;
+	diva_os_xdi_adapter_t *a;
 
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "driver_unload");
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload");
 
-  if((a = (diva_os_xdi_adapter_t*)diva_q_get_head(&adapter_queue)))
-    diva_q_remove (&adapter_queue, &a->link);
+	if ((a = (diva_os_xdi_adapter_t *) diva_q_get_head(&adapter_queue)))
+		diva_q_remove(&adapter_queue, &a->link);
 
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "driver_unload");
-  return(a);
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
+	return (a);
 }
 
 /* --------------------------------------------------------------------------
     Remove card from the card list
    -------------------------------------------------------------------------- */
-void diva_driver_remove_card (void* pdiva) {
-  diva_os_spin_lock_magic_t old_irql;
-  diva_os_xdi_adapter_t* a[4];
-  diva_os_xdi_adapter_t* pa;
-  int i;
-
-  pa = a[0] = (diva_os_xdi_adapter_t*)pdiva;
-  a[1] = a[2] = a[3] = 0;
-
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "remode adapter");
-
-  for (i = 1; i < 4; i++) {
-    if ((pa = (diva_os_xdi_adapter_t*)diva_q_get_next	(&pa->link)) &&
-        !pa->interface.cleanup_adapter_proc) {
-      a[i] = pa;
-    } else {
-      break;
-    }
-  }
-
-  for (i = 0; ((i < 4) && a[i]); i++) {
-    diva_q_remove (&adapter_queue, &a[i]->link);
-  }
-
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "driver_unload");
-
-  (*(a[0]->interface.cleanup_adapter_proc))(a[0]);
-
-  for (i = 0; i < 4; i++) {
-    if (a[i]) {
-      if (a[i]->controller) {
-        DBG_LOG(("remove adapter (%d)", a[i]->controller))
-        IoAdapters[a[i]->controller - 1] = 0;
-        remove_adapter_proc (a[i]);
-      }
-      diva_os_free (0, a[i]);
-    }
-  }
+void diva_driver_remove_card(void *pdiva)
+{
+	diva_os_spin_lock_magic_t old_irql;
+	diva_os_xdi_adapter_t *a[4];
+	diva_os_xdi_adapter_t *pa;
+	int i;
+
+	pa = a[0] = (diva_os_xdi_adapter_t *) pdiva;
+	a[1] = a[2] = a[3] = 0;
+
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter");
+
+	for (i = 1; i < 4; i++) {
+		if ((pa = (diva_os_xdi_adapter_t *) diva_q_get_next(&pa->link))
+		    && !pa->interface.cleanup_adapter_proc) {
+			a[i] = pa;
+		} else {
+			break;
+		}
+	}
+
+	for (i = 0; ((i < 4) && a[i]); i++) {
+		diva_q_remove(&adapter_queue, &a[i]->link);
+	}
+
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
+
+	(*(a[0]->interface.cleanup_adapter_proc)) (a[0]);
+
+	for (i = 0; i < 4; i++) {
+		if (a[i]) {
+			if (a[i]->controller) {
+				DBG_LOG(("remove adapter (%d)",
+					 a[i]->controller)) IoAdapters[a[i]->controller - 1] = 0;
+				remove_adapter_proc(a[i]);
+			}
+			diva_os_free(0, a[i]);
+		}
+	}
 }
 
 /* --------------------------------------------------------------------------
     Create diva PCI adapter and init internal adapter structures
    -------------------------------------------------------------------------- */
-static void* divas_create_pci_card (int handle, void* pci_dev_handle) {
-  diva_supported_cards_info_t* pI = &divas_supported_cards[handle];
-  diva_os_spin_lock_magic_t old_irql;
-  diva_os_xdi_adapter_t* a;
-
-  DBG_LOG(("found %d-%s",
-          pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
-
-  if (!(a = (diva_os_xdi_adapter_t*)diva_os_malloc (0, sizeof(*a)))) {
-    DBG_ERR(("A: can't alloc adapter"));
-    return (0);
-  }
-
-  memset (a, 0x00, sizeof(*a));
-
-  a->CardIndex = handle;
-  a->CardOrdinal = pI->CardOrdinal;
-  a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
-  a->xdi_adapter.cardType = a->CardOrdinal;
-  a->resources.pci.bus	= diva_os_get_pci_bus(pci_dev_handle);
-  a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
-  a->resources.pci.hdev = pci_dev_handle;
-
-  /*
-    Add master adapter first, so slave adapters will receive higher
-    numbers as master adapter
-  */
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "found_pci_card");
-  diva_q_add_tail (&adapter_queue, &a->link);
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "found_pci_card");
-
-  if ((*(pI->init_card))(a)) {
-    diva_os_enter_spin_lock (&adapter_lock, &old_irql, "found_pci_card");
-    diva_q_remove (&adapter_queue, &a->link);
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "found_pci_card");
-    diva_os_free (0, a);
-    DBG_ERR(("A: can't get adapter resources"));
-    return (0);
-  }
+static void *divas_create_pci_card(int handle, void *pci_dev_handle)
+{
+	diva_supported_cards_info_t *pI = &divas_supported_cards[handle];
+	diva_os_spin_lock_magic_t old_irql;
+	diva_os_xdi_adapter_t *a;
+
+	DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
+
+	if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) {
+		DBG_ERR(("A: can't alloc adapter"));
+		return (0);
+	}
+
+	memset(a, 0x00, sizeof(*a));
+
+	a->CardIndex = handle;
+	a->CardOrdinal = pI->CardOrdinal;
+	a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
+	a->xdi_adapter.cardType = a->CardOrdinal;
+	a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle);
+	a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
+	a->resources.pci.hdev = pci_dev_handle;
+
+	/*
+	   Add master adapter first, so slave adapters will receive higher
+	   numbers as master adapter
+	 */
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
+	diva_q_add_tail(&adapter_queue, &a->link);
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
+
+	if ((*(pI->init_card)) (a)) {
+		diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
+		diva_q_remove(&adapter_queue, &a->link);
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
+		diva_os_free(0, a);
+		DBG_ERR(("A: can't get adapter resources"));
+		return (0);
+	}
 
-  return (a);
+	return (a);
 }
 
 /* --------------------------------------------------------------------------
     Called on driver unload FINIT, finit, Unload
    -------------------------------------------------------------------------- */
-void divasa_xdi_driver_unload (void) {
-  diva_os_xdi_adapter_t* a;
+void divasa_xdi_driver_unload(void)
+{
+	diva_os_xdi_adapter_t *a;
 
-  while ((a = get_and_remove_from_queue())) {
-    if (a->interface.cleanup_adapter_proc) {
-      (*(a->interface.cleanup_adapter_proc))(a);
-    }
-    if (a->controller) {
-      IoAdapters[a->controller - 1] = 0;
-      remove_adapter_proc (a);
-    }
-    diva_os_free (0, a);
-  }
-  diva_os_destroy_spin_lock (&adapter_lock, "adapter");
+	while ((a = get_and_remove_from_queue())) {
+		if (a->interface.cleanup_adapter_proc) {
+			(*(a->interface.cleanup_adapter_proc)) (a);
+		}
+		if (a->controller) {
+			IoAdapters[a->controller - 1] = 0;
+			remove_adapter_proc(a);
+		}
+		diva_os_free(0, a);
+	}
+	diva_os_destroy_spin_lock(&adapter_lock, "adapter");
 }
 
 /*
 **  Receive and process command from user mode utility
 */
-static int
-cmp_adapter_nr (const void* what, const diva_entity_link_t* p)
+static int cmp_adapter_nr(const void *what, const diva_entity_link_t * p)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)p;
-  dword nr = (dword)(unsigned long)what;
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) p;
+	dword nr = (dword) (unsigned long) what;
 
-  return (nr != a->controller);
+	return (nr != a->controller);
 }
 
-void*
-diva_xdi_open_adapter (void* os_handle, const void* src,
-                       int length, divas_xdi_copy_from_user_fn_t cp_fn)
-{
-  diva_xdi_um_cfg_cmd_t	msg;
-  diva_os_xdi_adapter_t* a;
-  diva_os_spin_lock_magic_t old_irql;
-
-  if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
-    DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
-            length, sizeof(diva_xdi_um_cfg_cmd_t)))
-    return (0);
-  }
-  if ((*cp_fn)(os_handle, &msg, src, sizeof(msg)) <= 0) {
-    DBG_ERR(("A: A(?) open, write error"))
-    return (0);
-  }
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "open_adapter");
-  a = (diva_os_xdi_adapter_t*)diva_q_find (&adapter_queue,
-                                           (void*)(unsigned long)msg.adapter, cmp_adapter_nr);
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "open_adapter");
-
-  if (!a) {
-    DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter))
-  }
-	
-  return (a);
+void *diva_xdi_open_adapter(void *os_handle, const void *src,
+			    int length,
+			    divas_xdi_copy_from_user_fn_t cp_fn)
+{
+	diva_xdi_um_cfg_cmd_t msg;
+	diva_os_xdi_adapter_t *a;
+	diva_os_spin_lock_magic_t old_irql;
+
+	if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
+		DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
+			 length, sizeof(diva_xdi_um_cfg_cmd_t)))
+		return (0);
+	}
+	if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) {
+		DBG_ERR(("A: A(?) open, write error"))
+		return (0);
+	}
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
+	a = (diva_os_xdi_adapter_t *) diva_q_find(&adapter_queue,
+						  (void *) (unsigned long)
+						  msg.adapter,
+						  cmp_adapter_nr);
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
+
+	if (!a) {
+		DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter))
+	}
+
+	return (a);
 }
 
 /*
 **  Easy cleanup mailbox status
 */
-void
-diva_xdi_close_adapter (void* adapter, void* os_handle)
+void diva_xdi_close_adapter(void *adapter, void *os_handle)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)adapter;
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
 
-  a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
-  if (a->xdi_mbox.data) {
-    diva_os_free (0, a->xdi_mbox.data);
-    a->xdi_mbox.data = 0;
-  }
+	a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
+	if (a->xdi_mbox.data) {
+		diva_os_free(0, a->xdi_mbox.data);
+		a->xdi_mbox.data = 0;
+	}
 }
 
 int
-diva_xdi_write (void* adapter, void* os_handle, const void* src,
-                int length,divas_xdi_copy_from_user_fn_t cp_fn)
+diva_xdi_write(void *adapter, void *os_handle, const void *src,
+	       int length, divas_xdi_copy_from_user_fn_t cp_fn)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)adapter;
-  void* data;
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
+	void *data;
 
-  if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
-    DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
-    return (-1);
-  }
-
-  if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
-    DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
-          a->controller, length, sizeof(diva_xdi_um_cfg_cmd_t)))
-    return (-3);
-  }
-
-  if (!(data = diva_os_malloc (0, length))) {
-    DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
-    return (-2);
-  }
-
-  length = (*cp_fn)(os_handle, data, src, length);
-  if (length > 0) {
-    if ((*(a->interface.cmd_proc))(a, (diva_xdi_um_cfg_cmd_t*)data, length)) {
-      length = -3;
-    }
-  } else {
-    DBG_ERR(("A: A(%d) write error (%d)", a->controller, length))
-  }
+	if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
+		DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
+		return (-1);
+	}
+
+	if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
+		DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
+			 a->controller, length,
+			 sizeof(diva_xdi_um_cfg_cmd_t)))
+		return (-3);
+	}
+
+	if (!(data = diva_os_malloc(0, length))) {
+		DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
+		return (-2);
+	}
+
+	length = (*cp_fn) (os_handle, data, src, length);
+	if (length > 0) {
+		if ((*(a->interface.cmd_proc))
+		    (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
+			length = -3;
+		}
+	} else {
+		DBG_ERR(("A: A(%d) write error (%d)", a->controller,
+			 length))}
 
-  diva_os_free (0, data);
+	diva_os_free(0, data);
 
-  return (length);
+	return (length);
 }
 
 /*
 **  Write answers to user mode utility, if any
 */
 int
-diva_xdi_read (void* adapter, void* os_handle, void* dst,
-               int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
+diva_xdi_read(void *adapter, void *os_handle, void *dst,
+	      int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
+{
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
+	int ret;
+
+	if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
+		DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
+		return (-1);
+	}
+	if (!a->xdi_mbox.data) {
+		a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
+		DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
+		return (-2);
+	}
+
+	if (max_length < a->xdi_mbox.data_length) {
+		DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)",
+			 a->controller, max_length,
+			 a->xdi_mbox.data_length))
+		return (-3);
+	}
+
+	ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data,
+		      a->xdi_mbox.data_length);
+	if (ret > 0) {
+		diva_os_free(0, a->xdi_mbox.data);
+		a->xdi_mbox.data = 0;
+		a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
+	}
+
+	return (ret);
+}
+
+
+void diva_os_irq_wrapper(int irq, void *context, struct pt_regs *regs)
+{
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
+	diva_xdi_clear_interrupts_proc_t clear_int_proc;
+
+	if (!a || !a->xdi_adapter.diva_isr_handler) {
+		return;
+	}
+
+	if ((clear_int_proc = a->clear_interrupts_proc)) {
+		(*clear_int_proc) (a);
+		a->clear_interrupts_proc = 0;
+		return;
+	}
+
+	(*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter);
+}
+
+static void diva_init_request_array(void)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)adapter;
-  int ret;
+	Requests[0] = DivaIdiRequest0;
+	Requests[1] = DivaIdiRequest1;
+	Requests[2] = DivaIdiRequest2;
+	Requests[3] = DivaIdiRequest3;
+	Requests[4] = DivaIdiRequest4;
+	Requests[5] = DivaIdiRequest5;
+	Requests[6] = DivaIdiRequest6;
+	Requests[7] = DivaIdiRequest7;
+	Requests[8] = DivaIdiRequest8;
+	Requests[9] = DivaIdiRequest9;
+	Requests[10] = DivaIdiRequest10;
+	Requests[11] = DivaIdiRequest11;
+	Requests[12] = DivaIdiRequest12;
+	Requests[13] = DivaIdiRequest13;
+	Requests[14] = DivaIdiRequest14;
+	Requests[15] = DivaIdiRequest15;
+	Requests[16] = DivaIdiRequest16;
+	Requests[17] = DivaIdiRequest17;
+	Requests[18] = DivaIdiRequest18;
+	Requests[19] = DivaIdiRequest19;
+	Requests[20] = DivaIdiRequest20;
+	Requests[21] = DivaIdiRequest21;
+	Requests[22] = DivaIdiRequest22;
+	Requests[23] = DivaIdiRequest23;
+	Requests[24] = DivaIdiRequest24;
+	Requests[25] = DivaIdiRequest25;
+	Requests[26] = DivaIdiRequest26;
+	Requests[27] = DivaIdiRequest27;
+	Requests[28] = DivaIdiRequest28;
+	Requests[29] = DivaIdiRequest29;
+	Requests[30] = DivaIdiRequest30;
+	Requests[31] = DivaIdiRequest31;
+}
 
-  if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
-    DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
-    return (-1);
-  }
-  if (!a->xdi_mbox.data) {
-    a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
-    DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
-    return (-2);
-  }
-
-  if (max_length < a->xdi_mbox.data_length) {
-    DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)", 
-            a->controller, max_length, a->xdi_mbox.data_length))
-    return (-3);
-  }
-
-  ret = (*cp_fn)(os_handle, dst, a->xdi_mbox.data, a->xdi_mbox.data_length);
-  if (ret > 0) {
-    diva_os_free (0, a->xdi_mbox.data);
-    a->xdi_mbox.data = 0;
-    a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
-  }
-
-  return (ret);
-}
-
-
-void
-diva_os_irq_wrapper (int irq, void* context, struct pt_regs* regs)
-{
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)context;
-  diva_xdi_clear_interrupts_proc_t clear_int_proc;
-
-  if (!a || !a->xdi_adapter.diva_isr_handler) {
-    return;
-  }
-
-  if ((clear_int_proc = a->clear_interrupts_proc)) {
-    (*clear_int_proc)(a);
-    a->clear_interrupts_proc = 0;
-    return;
-  }
-
-  (*(a->xdi_adapter.diva_isr_handler))(&a->xdi_adapter);
-}
-
-static void
-diva_init_request_array (void)
-{
-  Requests[0 ] = DivaIdiRequest0;
-  Requests[1 ] = DivaIdiRequest1;
-  Requests[2 ] = DivaIdiRequest2;
-  Requests[3 ] = DivaIdiRequest3;
-  Requests[4 ] = DivaIdiRequest4;
-  Requests[5 ] = DivaIdiRequest5;
-  Requests[6 ] = DivaIdiRequest6;
-  Requests[7 ] = DivaIdiRequest7;
-  Requests[8 ] = DivaIdiRequest8;
-  Requests[9 ] = DivaIdiRequest9;
-  Requests[10] = DivaIdiRequest10;
-  Requests[11] = DivaIdiRequest11;
-  Requests[12] = DivaIdiRequest12;
-  Requests[13] = DivaIdiRequest13;
-  Requests[14] = DivaIdiRequest14;
-  Requests[15] = DivaIdiRequest15;
-  Requests[16] = DivaIdiRequest16;
-  Requests[17] = DivaIdiRequest17;
-  Requests[18] = DivaIdiRequest18;
-  Requests[19] = DivaIdiRequest19;
-  Requests[20] = DivaIdiRequest20;
-  Requests[21] = DivaIdiRequest21;
-  Requests[22] = DivaIdiRequest22;
-  Requests[23] = DivaIdiRequest23;
-  Requests[24] = DivaIdiRequest24;
-  Requests[25] = DivaIdiRequest25;
-  Requests[26] = DivaIdiRequest26;
-  Requests[27] = DivaIdiRequest27;
-  Requests[28] = DivaIdiRequest28;
-  Requests[29] = DivaIdiRequest29;
-  Requests[30] = DivaIdiRequest30;
-  Requests[31] = DivaIdiRequest31;
-}
-
-void
-diva_xdi_display_adapter_features (int card)
-{
-  dword features;
-  if (!card || ((card-1) > MAX_ADAPTER) || !IoAdapters[card-1]) {
-    return;
-  }
-  card--;
-  features = IoAdapters[card]->Properties.Features;
-
-  DBG_LOG(("FEATURES FOR ADAPTER: %d", card+1))
-  DBG_LOG((" DI_FAX3          :  %s", (features & DI_FAX3)   ? "Y" : "N"))
-  DBG_LOG((" DI_MODEM         :  %s", (features & DI_MODEM)  ? "Y" : "N"))
-  DBG_LOG((" DI_POST          :  %s", (features & DI_POST)   ? "Y" : "N"))
-  DBG_LOG((" DI_V110          :  %s", (features & DI_V110)   ? "Y" : "N"))
-  DBG_LOG((" DI_V120          :  %s", (features & DI_V120)   ? "Y" : "N"))
-  DBG_LOG((" DI_POTS          :  %s", (features & DI_POTS)   ? "Y" : "N"))
-  DBG_LOG((" DI_CODEC         :  %s", (features & DI_CODEC)  ? "Y" : "N"))
-  DBG_LOG((" DI_MANAGE        :  %s", (features & DI_MANAGE) ? "Y" : "N"))
-  DBG_LOG((" DI_V_42          :  %s", (features & DI_V_42)   ? "Y" : "N"))
-  DBG_LOG((" DI_EXTD_FAX      :  %s", (features & DI_EXTD_FAX) ? "Y" : "N"))
-  DBG_LOG((" DI_AT_PARSER     :  %s", (features & DI_AT_PARSER) ? "Y" : "N"))
-  DBG_LOG((" DI_VOICE_OVER_IP :  %s", (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
-}
-
-void diva_add_slave_adapter (diva_os_xdi_adapter_t* a) {
-  diva_os_spin_lock_magic_t old_irql;
-
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "add_slave");
-  diva_q_add_tail (&adapter_queue, &a->link);
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "add_slave");
-}
-
-int diva_card_read_xlog (diva_os_xdi_adapter_t* a) {
-  diva_get_xlog_t *req;
-  byte* data;
-
-  if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
-    return (-1);                                                                                         }
-  if (!(data = diva_os_malloc (0, sizeof(struct mi_pc_maint)))) {
-    return (-1);
-  }
-  memset (data, 0x00, sizeof(struct mi_pc_maint));
-
-  if (!(req = diva_os_malloc (0, sizeof(*req)))) {
-    diva_os_free (0, data);
-    return (-1);
-  }
-  req->command = 0x0400;
-  req->req = LOG;
-  req->rc = 0x00;
-
-  (*(a->xdi_adapter.DIRequest))(&a->xdi_adapter, (ENTITY*)req);
-
-  if (!req->rc || req->req) {
-    diva_os_free (0, data);
-    diva_os_free (0, req);
-    return (-1);
-  }
-
-  memcpy (data, &req->req, sizeof(struct mi_pc_maint));
-
-  diva_os_free (0, req);
-
-  a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
-  a->xdi_mbox.data = data;
-  a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+void diva_xdi_display_adapter_features(int card)
+{
+	dword features;
+	if (!card || ((card - 1) > MAX_ADAPTER) || !IoAdapters[card - 1]) {
+		return;
+	}
+	card--;
+	features = IoAdapters[card]->Properties.Features;
+
+	DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1))
+	DBG_LOG((" DI_FAX3          :  %s",
+		     (features & DI_FAX3) ? "Y" : "N"))
+	DBG_LOG((" DI_MODEM         :  %s",
+		     (features & DI_MODEM) ? "Y" : "N"))
+	DBG_LOG((" DI_POST          :  %s",
+		     (features & DI_POST) ? "Y" : "N"))
+	DBG_LOG((" DI_V110          :  %s",
+		     (features & DI_V110) ? "Y" : "N"))
+	DBG_LOG((" DI_V120          :  %s",
+		     (features & DI_V120) ? "Y" : "N"))
+	DBG_LOG((" DI_POTS          :  %s",
+		     (features & DI_POTS) ? "Y" : "N"))
+	DBG_LOG((" DI_CODEC         :  %s",
+		     (features & DI_CODEC) ? "Y" : "N"))
+	DBG_LOG((" DI_MANAGE        :  %s",
+		     (features & DI_MANAGE) ? "Y" : "N"))
+	DBG_LOG((" DI_V_42          :  %s",
+		     (features & DI_V_42) ? "Y" : "N"))
+	DBG_LOG((" DI_EXTD_FAX      :  %s",
+		     (features & DI_EXTD_FAX) ? "Y" : "N"))
+	DBG_LOG((" DI_AT_PARSER     :  %s",
+		     (features & DI_AT_PARSER) ? "Y" : "N"))
+	DBG_LOG((" DI_VOICE_OVER_IP :  %s",
+		     (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
+}
+
+void diva_add_slave_adapter(diva_os_xdi_adapter_t * a)
+{
+	diva_os_spin_lock_magic_t old_irql;
 
-  return (0);
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave");
+	diva_q_add_tail(&adapter_queue, &a->link);
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave");
 }
 
-void
-xdiFreeFile (void* handle)
+int diva_card_read_xlog(diva_os_xdi_adapter_t * a)
 {
+	diva_get_xlog_t *req;
+	byte *data;
+
+	if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
+		return (-1);
+	}
+	if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) {
+		return (-1);
+	}
+	memset(data, 0x00, sizeof(struct mi_pc_maint));
+
+	if (!(req = diva_os_malloc(0, sizeof(*req)))) {
+		diva_os_free(0, data);
+		return (-1);
+	}
+	req->command = 0x0400;
+	req->req = LOG;
+	req->rc = 0x00;
+
+	(*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req);
+
+	if (!req->rc || req->req) {
+		diva_os_free(0, data);
+		diva_os_free(0, req);
+		return (-1);
+	}
+
+	memcpy(data, &req->req, sizeof(struct mi_pc_maint));
+
+	diva_os_free(0, req);
+
+	a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
+	a->xdi_mbox.data = data;
+	a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+
+	return (0);
 }
 
+void xdiFreeFile(void *handle)
+{
+}
diff -Nru a/drivers/isdn/hardware/eicon/diva.h b/drivers/isdn/hardware/eicon/diva.h
--- a/drivers/isdn/hardware/eicon/diva.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/hardware/eicon/diva.h	Sun Nov 17 20:30:12 2002
@@ -1,31 +1,31 @@
-/* $Id: diva.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: diva.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
 
 #ifndef __DIVA_XDI_OS_PART_H__
 #define __DIVA_XDI_OS_PART_H__
 
 
-int  divasa_xdi_driver_entry  (void);
-void divasa_xdi_driver_unload (void);
-void* diva_driver_add_card (void* pdev, unsigned long CardOrdinal);
-void diva_driver_remove_card (void* pdiva);
+int divasa_xdi_driver_entry(void);
+void divasa_xdi_driver_unload(void);
+void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal);
+void diva_driver_remove_card(void *pdiva);
 
-typedef int (*divas_xdi_copy_to_user_fn_t)(void* os_handle, void* dst,
-                                           const void* src, int length);
+typedef int (*divas_xdi_copy_to_user_fn_t) (void *os_handle, void *dst,
+					    const void *src, int length);
 
-typedef int (*divas_xdi_copy_from_user_fn_t)(void* os_handle, void* dst,
-                                             const void* src, int length);
+typedef int (*divas_xdi_copy_from_user_fn_t) (void *os_handle, void *dst,
+					      const void *src, int length);
 
-int diva_xdi_read (void* adapter, void* os_handle, void* dst,
-                   int max_length, divas_xdi_copy_to_user_fn_t cp_fn);
+int diva_xdi_read(void *adapter, void *os_handle, void *dst,
+		  int max_length, divas_xdi_copy_to_user_fn_t cp_fn);
 
-int diva_xdi_write (void* adapter, void* os_handle, const void* src,
-                    int length, divas_xdi_copy_from_user_fn_t cp_fn);
+int diva_xdi_write(void *adapter, void *os_handle, const void *src,
+		   int length, divas_xdi_copy_from_user_fn_t cp_fn);
 
-void*	diva_xdi_open_adapter (void* os_handle, const void* src,
-                               int length, divas_xdi_copy_from_user_fn_t cp_fn);
+void *diva_xdi_open_adapter(void *os_handle, const void *src,
+			    int length,
+			    divas_xdi_copy_from_user_fn_t cp_fn);
 
-void	diva_xdi_close_adapter (void* adapter, void* os_handle);
+void diva_xdi_close_adapter(void *adapter, void *os_handle);
 
 
 #endif
-
diff -Nru a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
--- a/drivers/isdn/hardware/eicon/diva_didd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/diva_didd.c	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,4 @@
-/* $Id: diva_didd.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: diva_didd.c,v 1.1.2.6 2001/05/01 15:48:05 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -23,18 +23,19 @@
 #include "divasync.h"
 #include "did_vers.h"
 
-static char *main_revision = "$Revision: 1.1.2.2 $";
+static char *main_revision = "$Revision: 1.1.2.6 $";
 
-static char *DRIVERNAME = "Eicon DIVA - DIDD table (http://www.melware.net)";
+static char *DRIVERNAME =
+    "Eicon DIVA - DIDD table (http://www.melware.net)";
 static char *DRIVERLNAME = "divadidd";
 char *DRIVERRELEASE = "2.0";
 
 static char *dir_in_proc_net = "isdn";
 static char *main_proc_dir = "eicon";
 
-MODULE_DESCRIPTION(             "DIDD table driver for diva drivers");
-MODULE_AUTHOR(                  "Cytronics & Melware, Eicon Networks");
-MODULE_SUPPORTED_DEVICE(        "Eicon diva drivers");
+MODULE_DESCRIPTION("DIDD table driver for diva drivers");
+MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
+MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
 MODULE_LICENSE("GPL");
 
 #define MAX_DESCRIPTORS  32
@@ -45,7 +46,7 @@
 extern int diddfunc_init(void);
 extern void diddfunc_finit(void);
 
-extern void DIVA_DIDD_Read (void *, int);
+extern void DIVA_DIDD_Read(void *, int);
 
 static struct proc_dir_entry *proc_net_isdn;
 static struct proc_dir_entry *proc_didd;
@@ -54,8 +55,7 @@
 EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
 EXPORT_SYMBOL_NOVERS(proc_net_isdn_eicon);
 
-static char *
-getrev(const char *revision)
+static char *getrev(const char *revision)
 {
 	char *rev;
 	char *p;
@@ -63,106 +63,112 @@
 		rev = p + 2;
 		p = strchr(rev, '$');
 		*--p = 0;
-	} else rev = "1.0";
+	} else
+		rev = "1.0";
 	return rev;
 }
 
 static int
-proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+proc_read(char *page, char **start, off_t off, int count, int *eof,
+	  void *data)
 {
-  int len = 0;
-  char tmprev[32];
+	int len = 0;
+	char tmprev[32];
 
-  strcpy(tmprev, main_revision);
-  len += sprintf(page+len, "%s\n", DRIVERNAME);
-  len += sprintf(page+len, "name     : %s\n", DRIVERLNAME);
-  len += sprintf(page+len, "release  : %s\n", DRIVERRELEASE);
-  len += sprintf(page+len, "build    : %s(%s)\n",
-            diva_didd_common_code_build, DIVA_BUILD);
-  len += sprintf(page+len, "revision : %s\n", getrev(tmprev));
-
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	strcpy(tmprev, main_revision);
+	len += sprintf(page + len, "%s\n", DRIVERNAME);
+	len += sprintf(page + len, "name     : %s\n", DRIVERLNAME);
+	len += sprintf(page + len, "release  : %s\n", DRIVERRELEASE);
+	len += sprintf(page + len, "build    : %s(%s)\n",
+		       diva_didd_common_code_build, DIVA_BUILD);
+	len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
+
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
 static int DIVA_INIT_FUNCTION create_proc(void)
 {
-  struct proc_dir_entry *pe;
+	struct proc_dir_entry *pe;
 
-  for (pe = proc_net->subdir; pe; pe = pe->next) {
-    if (!memcmp(dir_in_proc_net, pe->name, pe->namelen)) {
-        proc_net_isdn = pe;
-        break;
-    }
-  }
-  if (!proc_net_isdn) {
-    proc_net_isdn = create_proc_entry(dir_in_proc_net, S_IFDIR, proc_net);
-  }
-  proc_net_isdn_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net_isdn);
-
-  if(proc_net_isdn_eicon) {
-    if((proc_didd = create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO, proc_net_isdn_eicon))) {
-      proc_didd->read_proc = proc_read;
-    }
-    return(1);
-  }
-  return(0);
+	for (pe = proc_net->subdir; pe; pe = pe->next) {
+		if (!memcmp(dir_in_proc_net, pe->name, pe->namelen)) {
+			proc_net_isdn = pe;
+			break;
+		}
+	}
+	if (!proc_net_isdn) {
+		proc_net_isdn =
+		    create_proc_entry(dir_in_proc_net, S_IFDIR, proc_net);
+	}
+	proc_net_isdn_eicon =
+	    create_proc_entry(main_proc_dir, S_IFDIR, proc_net_isdn);
+
+	if (proc_net_isdn_eicon) {
+		if (
+		    (proc_didd =
+		     create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO,
+				       proc_net_isdn_eicon))) {
+			proc_didd->read_proc = proc_read;
+		}
+		return (1);
+	}
+	return (0);
 }
 
 static void DIVA_EXIT_FUNCTION remove_proc(void)
 {
-  remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon);
-  remove_proc_entry(main_proc_dir, proc_net_isdn);
+	remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon);
+	remove_proc_entry(main_proc_dir, proc_net_isdn);
 
-  if ((proc_net_isdn) && (!proc_net_isdn->subdir)){
-    remove_proc_entry(dir_in_proc_net, proc_net);
-  }
+	if ((proc_net_isdn) && (!proc_net_isdn->subdir)) {
+		remove_proc_entry(dir_in_proc_net, proc_net);
+	}
 }
 
-static int DIVA_INIT_FUNCTION
-divadidd_init(void)
+static int DIVA_INIT_FUNCTION divadidd_init(void)
 {
-  char tmprev[32];
-  int ret = 0;
+	char tmprev[32];
+	int ret = 0;
 
-  MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 
-  printk(KERN_INFO "%s\n", DRIVERNAME);
-  printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  printk("%s  Build:%s(%s)\n", getrev(tmprev),
-        diva_didd_common_code_build, DIVA_BUILD);
+	printk(KERN_INFO "%s\n", DRIVERNAME);
+	printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	printk("%s  Build:%s(%s)\n", getrev(tmprev),
+	       diva_didd_common_code_build, DIVA_BUILD);
 
-  if (!create_proc()) {
-    printk(KERN_ERR "%s: could not create proc entry\n", DRIVERLNAME);
-    ret = -EIO;
-    goto out;
-  }
+	if (!create_proc()) {
+		printk(KERN_ERR "%s: could not create proc entry\n",
+		       DRIVERLNAME);
+		ret = -EIO;
+		goto out;
+	}
 
-  if(!diddfunc_init()) {
-    printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME);
-  	remove_proc();
-    ret = -EIO;
-    goto out;
-  }
+	if (!diddfunc_init()) {
+		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
+		       DRIVERLNAME);
+		remove_proc();
+		ret = -EIO;
+		goto out;
+	}
 
-out:
-  MOD_DEC_USE_COUNT;
-  return (ret);
+      out:
+	MOD_DEC_USE_COUNT;
+	return (ret);
 }
 
-void DIVA_EXIT_FUNCTION
-divadidd_exit(void)
+void DIVA_EXIT_FUNCTION divadidd_exit(void)
 {
-  diddfunc_finit();
-  remove_proc();
-  printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
+	diddfunc_finit();
+	remove_proc();
+	printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 }
 
 module_init(divadidd_init);
 module_exit(divadidd_exit);
-
diff -Nru a/drivers/isdn/hardware/eicon/diva_pci.h b/drivers/isdn/hardware/eicon/diva_pci.h
--- a/drivers/isdn/hardware/eicon/diva_pci.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/isdn/hardware/eicon/diva_pci.h	Sun Nov 17 20:30:13 2002
@@ -1,19 +1,16 @@
-/* $Id: diva_pci.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: diva_pci.h,v 1.1.2.2 2001/02/12 20:23:46 armin Exp $ */
 
 #ifndef __DIVA_PCI_INTERFACE_H__
 #define __DIVA_PCI_INTERFACE_H__
 
-void*  divasa_remap_pci_bar (unsigned long  bar,
-                             unsigned long area_length);
-void  divasa_unmap_pci_bar (void* bar);
-unsigned long divasa_get_pci_irq (unsigned char bus,
-                                  unsigned char func,
-                                  void* pci_dev_handle);
-unsigned long divasa_get_pci_bar (unsigned char bus,
-                                  unsigned char func,
-                                  int bar,
-                                  void* pci_dev_handle);
-byte diva_os_get_pci_bus (void* pci_dev_handle);
-byte diva_os_get_pci_func (void* pci_dev_handle);
+void *divasa_remap_pci_bar(unsigned long bar, unsigned long area_length);
+void divasa_unmap_pci_bar(void *bar);
+unsigned long divasa_get_pci_irq(unsigned char bus,
+				 unsigned char func, void *pci_dev_handle);
+unsigned long divasa_get_pci_bar(unsigned char bus,
+				 unsigned char func,
+				 int bar, void *pci_dev_handle);
+byte diva_os_get_pci_bus(void *pci_dev_handle);
+byte diva_os_get_pci_func(void *pci_dev_handle);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
--- a/drivers/isdn/hardware/eicon/divamnt.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/divamnt.c	Sun Nov 17 20:30:14 2002
@@ -1,10 +1,10 @@
-/* $Id: divamnt.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: divamnt.c,v 1.1.2.4 2001/05/01 15:48:05 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * Maint module
  *
- * Copyright 2000,2001 by Armin Schindler (mac@melware.de)
- * Copyright 2000,2001 Cytronics & Melware (info@melware.de)
+ * Copyright 2000-2002 by Armin Schindler (mac@melware.de)
+ * Copyright 2000-2002 Cytronics & Melware (info@melware.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -30,123 +30,132 @@
 
 EXPORT_NO_SYMBOLS;
 
-static char *main_revision = "$Revision: 1.1.2.2 $";
+static char *main_revision = "$Revision: 1.1.2.4 $";
 
 static int major = 241;
 
-MODULE_DESCRIPTION(             "Maint driver for Eicon DIVA Server cards");
-MODULE_AUTHOR(                  "Cytronics & Melware, Eicon Networks");
-MODULE_SUPPORTED_DEVICE(        "DIVA card driver");
+MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
+MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
+MODULE_SUPPORTED_DEVICE("DIVA card driver");
 MODULE_LICENSE("GPL");
 MODULE_PARM(major, "i");
 MODULE_PARM_DESC(major, "Major number for /dev/DivasMAINT");
 
 int buffer_length = 128;
 MODULE_PARM(buffer_length, "i");
-unsigned long diva_dbg_mem=0;
+unsigned long diva_dbg_mem = 0;
 MODULE_PARM(diva_dbg_mem, "l");
 
-static char *DRIVERNAME = "Eicon DIVA - MAINT module (http://www.melware.net)";
+static char *DRIVERNAME =
+    "Eicon DIVA - MAINT module (http://www.melware.net)";
 static char *DRIVERLNAME = "diva_mnt";
 char *DRIVERRELEASE = "2.0";
 
 static devfs_handle_t devfs_handle;
 
 static wait_queue_head_t msgwaitq;
-static atomic_t opened; 
+static DECLARE_MUTEX(opened_sem);
+static int opened;
 static struct timeval start_time;
 
 extern int mntfunc_init(int *, void **, unsigned long);
 extern void mntfunc_finit(void);
-extern int maint_read_write(void * buf);
+extern int maint_read_write(void *buf);
 
 /*
  *  helper functions
  */
-static char *
-getrev(const char *revision)
+static char *getrev(const char *revision)
 {
-  char *rev;
-  char *p;
+	char *rev;
+	char *p;
 
-  if ((p = strchr(revision, ':'))) {
-    rev = p + 2;
-    p = strchr(rev, '$');
-    *--p = 0;
-  } else rev = "1.0";
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "1.0";
 
-  return rev;
-} 
+	return rev;
+}
 
 /*
  * memory alloc
  */
-void* diva_os_malloc (unsigned long flags, unsigned long size) {
-  return (vmalloc (size));
+void *diva_os_malloc(unsigned long flags, unsigned long size)
+{
+	return (vmalloc(size));
 }
-void diva_os_free (unsigned long flags, void* ptr) {
-  if (ptr) {
-    vfree (ptr);
-  }
-}
-void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size) {
-		return(kmalloc(size, GFP_KERNEL));
-}
-void diva_os_free_tbuffer(unsigned long flags, void* ptr) {
-  if (ptr) {
-    kfree (ptr);
-  }
+void diva_os_free(unsigned long flags, void *ptr)
+{
+	if (ptr) {
+		vfree(ptr);
+	}
+}
+void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size)
+{
+	return (kmalloc(size, GFP_KERNEL));
+}
+void diva_os_free_tbuffer(unsigned long flags, void *ptr)
+{
+	if (ptr) {
+		kfree(ptr);
+	}
 }
 
 /*
  * sleep msec
  */
-void diva_os_sleep (dword mSec)
+void diva_os_sleep(dword mSec)
 {
 	unsigned long timeout = HZ * mSec / 1000 + 1;
-			 
+
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(timeout);
-} 
+}
 
 /*
  * kernel/user space copy functions
  */
-int diva_os_copy_to_user(void* os_handle, void* dst, const void* src, int length)
+int diva_os_copy_to_user(void *os_handle, void *dst, const void *src,
+			 int length)
 {
 	return (copy_to_user(dst, src, length));
 }
-int diva_os_copy_from_user(void* os_handle, void* dst, const void* src, int length)
+int diva_os_copy_from_user(void *os_handle, void *dst, const void *src,
+			   int length)
 {
-	return(copy_from_user(dst, src, length));
-} 
+	return (copy_from_user(dst, src, length));
+}
 
 /*
  * get time
  */
-void diva_os_get_time (dword* sec, dword* usec) {
-  struct timeval tv;
+void diva_os_get_time(dword * sec, dword * usec)
+{
+	struct timeval tv;
 
-  do_gettimeofday (&tv);
+	do_gettimeofday(&tv);
 
-  if (tv.tv_sec > start_time.tv_sec) {
-    if (start_time.tv_usec > tv.tv_usec) {
-      tv.tv_sec--;
-      tv.tv_usec += 1000000;
-    }
-    *sec  = (dword)(tv.tv_sec  - start_time.tv_sec);
-    *usec = (dword)(tv.tv_usec - start_time.tv_usec);
-  } else if (tv.tv_sec == start_time.tv_sec) {
-    *sec  = 0;
-    if (start_time.tv_usec < tv.tv_usec) {
-      *usec = (dword)(tv.tv_usec - start_time.tv_usec);
-    } else {
-      *usec = 0;
-    }
-  } else {
-    *sec  = (dword)tv.tv_sec;
-    *usec = (dword)tv.tv_usec;
-  }
+	if (tv.tv_sec > start_time.tv_sec) {
+		if (start_time.tv_usec > tv.tv_usec) {
+			tv.tv_sec--;
+			tv.tv_usec += 1000000;
+		}
+		*sec = (dword) (tv.tv_sec - start_time.tv_sec);
+		*usec = (dword) (tv.tv_usec - start_time.tv_usec);
+	} else if (tv.tv_sec == start_time.tv_sec) {
+		*sec = 0;
+		if (start_time.tv_usec < tv.tv_usec) {
+			*usec = (dword) (tv.tv_usec - start_time.tv_usec);
+		} else {
+			*usec = 0;
+		}
+	} else {
+		*sec = (dword) tv.tv_sec;
+		*usec = (dword) tv.tv_usec;
+	}
 }
 
 /*
@@ -163,274 +172,273 @@
 static ssize_t
 maint_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
-  diva_dbg_entry_head_t* pmsg = 0;
-  diva_os_spin_lock_magic_t old_irql;
-  word size;
-  char* pstr, *dli_label = "UNK";
+	diva_dbg_entry_head_t *pmsg = 0;
+	diva_os_spin_lock_magic_t old_irql;
+	word size;
+	char *pstr, *dli_label = "UNK";
 	int str_length;
 	int *str_msg;
 
-  if (off != &file->f_pos)
-    return -ESPIPE;
+	if (off != &file->f_pos)
+		return -ESPIPE;
+
+	if (!file->private_data) {
+		for (;;) {
+			while (
+			       (pmsg =
+				diva_maint_get_message(&size,
+						       &old_irql))) {
+				if (!(pmsg->facility == MSG_TYPE_STRING)) {
+					diva_maint_ack_message(1,
+							       &old_irql);
+				} else {
+					break;
+				}
+			}
+
+			if (!pmsg) {
+				if (file->f_flags & O_NONBLOCK) {
+					return (-EAGAIN);
+				}
+				interruptible_sleep_on(&msgwaitq);
+				if (signal_pending(current)) {
+					return (-ERESTARTSYS);
+				}
+			} else {
+				break;
+			}
+		}
+		/*
+		   The length of message that shoule be read is:
+		   pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero
+		 */
+		if (!
+		    (str_msg =
+		     (int *) diva_os_malloc_tbuffer(0,
+						    pmsg->data_length +
+						    29 + 2 * sizeof(int)))) {
+			diva_maint_ack_message(0, &old_irql);
+			return (-ENOMEM);
+		}
+		pstr = (char *) &str_msg[2];
+
+		switch (pmsg->dli) {
+		case DLI_LOG:
+			dli_label = "LOG";
+			break;
+		case DLI_FTL:
+			dli_label = "FTL";
+			break;
+		case DLI_ERR:
+			dli_label = "ERR";
+			break;
+		case DLI_TRC:
+			dli_label = "TRC";
+			break;
+		case DLI_REG:
+			dli_label = "REG";
+			break;
+		case DLI_MEM:
+			dli_label = "MEM";
+			break;
+		case DLI_SPL:
+			dli_label = "SPL";
+			break;
+		case DLI_IRP:
+			dli_label = "IRP";
+			break;
+		case DLI_TIM:
+			dli_label = "TIM";
+			break;
+		case DLI_TAPI:
+			dli_label = "TAPI";
+			break;
+		case DLI_NDIS:
+			dli_label = "NDIS";
+			break;
+		case DLI_CONN:
+			dli_label = "CONN";
+			break;
+		case DLI_STAT:
+			dli_label = "STAT";
+			break;
+		case DLI_PRV0:
+			dli_label = "PRV0";
+			break;
+		case DLI_PRV1:
+			dli_label = "PRV1";
+			break;
+		case DLI_PRV2:
+			dli_label = "PRV2";
+			break;
+		case DLI_PRV3:
+			dli_label = "PRV3";
+			break;
+		}
+		str_length = sprintf(pstr, "%s %02x %s\n",
+				     dli_label, (byte) pmsg->drv_id,
+				     (char *) &pmsg[1]);
+		str_msg[0] = str_length;
+		str_msg[1] = 0;
+		file->private_data = str_msg;
+		diva_maint_ack_message(1, &old_irql);
+	} else {
+		str_msg = (int *) file->private_data;
+		pstr = (char *) &str_msg[2];
+		pstr += str_msg[1];	/* head + offset */
+		str_length = str_msg[0] - str_msg[1];	/* length - offset */
+	}
+	str_length = MIN(str_length, count);
 
-  if (!file->private_data) {
-    for (;;) {
-      while ((pmsg = diva_maint_get_message (&size, &old_irql))) {
-        if (!(pmsg->facility == MSG_TYPE_STRING)) {
-          diva_maint_ack_message (1, &old_irql);
-        } else {
-          break;
-        }
-      }
-
-      if (!pmsg) {
-        if (file->f_flags & O_NONBLOCK) {
-          return (-EAGAIN);
-        }
-        interruptible_sleep_on(&msgwaitq);
-        if (signal_pending(current)) {
-          return (-ERESTARTSYS);
-        }
-      } else {
-        break;
-      }
-    }
-    /*
-      The length of message that shoule be read is:
-      pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero
-      */
-    if (!(str_msg = (int*)diva_os_malloc_tbuffer(0, pmsg->data_length + 29 + 2*sizeof(int)))) {
-      diva_maint_ack_message (0, &old_irql);
-      return (-ENOMEM);
-    }
-    pstr = (char*)&str_msg[2];
-
-    switch (pmsg->dli) {
-      case DLI_LOG :
-        dli_label = "LOG";
-        break;
-      case DLI_FTL :
-        dli_label = "FTL";
-        break;
-      case DLI_ERR :
-        dli_label = "ERR";
-        break;
-      case DLI_TRC :
-        dli_label = "TRC";
-        break;
-      case DLI_REG :
-        dli_label = "REG";
-        break;
-      case DLI_MEM :
-        dli_label = "MEM";
-        break;
-      case DLI_SPL :
-        dli_label = "SPL";
-        break;
-      case DLI_IRP :
-        dli_label = "IRP";
-        break;
-      case DLI_TIM :
-        dli_label = "TIM";
-        break;
-      case DLI_TAPI:
-        dli_label = "TAPI";
-        break;
-      case DLI_NDIS:
-        dli_label = "NDIS";
-        break;
-      case DLI_CONN:
-        dli_label = "CONN";
-        break;
-      case DLI_STAT:
-        dli_label = "STAT";
-        break;
-      case DLI_PRV0:
-        dli_label = "PRV0";
-        break;
-      case DLI_PRV1:
-        dli_label = "PRV1";
-        break;
-      case DLI_PRV2:
-        dli_label = "PRV2";
-        break;
-      case DLI_PRV3:
-        dli_label = "PRV3";
-        break;
-    }
-    str_length = sprintf (pstr, "%s %02x %s\n",
-                          dli_label, (byte)pmsg->drv_id, (char*)&pmsg[1]);
-    str_msg[0] = str_length;
-    str_msg[1] = 0;
-    file->private_data = str_msg;
-    diva_maint_ack_message (1, &old_irql);
-  } else {
-    str_msg = (int*)file->private_data;
-    pstr = (char*)&str_msg[2];
-    pstr += str_msg[1]; /* head + offset */
-    str_length = str_msg[0] - str_msg[1]; /* length - offset */
-  }
-  str_length = MIN(str_length, count);
-
-  if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) {
-    diva_os_free_tbuffer(0, str_msg);
-    file->private_data = 0;
-    return (-EFAULT);
-  }
-  str_msg[1] += str_length;
-  if ((str_msg[0] - str_msg[1]) <= 0) {
-    diva_os_free_tbuffer(0, str_msg);
-    file->private_data = 0;
-  }
+	if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) {
+		diva_os_free_tbuffer(0, str_msg);
+		file->private_data = 0;
+		return (-EFAULT);
+	}
+	str_msg[1] += str_length;
+	if ((str_msg[0] - str_msg[1]) <= 0) {
+		diva_os_free_tbuffer(0, str_msg);
+		file->private_data = 0;
+	}
 
-  return (str_length);
+	return (str_length);
 }
 
 static ssize_t
 maint_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-  return (-ENODEV);
-}                                  
-
-static unsigned int
-maint_poll(struct file *file, poll_table * wait)
-{
-  unsigned int mask = 0;
-
-  poll_wait(file, &msgwaitq, wait);
-  mask = POLLOUT | POLLWRNORM;
-  if (file->private_data || diva_dbg_q_length ()) {
-    mask |= POLLIN | POLLRDNORM;
-  }
-  return (mask);
+	return (-ENODEV);
 }
 
-static int
-maint_open(struct inode *ino, struct file *filep)
+static unsigned int maint_poll(struct file *file, poll_table * wait)
 {
-  if (atomic_read(&opened))
-      return(-EBUSY);
-  else
-    atomic_inc(&opened);
+	unsigned int mask = 0;
 
-  filep->private_data = 0;
-
-  return(0);
+	poll_wait(file, &msgwaitq, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (file->private_data || diva_dbg_q_length()) {
+		mask |= POLLIN | POLLRDNORM;
+	}
+	return (mask);
 }
 
-static int
-maint_close(struct inode *ino, struct file *filep)
+static int maint_open(struct inode *ino, struct file *filep)
 {
-  if (filep->private_data) {
-    diva_os_free_tbuffer(0, filep->private_data);
-    filep->private_data = 0;
-  }
+	down(&opened_sem);
+	if (opened) {
+		up(&opened_sem);
+		return (-EBUSY);
+	}
+	opened++;
+	up(&opened_sem);
 
-  atomic_dec(&opened);
-  return(0);
-}
+	filep->private_data = 0;
 
-static int maint_ioctl (struct inode *inode, struct file *file, uint cmd, ulong arg)
-{
-		return(-EINVAL);
+	return (0);
 }
 
-static loff_t
-maint_lseek(struct file *file, loff_t offset, int orig)
+static int maint_close(struct inode *ino, struct file *filep)
 {
-  return(-ESPIPE);
+	if (filep->private_data) {
+		diva_os_free_tbuffer(0, filep->private_data);
+		filep->private_data = 0;
+	}
+
+	down(&opened_sem);
+	opened--;
+	up(&opened_sem);
+	return (0);
 }
 
 /*
  * fops
  */
-static struct file_operations maint_fops =
-{
-	owner:          THIS_MODULE,
-  llseek:         maint_lseek,
-  read:           maint_read,
-  write:          maint_write,
-  poll:           maint_poll,
-  ioctl:          maint_ioctl,
-  open:           maint_open,
-  release:        maint_close,
+static struct file_operations maint_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = maint_read,
+	.write   = maint_write,
+	.poll    = maint_poll,
+	.open    = maint_open,
+	.release = maint_close
 };
 
-static int DIVA_INIT_FUNCTION
-create_maint_proc(void)
+static int DIVA_INIT_FUNCTION create_maint_proc(void)
 {
-  maint_proc_entry = create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR, proc_net_isdn_eicon);
-  if (!maint_proc_entry)
-    return(0);
+	maint_proc_entry =
+	    create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR,
+			      proc_net_isdn_eicon);
+	if (!maint_proc_entry)
+		return (0);
 
-  maint_proc_entry->proc_fops = &maint_fops;   
-  maint_proc_entry->owner = THIS_MODULE;
+	maint_proc_entry->proc_fops = &maint_fops;
+	maint_proc_entry->owner = THIS_MODULE;
 
-  return(1);
+	return (1);
 }
 
-static void
-remove_maint_proc(void)
+static void remove_maint_proc(void)
 {
-  if (maint_proc_entry) {
-    remove_proc_entry("maint", proc_net_isdn_eicon);
-    maint_proc_entry = NULL;
-  }
+	if (maint_proc_entry) {
+		remove_proc_entry("maint", proc_net_isdn_eicon);
+		maint_proc_entry = NULL;
+	}
 }
 
 /*
  * device node operations
  */
-static ssize_t divas_maint_write(struct file * file, const char * buf,
-            size_t count, loff_t *ppos)
+static ssize_t divas_maint_write(struct file *file, const char *buf,
+				 size_t count, loff_t * ppos)
 {
-		return(maint_read_write((char *)buf));
+	return (maint_read_write((char *) buf));
 }
 
-static ssize_t divas_maint_read(struct file * file, char * buf,
-            size_t count, loff_t *ppos)
+static ssize_t divas_maint_read(struct file *file, char *buf,
+				size_t count, loff_t * ppos)
 {
-		return(maint_read_write(buf));
+	return (maint_read_write(buf));
 }
 
-static struct file_operations divas_maint_fops =
-{
-		owner:			THIS_MODULE,
-		llseek:			maint_lseek,
-		read:				divas_maint_read,
-		write:			divas_maint_write,
-		poll:				maint_poll,
-		ioctl:			maint_ioctl,
-		open:				maint_open,
-		release:		maint_close,
+static struct file_operations divas_maint_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = divas_maint_read,
+	.write   = divas_maint_write,
+	.poll    = maint_poll,
+	.open    = maint_open,
+	.release = maint_close
 };
 
 static void divas_maint_unregister_chrdev(void)
 {
-		if (devfs_handle)
-				devfs_unregister (devfs_handle);
-		unregister_chrdev(major, "DivasMAINT");
+	if (devfs_handle)
+		devfs_unregister(devfs_handle);
+	unregister_chrdev(major, "DivasMAINT");
 }
 
 static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
 {
-		if (register_chrdev (major, "DivasMAINT", &divas_maint_fops))
-		{
-				printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME);
-				return(0);
-		}
-		devfs_handle = devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0,
-					S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops, NULL);
+	if (register_chrdev(major, "DivasMAINT", &divas_maint_fops))
+	{
+		printk(KERN_ERR "%s: failed to create /dev entry.\n",
+		       DRIVERLNAME);
+		return (0);
+	}
+	devfs_handle =
+	    devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0,
+			   S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops,
+			   NULL);
 
-		return(1);
+	return (1);
 }
 
 /*
  * wake up reader
  */
-void diva_maint_wakeup_read (void)
+void diva_maint_wakeup_read(void)
 {
-		wake_up_interruptible (&msgwaitq);
+	wake_up_interruptible(&msgwaitq);
 }
 
 /*
@@ -438,46 +446,49 @@
  */
 static int DIVA_INIT_FUNCTION maint_init(void)
 {
-  char tmprev[50];
-  int ret = 0;
-  void* buffer = 0;
-
-  MOD_INC_USE_COUNT;
-
-  do_gettimeofday (&start_time);
-  init_waitqueue_head(&msgwaitq);
-
-  printk(KERN_INFO "%s\n", DRIVERNAME);
-  printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  printk("%s  Build: %s  Major: %d\n", getrev(tmprev), DIVA_BUILD, major);
-
-	if (!divas_maint_register_chrdev())
-	{
-			ret = -EIO;
-			goto out;
+	char tmprev[50];
+	int ret = 0;
+	void *buffer = 0;
+
+	MOD_INC_USE_COUNT;
+
+	do_gettimeofday(&start_time);
+	init_waitqueue_head(&msgwaitq);
+
+	printk(KERN_INFO "%s\n", DRIVERNAME);
+	printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	printk("%s  Build: %s  Major: %d\n", getrev(tmprev), DIVA_BUILD,
+	       major);
+
+	if (!divas_maint_register_chrdev()) {
+		ret = -EIO;
+		goto out;
 	}
-  if (!create_maint_proc()) {
-    printk(KERN_ERR "%s: failed to create proc entry.\n", DRIVERLNAME);
+	if (!create_maint_proc()) {
+		printk(KERN_ERR "%s: failed to create proc entry.\n",
+		       DRIVERLNAME);
 		divas_maint_unregister_chrdev();
-    ret = -EIO;
-    goto out;
-  }
-
-  if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
-    printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME);
-  	remove_maint_proc();
+		ret = -EIO;
+		goto out;
+	}
+
+	if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
+		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
+		       DRIVERLNAME);
+		remove_maint_proc();
 		divas_maint_unregister_chrdev();
-    ret = -EIO;
-    goto out;
-  }
-
-  printk(KERN_INFO "%s: trace buffer = %p - %d kBytes, %s \n",
-         DRIVERLNAME, buffer, buffer_length, (diva_dbg_mem == 0) ? "internal" : "external");
-
-out:
-  MOD_DEC_USE_COUNT;
-  return(ret);  
+		ret = -EIO;
+		goto out;
+	}
+
+	printk(KERN_INFO "%s: trace buffer = %p - %d kBytes, %s \n",
+	       DRIVERLNAME, buffer, buffer_length,
+	       (diva_dbg_mem == 0) ? "internal" : "external");
+
+      out:
+	MOD_DEC_USE_COUNT;
+	return (ret);
 }
 
 /*
@@ -485,13 +496,12 @@
 */
 static void DIVA_EXIT_FUNCTION maint_exit(void)
 {
-  remove_maint_proc();
+	remove_maint_proc();
 	divas_maint_unregister_chrdev();
 	mntfunc_finit();
 
-  printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
+	printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 }
 
 module_init(maint_init);
 module_exit(maint_exit);
-
diff -Nru a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
--- a/drivers/isdn/hardware/eicon/divasfunc.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/divasfunc.c	Sun Nov 17 20:30:14 2002
@@ -21,13 +21,13 @@
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
-extern void DIVA_DIDD_Read (void *, int);
+extern void DIVA_DIDD_Read(void *, int);
 
 extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
 
 #define MAX_DESCRIPTORS  32
 
-extern void diva_run_trap_script (PISDN_ADAPTER IoAdapter, dword ANum);
+extern void diva_run_trap_script(PISDN_ADAPTER IoAdapter, dword ANum);
 extern char *DRIVERRELEASE;
 
 static dword notify_handle;
@@ -37,10 +37,11 @@
 /* --------------------------------------------------------------------------
     MAINT driver connector section
    -------------------------------------------------------------------------- */
-static void no_printf (unsigned char * x ,...)
+static void no_printf(unsigned char *x, ...)
 {
-  /* dummy debug function */
+	/* dummy debug function */
 }
+
 DIVA_DI_PRINTF dprintf = no_printf;
 
 #include "debuglib.c"
@@ -48,67 +49,73 @@
 /*
  * get the adapters serial number
  */
-void
-diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf)
+void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf)
 {
 	int contr = 0;
-			 
-	if ((contr = ((IoAdapter->serialNo & 0xff000000) >> 24)))
-	{
+
+	if ((contr = ((IoAdapter->serialNo & 0xff000000) >> 24))) {
 		sprintf(buf, "%d-%d",
 			IoAdapter->serialNo & 0x00ffffff, contr + 1);
-	}
-	else
-	{
+	} else {
 		sprintf(buf, "%d", IoAdapter->serialNo);
 	}
-} 
+}
 
 /*
  * register a new adapter
  */
-void diva_xdi_didd_register_adapter (int card)
+void diva_xdi_didd_register_adapter(int card)
 {
-  DESCRIPTOR d;
-  IDI_SYNC_REQ req;
+	DESCRIPTOR d;
+	IDI_SYNC_REQ req;
 
-  if (card && ((card-1) < MAX_ADAPTER) &&
-      IoAdapters[card-1] && Requests[card-1]) {
-    d.type = IoAdapters[card-1]->Properties.DescType;
-    d.request  = Requests[card-1];
-    d.channels = IoAdapters[card-1]->Properties.Channels;
-    d.features = IoAdapters[card-1]->Properties.Features;
-    DBG_TRC(("DIDD register A(%d) channels=%d", card, d.channels))
-    /* workaround for different Name in structure */
-    strncpy(IoAdapters[card-1]->Name, IoAdapters[card-1]->Properties.Name,
-            MIN(30, strlen(IoAdapters[card-1]->Properties.Name)));
-    req.didd_remove_adapter.e.Req = 0;
-    req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
-    req.didd_add_adapter.info.descriptor = (void *)&d;
-    DAdapter.request((ENTITY *)&req);
-    if (req.didd_add_adapter.e.Rc != 0xff) {
-      DBG_ERR(("DIDD register A(%d) failed !", card))
-    } else {
-      IoAdapters[card-1]->os_trap_nfy_Fnc = diva_run_trap_script;
-    }
-  }
+	if (card && ((card - 1) < MAX_ADAPTER) &&
+	    IoAdapters[card - 1] && Requests[card - 1]) {
+		d.type = IoAdapters[card - 1]->Properties.DescType;
+		d.request = Requests[card - 1];
+		d.channels = IoAdapters[card - 1]->Properties.Channels;
+		d.features = IoAdapters[card - 1]->Properties.Features;
+		DBG_TRC(("DIDD register A(%d) channels=%d", card,
+			 d.channels))
+		    /* workaround for different Name in structure */
+		    strncpy(IoAdapters[card - 1]->Name,
+			    IoAdapters[card - 1]->Properties.Name, MIN(30,
+								       strlen
+								       (IoAdapters
+									[card
+									 -
+									 1]->
+									Properties.
+									Name)));
+		req.didd_remove_adapter.e.Req = 0;
+		req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
+		req.didd_add_adapter.info.descriptor = (void *) &d;
+		DAdapter.request((ENTITY *) & req);
+		if (req.didd_add_adapter.e.Rc != 0xff) {
+			DBG_ERR(("DIDD register A(%d) failed !", card))
+		} else {
+			IoAdapters[card - 1]->os_trap_nfy_Fnc =
+			    diva_run_trap_script;
+		}
+	}
 }
 
 /*
  * remove an adapter
  */
-void diva_xdi_didd_remove_adapter (int card)
+void diva_xdi_didd_remove_adapter(int card)
 {
-  IDI_SYNC_REQ req;
-  ADAPTER *a = &IoAdapters[card-1]->a;
+	IDI_SYNC_REQ req;
+	ADAPTER *a = &IoAdapters[card - 1]->a;
 
-  IoAdapters[card-1]->os_trap_nfy_Fnc = NULL;
-  DBG_TRC(("DIDD de-register A(%d)", card))
-  req.didd_remove_adapter.e.Req = 0;
-  req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
-  req.didd_remove_adapter.info.p_request = (IDI_CALL)Requests[card-1];
-  DAdapter.request((ENTITY *)&req);
-  memset(&(a->IdTable), 0x00, 256);
+	IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
+	DBG_TRC(("DIDD de-register A(%d)", card))
+	req.didd_remove_adapter.e.Req = 0;
+	req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
+	req.didd_remove_adapter.info.p_request =
+	    (IDI_CALL) Requests[card - 1];
+	DAdapter.request((ENTITY *) & req);
+	memset(&(a->IdTable), 0x00, 256);
 }
 
 /*
@@ -116,45 +123,42 @@
  */
 static void start_dbg(void)
 {
-  DbgRegister("DIVAS", DRIVERRELEASE, DBG_DEFAULT);
-  DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)",
-    DIVA_BUILD, diva_xdi_common_code_build, __DATE__, __TIME__))
-}
+	DbgRegister("DIVAS", DRIVERRELEASE, DBG_DEFAULT);
+	DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)",
+		 DIVA_BUILD, diva_xdi_common_code_build, __DATE__,
+		 __TIME__))}
 
 /*
  * stop debug
  */
 static void stop_dbg(void)
 {
-		DbgDeregister();
-		memset(&MAdapter, 0, sizeof(MAdapter));
-		dprintf = no_printf;
+	DbgDeregister();
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
 
 /*
  * didd callback function
  */
-static void * didd_callback(void *context, DESCRIPTOR* adapter, int removal)
+static void *didd_callback(void *context, DESCRIPTOR * adapter,
+			   int removal)
 {
-  if (adapter->type == IDI_DADAPTER)
-  {
-    DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
-		return(NULL);
-  }
-
-  if (adapter->type == IDI_DIMAINT)
-  {
-    if (removal)
-    {
-				stop_dbg();
-    }
-    else
-    {
-      memcpy(&MAdapter, adapter, sizeof(MAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      start_dbg();
-    }
-  }  return(NULL);
+	if (adapter->type == IDI_DADAPTER) {
+		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
+		return (NULL);
+	}
+
+	if (adapter->type == IDI_DIMAINT) {
+		if (removal) {
+			stop_dbg();
+		} else {
+			memcpy(&MAdapter, adapter, sizeof(MAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			start_dbg();
+		}
+	}
+	return (NULL);
 }
 
 /*
@@ -162,45 +166,40 @@
  */
 static int DIVA_INIT_FUNCTION connect_didd(void)
 {
-  int x = 0;
-  int dadapter = 0;
-  IDI_SYNC_REQ req;
-  DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
-
-  DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
-
-  for (x = 0; x < MAX_DESCRIPTORS; x++)
-  {
-    if (DIDD_Table[x].type == IDI_DADAPTER)
-    {  /* DADAPTER found */
-      dadapter = 1;
-      memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      req.didd_notify.e.Req = 0;
-      req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
-      req.didd_notify.info.callback = didd_callback;
-      req.didd_notify.info.context = 0;
-      DAdapter.request((ENTITY *)&req);
-      if (req.didd_notify.e.Rc != 0xff)
-			{
-					stop_dbg();
-					return(0);
+	int x = 0;
+	int dadapter = 0;
+	IDI_SYNC_REQ req;
+	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
+	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
+			dadapter = 1;
+			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			req.didd_notify.e.Req = 0;
+			req.didd_notify.e.Rc =
+			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
+			req.didd_notify.info.callback = didd_callback;
+			req.didd_notify.info.context = 0;
+			DAdapter.request((ENTITY *) & req);
+			if (req.didd_notify.e.Rc != 0xff) {
+				stop_dbg();
+				return (0);
 			}
-      notify_handle = req.didd_notify.info.handle;
-    } 
-    else if (DIDD_Table[x].type == IDI_DIMAINT)
-    {  /* MAINT found */
-      memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      start_dbg();
-    }
-  }
+			notify_handle = req.didd_notify.info.handle;
+		} else if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
+			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			start_dbg();
+		}
+	}
 
-	if (!dadapter)
-	{
-			stop_dbg();
+	if (!dadapter) {
+		stop_dbg();
 	}
-	
-  return(dadapter);
+
+	return (dadapter);
 }
 
 /*
@@ -208,14 +207,14 @@
  */
 static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 {
-  IDI_SYNC_REQ req;
+	IDI_SYNC_REQ req;
 
 	stop_dbg();
 
-  req.didd_notify.e.Req = 0;
-  req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
-  req.didd_notify.info.handle = notify_handle;
-  DAdapter.request((ENTITY *)&req);
+	req.didd_notify.e.Req = 0;
+	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
+	req.didd_notify.info.handle = notify_handle;
+	DAdapter.request((ENTITY *) & req);
 }
 
 /*
@@ -223,14 +222,14 @@
  */
 int DIVA_INIT_FUNCTION divasfunc_init(void)
 {
-  if(!connect_didd()) {
-    DBG_ERR(("divasfunc: failed to connect to DIDD."))
-    return(0);
-  }
+	if (!connect_didd()) {
+		DBG_ERR(("divasfunc: failed to connect to DIDD."))
+		return (0);
+	}
 
-  divasa_xdi_driver_entry ();
+	divasa_xdi_driver_entry();
 
-  return(1);  
+	return (1);
 }
 
 /*
@@ -238,7 +237,6 @@
  */
 void DIVA_EXIT_FUNCTION divasfunc_exit(void)
 {
-  divasa_xdi_driver_unload ();
-  disconnect_didd ();
+	divasa_xdi_driver_unload();
+	disconnect_didd();
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
--- a/drivers/isdn/hardware/eicon/divasi.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/hardware/eicon/divasi.c	Sun Nov 17 20:30:12 2002
@@ -1,10 +1,10 @@
-/* $Id: divasi.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: divasi.c,v 1.1.2.7 2001/05/01 15:48:05 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * User Mode IDI Interface 
  *
- * Copyright 2000,2001 by Armin Schindler (mac@melware.de)
- * Copyright 2000,2001 Cytronics & Melware (info@melware.de)
+ * Copyright 2000-2002 by Armin Schindler (mac@melware.de)
+ * Copyright 2000-2002 Cytronics & Melware (info@melware.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -30,13 +30,13 @@
 
 EXPORT_NO_SYMBOLS;
 
-static char *main_revision = "$Revision: 1.1.2.2 $";
+static char *main_revision = "$Revision: 1.1.2.7 $";
 
 static int major = 242;
 
-MODULE_DESCRIPTION(             "User IDI Interface for Eicon ISDN cards");
-MODULE_AUTHOR(                  "Cytronics & Melware, Eicon Networks");
-MODULE_SUPPORTED_DEVICE(        "DIVA card driver");
+MODULE_DESCRIPTION("User IDI Interface for Eicon ISDN cards");
+MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
+MODULE_SUPPORTED_DEVICE("DIVA card driver");
 MODULE_LICENSE("GPL");
 MODULE_PARM(major, "i");
 MODULE_PARM_DESC(major, "Major number for /dev/DivasIDI");
@@ -44,7 +44,7 @@
 typedef struct _diva_um_idi_os_context {
 	wait_queue_head_t read_wait;
 	wait_queue_head_t close_wait;
-	struct  timer_list diva_timer_id;
+	struct timer_list diva_timer_id;
 	int aborted;
 } diva_um_idi_os_context_t;
 
@@ -60,53 +60,53 @@
 /*
  *  helper functions
  */
-static char *
-getrev(const char *revision)
+static char *getrev(const char *revision)
 {
-  char *rev;
-  char *p;
-  if ((p = strchr(revision, ':'))) {
-     rev = p + 2;
-     p = strchr(rev, '$');
-     *--p = 0;
-  } else rev = "1.0";
-  return rev;
+	char *rev;
+	char *p;
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "1.0";
+	return rev;
 }
 
 /*
  *  LOCALS
  */
-static loff_t um_idi_lseek (struct file *file, loff_t offset, int orig);
-static ssize_t um_idi_read (struct file *file, char *buf, size_t count, loff_t *offset);
-static ssize_t um_idi_write (struct file *file, const char *buf, size_t count, loff_t *offset);
-static unsigned int um_idi_poll (struct file *file, poll_table *wait);
-static int um_idi_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int um_idi_open (struct inode *inode, struct file *file);
-static int um_idi_release (struct inode *inode, struct file *file);
-static int remove_entity (void* entity);
-static void diva_um_timer_function (unsigned long data);
+static ssize_t um_idi_read(struct file *file, char *buf, size_t count,
+			   loff_t * offset);
+static ssize_t um_idi_write(struct file *file, const char *buf,
+			    size_t count, loff_t * offset);
+static unsigned int um_idi_poll(struct file *file, poll_table * wait);
+static int um_idi_open(struct inode *inode, struct file *file);
+static int um_idi_release(struct inode *inode, struct file *file);
+static int remove_entity(void *entity);
+static void diva_um_timer_function(unsigned long data);
 
 /*
  * malloc
  */
-void* diva_os_malloc (unsigned long flags, unsigned long size)
+void *diva_os_malloc(unsigned long flags, unsigned long size)
 {
-  void* ret = NULL;
+	void *ret = NULL;
 
-  if (size) {
-      ret = (void*)vmalloc ((unsigned int)size);
-  }
-  return (ret);
+	if (size) {
+		ret = (void *) vmalloc((unsigned int) size);
+	}
+	return (ret);
 }
 
 /*
  * free
  */
-void diva_os_free (unsigned long unused, void* ptr)
+void diva_os_free(unsigned long unused, void *ptr)
 {
-  if (ptr) {
-    vfree (ptr);
-  }
+	if (ptr) {
+		vfree(ptr);
+	}
 }
 
 /*
@@ -116,135 +116,136 @@
 static struct proc_dir_entry *um_idi_proc_entry = NULL;
 
 static int
-um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof,
+		 void *data)
 {
-  int len = 0;
-  char tmprev[32];
+	int len = 0;
+	char tmprev[32];
 
-  len += sprintf(page+len, "%s\n", DRIVERNAME);
-  len += sprintf(page+len, "name     : %s\n", DRIVERLNAME);
-  len += sprintf(page+len, "release  : %s\n", DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  len += sprintf(page+len, "revision : %s\n", getrev(tmprev));
-  len += sprintf(page+len, "build    : %s\n", DIVA_BUILD);
+	len += sprintf(page + len, "%s\n", DRIVERNAME);
+	len += sprintf(page + len, "name     : %s\n", DRIVERLNAME);
+	len += sprintf(page + len, "release  : %s\n", DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
+	len += sprintf(page + len, "build    : %s\n", DIVA_BUILD);
 
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
-static int DIVA_INIT_FUNCTION
-create_um_idi_proc(void)
+static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
 {
-  um_idi_proc_entry = create_proc_entry(DRIVERLNAME,
-                     S_IFREG | S_IRUGO | S_IWUSR, proc_net_isdn_eicon);
-  if (!um_idi_proc_entry)
-    return(0);
+	um_idi_proc_entry = create_proc_entry(DRIVERLNAME,
+					      S_IFREG | S_IRUGO | S_IWUSR,
+					      proc_net_isdn_eicon);
+	if (!um_idi_proc_entry)
+		return (0);
 
-  um_idi_proc_entry->read_proc = um_idi_proc_read;
-  um_idi_proc_entry->owner = THIS_MODULE;
+	um_idi_proc_entry->read_proc = um_idi_proc_read;
+	um_idi_proc_entry->owner = THIS_MODULE;
 
-  return(1);
+	return (1);
 }
 
-static void
-remove_um_idi_proc(void)
+static void remove_um_idi_proc(void)
 {
-  if (um_idi_proc_entry) {
-    remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon);
-    um_idi_proc_entry = NULL;
-  }
+	if (um_idi_proc_entry) {
+		remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon);
+		um_idi_proc_entry = NULL;
+	}
 }
 
-static struct file_operations divas_idi_fops =
-{
-	owner:      THIS_MODULE,
-  llseek:      um_idi_lseek,
-  read:        um_idi_read,
-  write:       um_idi_write,
-  poll:        um_idi_poll,
-  ioctl:       um_idi_ioctl,
-  open:        um_idi_open,
-  release:     um_idi_release,
+static struct file_operations divas_idi_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = um_idi_read,
+	.write   = um_idi_write,
+	.poll    = um_idi_poll,
+	.open    = um_idi_open,
+	.release = um_idi_release
 };
 
 static void divas_idi_unregister_chrdev(void)
 {
-		if (devfs_handle)
-				devfs_unregister (devfs_handle);
-		unregister_chrdev(major, "DivasIDI");
+	if (devfs_handle)
+		devfs_unregister(devfs_handle);
+	unregister_chrdev(major, "DivasIDI");
 }
 
 static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
 {
-		if (register_chrdev (major, "DivasIDI", &divas_idi_fops))
-		{
-				printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME);
-				return(0);
-		}
-		devfs_handle = devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0,
-					S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops, NULL);
+	if (register_chrdev(major, "DivasIDI", &divas_idi_fops))
+	{
+		printk(KERN_ERR "%s: failed to create /dev entry.\n",
+		       DRIVERLNAME);
+		return (0);
+	}
+	devfs_handle =
+	    devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0,
+			   S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops,
+			   NULL);
 
-		return(1);
+	return (1);
 }
 
 /*
 ** Driver Load
 */
-static int DIVA_INIT_FUNCTION
-divasi_init(void)
+static int DIVA_INIT_FUNCTION divasi_init(void)
 {
-  char tmprev[50];
-  int ret = 0;
+	char tmprev[50];
+	int ret = 0;
 
-  MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 
-  printk(KERN_INFO "%s\n", DRIVERNAME);
-  printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  printk("%s  Build: %s Major: %d\n", getrev(tmprev), DIVA_BUILD, major);
+	printk(KERN_INFO "%s\n", DRIVERNAME);
+	printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	printk("%s  Build: %s Major: %d\n", getrev(tmprev), DIVA_BUILD,
+	       major);
 
-	if (!divas_idi_register_chrdev())
-	{
-    ret = -EIO;
-    goto out;
+	if (!divas_idi_register_chrdev()) {
+		ret = -EIO;
+		goto out;
 	}
-	
-	if(!create_um_idi_proc()) {
+
+	if (!create_um_idi_proc()) {
 		divas_idi_unregister_chrdev();
-		printk(KERN_ERR "%s: failed to create proc entry.\n", DRIVERLNAME);
+		printk(KERN_ERR "%s: failed to create proc entry.\n",
+		       DRIVERLNAME);
 		ret = -EIO;
 		goto out;
 	}
 
-	if(!(idifunc_init())) {
+	if (!(idifunc_init())) {
 		remove_um_idi_proc();
 		divas_idi_unregister_chrdev();
-		printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME);
+		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
+		       DRIVERLNAME);
 		ret = -EIO;
 		goto out;
 	}
 
-out:
-  MOD_DEC_USE_COUNT;
-  return (ret);
+      out:
+	MOD_DEC_USE_COUNT;
+	return (ret);
 }
 
 
 /*
 ** Driver Unload
 */
-static void DIVA_EXIT_FUNCTION
-divasi_exit(void)
+static void DIVA_EXIT_FUNCTION divasi_exit(void)
 {
 	idifunc_finit();
-  remove_um_idi_proc();
+	remove_um_idi_proc();
 	divas_idi_unregister_chrdev();
 
-  printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
+	printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 }
 
 module_init(divasi_init);
@@ -255,343 +256,349 @@
  *  FILE OPERATIONS
  */
 
-static loff_t
-um_idi_lseek(struct file *file, loff_t offset, int orig)
-{
-  return (-ESPIPE);
-}
-
 static int
-divas_um_idi_copy_to_user (void* os_handle, void* dst, const void* src, int length)
+divas_um_idi_copy_to_user(void *os_handle, void *dst, const void *src,
+			  int length)
 {
-  memcpy (dst, src, length);
-  return (length);
+	memcpy(dst, src, length);
+	return (length);
 }
 
 static ssize_t
-um_idi_read (struct file *file, char *buf, size_t count, loff_t *offset)
+um_idi_read(struct file *file, char *buf, size_t count, loff_t * offset)
 {
-	diva_um_idi_os_context_t* p_os;
+	diva_um_idi_os_context_t *p_os;
 	int ret = -EINVAL;
 	void *data;
 
-  if (!file->private_data) {
-    return (-ENODEV);
-  }
+	if (!file->private_data) {
+		return (-ENODEV);
+	}
 
-	if (!(p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(file->private_data))) {
-			return (-ENODEV);
+	if (!
+	    (p_os =
+	     (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->
+								    private_data)))
+	{
+		return (-ENODEV);
 	}
 	if (p_os->aborted) {
-			return (-ENODEV);
+		return (-ENODEV);
 	}
-	
-  if(!(data = diva_os_malloc(0, count))) {
-    return (-ENOMEM);
-  }
-
-   ret = diva_um_idi_read (file->private_data,
-                           file, data, count,
-                           divas_um_idi_copy_to_user);
-   switch(ret) {
-     case   0 : /* no message available */
-       ret = (-EAGAIN);
-       break;
-     case (-1): /* adapter was removed */
-       ret  = (-ENODEV);
-       break;
-     case (-2): /* message_length > length of user buffer */
-       ret = (-EFAULT);
-       break;
-   }
-
-   if(ret > 0) {
-     if (copy_to_user(buf, data, ret)) {
-       ret = (-EFAULT);
-     }
-   }
-
-  diva_os_free (0, data);
-  DBG_TRC(("read: ret %d", ret));
-  return (ret);
+
+	if (!(data = diva_os_malloc(0, count))) {
+		return (-ENOMEM);
+	}
+
+	ret = diva_um_idi_read(file->private_data,
+			       file, data, count,
+			       divas_um_idi_copy_to_user);
+	switch (ret) {
+	case 0:		/* no message available */
+		ret = (-EAGAIN);
+		break;
+	case (-1):		/* adapter was removed */
+		ret = (-ENODEV);
+		break;
+	case (-2):		/* message_length > length of user buffer */
+		ret = (-EFAULT);
+		break;
+	}
+
+	if (ret > 0) {
+		if (copy_to_user(buf, data, ret)) {
+			ret = (-EFAULT);
+		}
+	}
+
+	diva_os_free(0, data);
+	DBG_TRC(("read: ret %d", ret));
+	return (ret);
 }
 
 
 static int
-divas_um_idi_copy_from_user (void* os_handle, void* dst, const void* src, int length)
+divas_um_idi_copy_from_user(void *os_handle, void *dst, const void *src,
+			    int length)
 {
-  memcpy(dst, src, length);
-  return (length);
+	memcpy(dst, src, length);
+	return (length);
 }
 
-static int
-um_idi_open_adapter(struct file *file, int adapter_nr)
+static int um_idi_open_adapter(struct file *file, int adapter_nr)
 {
-  diva_um_idi_os_context_t* p_os;
-  void* e = divas_um_idi_create_entity ((dword)adapter_nr, (void*)file);
+	diva_um_idi_os_context_t *p_os;
+	void *e =
+	    divas_um_idi_create_entity((dword) adapter_nr, (void *) file);
 
-  if (!(file->private_data = e)) {
-    return (0);
-  }
-  p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(e);
-  init_waitqueue_head(&p_os->read_wait);
-  init_waitqueue_head(&p_os->close_wait);
-	init_timer (&p_os->diva_timer_id);
-	p_os->diva_timer_id.function = (void *)diva_um_timer_function;
-	p_os->diva_timer_id.data     = (unsigned long)p_os;
+	if (!(file->private_data = e)) {
+		return (0);
+	}
+	p_os = (diva_um_idi_os_context_t *) diva_um_id_get_os_context(e);
+	init_waitqueue_head(&p_os->read_wait);
+	init_waitqueue_head(&p_os->close_wait);
+	init_timer(&p_os->diva_timer_id);
+	p_os->diva_timer_id.function = (void *) diva_um_timer_function;
+	p_os->diva_timer_id.data = (unsigned long) p_os;
 	p_os->aborted = 0;
-  return (1);
+	return (1);
 }
 
 static ssize_t
-um_idi_write (struct file *file, const char *buf, size_t count, loff_t *offset)
+um_idi_write(struct file *file, const char *buf, size_t count,
+	     loff_t * offset)
 {
-	diva_um_idi_os_context_t* p_os;
+	diva_um_idi_os_context_t *p_os;
 	int ret = -EINVAL;
 	void *data;
 	int adapter_nr = 0;
 
-  if (!file->private_data) {
+	if (!file->private_data) {
 		/* the first write() selects the adapter_nr */
 		if (count == sizeof(int)) {
-				if (copy_from_user((void *)&adapter_nr, buf, count))
-						return(-EFAULT);
-				if (!(um_idi_open_adapter(file, adapter_nr)))
-						return(-ENODEV);
-				return(count);
+			if (copy_from_user
+			    ((void *) &adapter_nr, buf,
+			     count)) return (-EFAULT);
+			if (!(um_idi_open_adapter(file, adapter_nr)))
+				return (-ENODEV);
+			return (count);
 		} else
-		    return (-ENODEV);
-  }
-
-	if (!(p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(file->private_data))) {
 			return (-ENODEV);
 	}
+
+	if (!(p_os =
+	     (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->
+								    private_data)))
+	{
+		return (-ENODEV);
+	}
 	if (p_os->aborted) {
-			return (-ENODEV);
+		return (-ENODEV);
 	}
-	
-  if(!(data = diva_os_malloc(0, count))) {
-    return (-ENOMEM);
-  }
-
-  if (copy_from_user(data, buf, count)) {
-    ret = -EFAULT;
-  }	else {
-    ret = diva_um_idi_write (file->private_data,
-                               file, data, count,
-                               divas_um_idi_copy_from_user);
-    switch (ret) {
-      case   0 : /* no space available */
-        ret = (-EAGAIN);
-        break;
-      case (-1): /* adapter was removed */
-        ret = (-ENODEV);
-        break;
-      case (-2): /* length of user buffer > max message_length */
-        ret = (-EFAULT);
-        break;
-    }
-  }
-  diva_os_free (0, data);
-  DBG_TRC(("write: ret %d", ret));
-  return (ret);
-}
-
-static unsigned int
-um_idi_poll (struct file *file, poll_table *wait)
-{
-  diva_um_idi_os_context_t* p_os;
-
-  if (!file->private_data) {
-    return (POLLERR);
-  }
-
-	if ((!(p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context (file->private_data))) ||
-		p_os->aborted) {
-			return (POLLERR);
+
+	if (!(data = diva_os_malloc(0, count))) {
+		return (-ENOMEM);
 	}
 
-  poll_wait (file, &p_os->read_wait, wait);
+	if (copy_from_user(data, buf, count)) {
+		ret = -EFAULT;
+	} else {
+		ret = diva_um_idi_write(file->private_data,
+					file, data, count,
+					divas_um_idi_copy_from_user);
+		switch (ret) {
+		case 0:	/* no space available */
+			ret = (-EAGAIN);
+			break;
+		case (-1):	/* adapter was removed */
+			ret = (-ENODEV);
+			break;
+		case (-2):	/* length of user buffer > max message_length */
+			ret = (-EFAULT);
+			break;
+		}
+	}
+	diva_os_free(0, data);
+	DBG_TRC(("write: ret %d", ret));
+	return (ret);
+}
 
-	if (p_os->aborted) {
-			return (POLLERR);
+static unsigned int um_idi_poll(struct file *file, poll_table * wait)
+{
+	diva_um_idi_os_context_t *p_os;
+
+	if (!file->private_data) {
+		return (POLLERR);
 	}
 
-  switch (diva_user_mode_idi_ind_ready (file->private_data, file)) {
-    case (-1):
-      return (POLLERR);
+	if ((!(p_os =
+	       (diva_um_idi_os_context_t *)
+	       diva_um_id_get_os_context(file->private_data)))
+	    || p_os->aborted) {
+		return (POLLERR);
+	}
 
-    case 0:
-      return (0);
-  }
+	poll_wait(file, &p_os->read_wait, wait);
 
-  return (POLLIN | POLLRDNORM);
-}
+	if (p_os->aborted) {
+		return (POLLERR);
+	}
 
-static int 
-um_idi_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-  return (-EINVAL);
+	switch (diva_user_mode_idi_ind_ready(file->private_data, file)) {
+	case (-1):
+		return (POLLERR);
+
+	case 0:
+		return (0);
+	}
+
+	return (POLLIN | POLLRDNORM);
 }
 
-static int
-um_idi_open (struct inode *inode, struct file *file)
+static int um_idi_open(struct inode *inode, struct file *file)
 {
-  return (0);
+	return (0);
 }
 
 
-static int
-um_idi_release (struct inode *inode, struct file *file)
+static int um_idi_release(struct inode *inode, struct file *file)
 {
-  unsigned int adapter_nr = minor(inode->i_rdev);
-  int ret = 0;
+	unsigned int adapter_nr = minor(inode->i_rdev);
+	int ret = 0;
 
-  if (!(file->private_data)) {
-    ret = -ENODEV;
-    goto out;
-  }
+	if (!(file->private_data)) {
+		ret = -ENODEV;
+		goto out;
+	}
 
-  if ((ret = remove_entity (file->private_data))) {
-    goto out;
-  }
+	if ((ret = remove_entity(file->private_data))) {
+		goto out;
+	}
 
-  if (divas_um_idi_delete_entity ((int)adapter_nr, file->private_data)) {
-    ret = -ENODEV;
-    goto out;
-  }
+	if (divas_um_idi_delete_entity
+	    ((int) adapter_nr, file->private_data)) {
+		ret = -ENODEV;
+		goto out;
+	}
 
-out:
-  return(ret);
+      out:
+	return (ret);
 }
 
-int
-diva_os_get_context_size (void)
+int diva_os_get_context_size(void)
 {
-  return (sizeof(diva_um_idi_os_context_t));
+	return (sizeof(diva_um_idi_os_context_t));
 }
 
-void
-diva_os_wakeup_read (void* os_context)
+void diva_os_wakeup_read(void *os_context)
 {
-  diva_um_idi_os_context_t* p_os = (diva_um_idi_os_context_t*)os_context;
-  wake_up_interruptible (&p_os->read_wait);
+	diva_um_idi_os_context_t *p_os =
+	    (diva_um_idi_os_context_t *) os_context;
+	wake_up_interruptible(&p_os->read_wait);
 }
 
-void
-diva_os_wakeup_close (void* os_context)
+void diva_os_wakeup_close(void *os_context)
 {
-  diva_um_idi_os_context_t* p_os = (diva_um_idi_os_context_t*)os_context;
-  wake_up_interruptible (&p_os->close_wait);
+	diva_um_idi_os_context_t *p_os =
+	    (diva_um_idi_os_context_t *) os_context;
+	wake_up_interruptible(&p_os->close_wait);
 }
 
 static
-void diva_um_timer_function (unsigned long data)
+void diva_um_timer_function(unsigned long data)
 {
-		diva_um_idi_os_context_t* p_os = (diva_um_idi_os_context_t*)data;
+	diva_um_idi_os_context_t *p_os = (diva_um_idi_os_context_t *) data;
 
-		p_os->aborted = 1;
-		wake_up_interruptible (&p_os->read_wait);
-		wake_up_interruptible (&p_os->close_wait);
-		DBG_ERR(("entity removal watchdog"))
+	p_os->aborted = 1;
+	wake_up_interruptible(&p_os->read_wait);
+	wake_up_interruptible(&p_os->close_wait);
+	DBG_ERR(("entity removal watchdog"))
 }
 
 /*
 **  If application exits without entity removal this function will remove
 **  entity and block until removal is complete
 */
-static int
-remove_entity (void* entity)
+static int remove_entity(void *entity)
 {
-  struct task_struct *curtask = current;
-  diva_um_idi_os_context_t* p_os;
+	struct task_struct *curtask = current;
+	diva_um_idi_os_context_t *p_os;
 
-	diva_um_idi_stop_wdog (entity);
+	diva_um_idi_stop_wdog(entity);
 
 	if (!entity) {
-			DBG_FTL(("Zero entity on remove"))
-			return (0);
+		DBG_FTL(("Zero entity on remove"))
+		return (0);
 	}
 
-	if (!(p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(entity))) {
-			DBG_FTL(("Zero entity os context on remove"))
-			return (0);
+	if (!(p_os =
+	     (diva_um_idi_os_context_t *)
+	     diva_um_id_get_os_context(entity))) {
+		DBG_FTL(("Zero entity os context on remove"))
+		return (0);
 	}
 
 	if (!divas_um_idi_entity_assigned(entity) || p_os->aborted) {
-			/*
-				Entity is not assigned, also can be removed
-				*/
-			return (0);
+		/*
+		   Entity is not assigned, also can be removed
+		 */
+		return (0);
 	}
 
 	DBG_TRC(("E(%08x) check remove", entity))
 
 	/*
-		If adapter not answers on remove request inside of
-		10 Sec, then adapter is dead
-		*/
-	diva_um_idi_start_wdog (entity);
+	   If adapter not answers on remove request inside of
+	   10 Sec, then adapter is dead
+	 */
+	diva_um_idi_start_wdog(entity);
 
 	{
-			DECLARE_WAITQUEUE(wait, curtask);
+		DECLARE_WAITQUEUE(wait, curtask);
 
-			add_wait_queue (&p_os->close_wait, &wait);
-			for (;;) {
-					set_current_state(TASK_INTERRUPTIBLE);
-					if (!divas_um_idi_entity_start_remove (entity) || p_os->aborted) {
-							break;
-					}
-					schedule();
+		add_wait_queue(&p_os->close_wait, &wait);
+		for (;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!divas_um_idi_entity_start_remove(entity)
+			    || p_os->aborted) {
+				break;
 			}
-			set_current_state(TASK_RUNNING);
-  		remove_wait_queue (&p_os->close_wait, &wait);
+			schedule();
+		}
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&p_os->close_wait, &wait);
 	}
 
 	DBG_TRC(("E(%08x) start remove", entity))
-
 	{
-			DECLARE_WAITQUEUE(wait, curtask);
+		DECLARE_WAITQUEUE(wait, curtask);
 
-			add_wait_queue (&p_os->close_wait, &wait);
-			for (;;) {
-					set_current_state(TASK_INTERRUPTIBLE);
-					if (!divas_um_idi_entity_assigned (entity) || p_os->aborted) {
-							break;
-					}
-					schedule();
+		add_wait_queue(&p_os->close_wait, &wait);
+		for (;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!divas_um_idi_entity_assigned(entity)
+			    || p_os->aborted) {
+				break;
 			}
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue (&p_os->close_wait, &wait);
+			schedule();
+		}
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&p_os->close_wait, &wait);
 	}
 
-	DBG_TRC(("E(%08x) remove complete, aborted:%d", entity, p_os->aborted))
+	DBG_TRC(("E(%08x) remove complete, aborted:%d", entity,
+		 p_os->aborted))
 
-	diva_um_idi_stop_wdog (entity);
+	diva_um_idi_stop_wdog(entity);
 
 	p_os->aborted = 0;
-	
-  return (0);
+
+	return (0);
 }
 
 /*
  * timer watchdog
  */
-void diva_um_idi_start_wdog (void* entity) {
-		diva_um_idi_os_context_t* p_os;
+void diva_um_idi_start_wdog(void *entity)
+{
+	diva_um_idi_os_context_t *p_os;
 
-		if (entity &&
-				((p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(entity)))) {
-			mod_timer (&p_os->diva_timer_id, jiffies + 10*HZ);
-		}
+	if (entity &&
+	    ((p_os =
+	      (diva_um_idi_os_context_t *)
+	      diva_um_id_get_os_context(entity)))) {
+		mod_timer(&p_os->diva_timer_id, jiffies + 10 * HZ);
+	}
 }
 
-void diva_um_idi_stop_wdog (void* entity) {
-		diva_um_idi_os_context_t* p_os;
+void diva_um_idi_stop_wdog(void *entity)
+{
+	diva_um_idi_os_context_t *p_os;
 
-		if (entity &&
-				((p_os = (diva_um_idi_os_context_t*)diva_um_id_get_os_context(entity)))) {
-			del_timer (&p_os->diva_timer_id);
-		}
+	if (entity &&
+	    ((p_os =
+	      (diva_um_idi_os_context_t *)
+	      diva_um_id_get_os_context(entity)))) {
+		del_timer(&p_os->diva_timer_id);
+	}
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
--- a/drivers/isdn/hardware/eicon/divasmain.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/isdn/hardware/eicon/divasmain.c	Sun Nov 17 20:30:03 2002
@@ -1,4 +1,4 @@
-/* $Id: divasmain.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: divasmain.c,v 1.1.2.8 2001/05/01 15:48:05 armin Exp $
  *
  * Low level driver for Eicon DIVA Server ISDN cards.
  *
@@ -46,22 +46,24 @@
 #include "diva_dma.h"
 
 EXPORT_NO_SYMBOLS;
-static char *main_revision = "$Revision: 1.1.2.2 $";
+static char *main_revision = "$Revision: 1.1.2.8 $";
 
 int errno = 0;
 static int major = 240;
 
-MODULE_DESCRIPTION( "Kernel driver for Eicon DIVA Server cards");
-MODULE_AUTHOR(      "Cytronics & Melware, Eicon Networks");
+MODULE_DESCRIPTION("Kernel driver for Eicon DIVA Server cards");
+MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
 MODULE_LICENSE("GPL");
 MODULE_PARM(major, "i");
 MODULE_PARM_DESC(major, "Major number for /dev/Divas");
 
-static char *DRIVERNAME = "Eicon DIVA Server driver (http://www.melware.net)";
+static char *DRIVERNAME =
+    "Eicon DIVA Server driver (http://www.melware.net)";
 static char *DRIVERLNAME = "divas";
 char *DRIVERRELEASE = "2.0";
 
-extern void diva_os_irq_wrapper (int irq, void* context, struct pt_regs* regs);
+extern void diva_os_irq_wrapper(int irq, void *context,
+				struct pt_regs *regs);
 extern int create_divas_proc(void);
 extern void remove_divas_proc(void);
 extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);
@@ -72,9 +74,9 @@
 
 typedef struct _diva_os_thread_dpc {
 	struct tasklet_struct divas_task;
-  diva_os_soft_isr_t*   psoft_isr;
-	struct work_struct      trap_script_task;
-  int                   card_failed;
+	struct work_struct trap_script_task;
+	diva_os_soft_isr_t *psoft_isr;
+	int card_failed;
 } diva_os_thread_dpc_t;
 
 /* --------------------------------------------------------------------------
@@ -89,17 +91,6 @@
   driver_data	Data private to the driver.
   */
 
-/*
-  List should be sorted
-  */
-#if !defined(PCI_DEVICE_ID_EICON_4BRI)
-#define PCI_DEVICE_ID_EICON_4BRI             0xE012
-#endif
-
-#if !defined(PCI_DEVICE_ID_EICON_4BRI_2)
-#define PCI_DEVICE_ID_EICON_4BRI_2           0xE013
-#endif
-
 #if !defined(PCI_DEVICE_ID_EICON_MAESTRAP_2)
 #define PCI_DEVICE_ID_EICON_MAESTRAP_2       0xE015
 #endif
@@ -133,129 +124,123 @@
   */
 static struct pci_device_id divas_pci_tbl[] __devinitdata = {
 /* Diva Server BRI-2M PCI 0xE010 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRA,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_MAESTRA_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_MAESTRA_PCI},
 /* Diva Server 4BRI-8M PCI 0xE012 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_PCI},
 /* Diva Server 4BRI-8M 2.0 PCI 0xE013 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_2,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_V2_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ_U,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_V2_PCI},
 /* Diva Server PRI-30M PCI 0xE014 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_PCI},
 /* Diva Server PRI 2.0 adapter 0xE015 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_V2_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_V2_PCI},
 /* Diva Server Voice 4BRI-8M PCI 0xE016 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_VOIP,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_VOIP,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_PCI},
 /* Diva Server Voice 4BRI-8M 2.0 PCI 0xE017 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_2_VOIP,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_2_VOIP,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI},
 /* Diva Server BRI-2M 2.0 PCI 0xE018 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2M_V2_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2M_V2_PCI},
 /* Diva Server Voice PRI 2.0 PCI 0xE019 */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	 CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI},
 /* Diva Server 2FX 0xE01A */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_2F,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2F_PCI },
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_2F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2F_PCI},
 /* Diva Server Voice BRI-2M 2.0 PCI 0xE01B */
-  { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2_VOIP,
-    PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI },
-  {0,}  /* 0 terminated list. */
+	{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2_VOIP,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI},
+	{0,}			/* 0 terminated list. */
 };
 MODULE_DEVICE_TABLE(pci, divas_pci_tbl);
 
-static int divas_init_one (struct pci_dev *pdev,
-                           const struct pci_device_id *ent);
-static void divas_remove_one (struct pci_dev *pdev);
+static int divas_init_one(struct pci_dev *pdev,
+			  const struct pci_device_id *ent);
+static void divas_remove_one(struct pci_dev *pdev);
 
 static struct pci_driver diva_pci_driver = {
-  name:     "divas",
-  probe:    divas_init_one,
-  remove:   divas_remove_one,
-  id_table: divas_pci_tbl,
+	.name     = "divas",
+	.probe    = divas_init_one,
+	.remove   = divas_remove_one,
+	.id_table = divas_pci_tbl,
 };
 
 /*********************************************************
  ** little helper functions
  *********************************************************/
-static char *
-getrev(const char *revision)
+static char *getrev(const char *revision)
 {
-        char *rev;
-        char *p;
-        if ((p = strchr(revision, ':'))) {
-                rev = p + 2;
-                p = strchr(rev, '$');
-                *--p = 0;
-        } else rev = "1.0";
-        return rev;
-} 
+	char *rev;
+	char *p;
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else
+		rev = "1.0";
+	return rev;
+}
 
-void
-diva_os_sleep (dword mSec)
+void diva_os_sleep(dword mSec)
 {
-  unsigned long timeout = HZ * mSec / 1000 + 1;
+	unsigned long timeout = HZ * mSec / 1000 + 1;
 
-  set_current_state(TASK_UNINTERRUPTIBLE);
-  schedule_timeout(timeout);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(timeout);
 }
 
-void
-diva_os_wait (dword mSec)
+void diva_os_wait(dword mSec)
 {
-  mdelay (mSec);
-} 
+	mdelay(mSec);
+}
 
-void
-diva_log_info(unsigned char * format, ...)
+void diva_log_info(unsigned char *format, ...)
 {
-  va_list args;
-  unsigned char line[160];
+	va_list args;
+	unsigned char line[160];
 
-  va_start(args, format);
-  vsprintf(line, format, args);  
-  va_end(args);
+	va_start(args, format);
+	vsprintf(line, format, args);
+	va_end(args);
 
-  printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line);
+	printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line);
 }
 
-void
-divas_get_version(char *p)
+void divas_get_version(char *p)
 {
-  char tmprev[32];
+	char tmprev[32];
 
-  strcpy(tmprev, main_revision);
-  sprintf(p, "%s: %s(%s) %s(%s)\n", DRIVERLNAME, DRIVERRELEASE,
-                          getrev(tmprev),
-                          diva_xdi_common_code_build,
-                          DIVA_BUILD);
+	strcpy(tmprev, main_revision);
+	sprintf(p, "%s: %s(%s) %s(%s)\n", DRIVERLNAME, DRIVERRELEASE,
+		getrev(tmprev), diva_xdi_common_code_build, DIVA_BUILD);
 }
 
 /*********************************************************
  ** malloc / free
  *********************************************************/
 
-void* diva_os_malloc (unsigned long flags, unsigned long size)
+void *diva_os_malloc(unsigned long flags, unsigned long size)
 {
-  void* ret = NULL;
- 
-  if (size) {
-      ret = (void*)vmalloc ((unsigned int)size);
-  }
-  return (ret);
-}
-
-void
-diva_os_free (unsigned long unused, void* ptr)
-{
-  if (ptr) {
-    vfree (ptr);
-  }
+	void *ret = NULL;
+
+	if (size) {
+		ret = (void *) vmalloc((unsigned int) size);
+	}
+	return (ret);
+}
+
+void diva_os_free(unsigned long unused, void *ptr)
+{
+	if (ptr) {
+		vfree(ptr);
+	}
 }
 
 /* --------------------------------------------------------------------------
@@ -263,232 +248,258 @@
    -------------------------------------------------------------------------- */
 #define TRAP_PROG  "/usr/sbin/divas_trap.rc"
 
-static void diva_adapter_trapped (void* context) {
-  diva_os_thread_dpc_t* pdpc = (diva_os_thread_dpc_t*)context;
+static void diva_adapter_trapped(void *context)
+{
+	diva_os_thread_dpc_t *pdpc = (diva_os_thread_dpc_t *) context;
 
-  if (pdpc && pdpc->card_failed) {
-    char * envp[] = { "HOME=/",
-                      "TERM=linux",
-                      "PATH=/usr/sbin:/sbin:/bin:/usr/bin", 0 };
-    char *argv[] = { TRAP_PROG, "trap", 0, 0 };
-    char adapter[8];
-    int ret;
-
-    sprintf (adapter, "%d", pdpc->card_failed-1);
-    pdpc->card_failed = 0;
-    argv[2] = &adapter[0];
-
-    ret = call_usermodehelper (argv[0], argv, envp);
-
-    if (ret) {
-      printk(KERN_ERR "%s: couldn't start trap script, errno %d\n",
-            DRIVERLNAME, ret);
-    }
-  }
+	if (pdpc && pdpc->card_failed) {
+		char *envp[] = { "HOME=/",
+			"TERM=linux",
+			"PATH=/usr/sbin:/sbin:/bin:/usr/bin", 0
+		};
+		char *argv[] = { TRAP_PROG, "trap", 0, 0 };
+		char adapter[8];
+		int ret;
+
+		sprintf(adapter, "%d", pdpc->card_failed - 1);
+		pdpc->card_failed = 0;
+		argv[2] = &adapter[0];
+
+		ret = call_usermodehelper(argv[0], argv, envp);
+
+		if (ret) {
+			printk(KERN_ERR
+			       "%s: couldn't start trap script, errno %d\n",
+			       DRIVERLNAME, ret);
+		}
+	}
 }
 
 /*
  * run the trap script
  */
-void diva_run_trap_script (PISDN_ADAPTER IoAdapter, dword ANum)
+void diva_run_trap_script(PISDN_ADAPTER IoAdapter, dword ANum)
 {
-  diva_os_soft_isr_t* psoft_isr  = &IoAdapter->isr_soft_isr;
-  diva_os_thread_dpc_t* context = (diva_os_thread_dpc_t*)psoft_isr->object;
-
-  if (context && !context->card_failed) {
-    context->card_failed = ANum+1;
-    schedule_work(&context->trap_script_task);
+	diva_os_soft_isr_t *psoft_isr = &IoAdapter->isr_soft_isr;
+	diva_os_thread_dpc_t *context =
+	    (diva_os_thread_dpc_t *) psoft_isr->object;
+
+	if (context && !context->card_failed) {
+		context->card_failed = ANum + 1;
+		schedule_work(&context->trap_script_task);
 	}
 }
 
 /* --------------------------------------------------------------------------
     PCI Bus services  
    -------------------------------------------------------------------------- */
-byte diva_os_get_pci_bus (void* pci_dev_handle)
+byte diva_os_get_pci_bus(void *pci_dev_handle)
 {
-  struct pci_dev *pdev = (struct pci_dev*)pci_dev_handle;
-  return ((byte)pdev->bus->number);
+	struct pci_dev *pdev = (struct pci_dev *) pci_dev_handle;
+	return ((byte) pdev->bus->number);
 }
 
-byte diva_os_get_pci_func (void* pci_dev_handle)
+byte diva_os_get_pci_func(void *pci_dev_handle)
 {
-  struct pci_dev *pdev = (struct pci_dev*)pci_dev_handle;
-  return ((byte)pdev->devfn);
+	struct pci_dev *pdev = (struct pci_dev *) pci_dev_handle;
+	return ((byte) pdev->devfn);
 }
 
-unsigned long divasa_get_pci_irq (unsigned char bus, unsigned char func, void* pci_dev_handle)
+unsigned long divasa_get_pci_irq(unsigned char bus, unsigned char func,
+				 void *pci_dev_handle)
 {
-  unsigned char irq = 0;
-  struct pci_dev	*dev = (struct pci_dev*)pci_dev_handle;
+	unsigned char irq = 0;
+	struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
 
 	irq = dev->irq;
- 
-  return ((unsigned long)irq);
-} 
-
-unsigned long divasa_get_pci_bar (unsigned char bus, unsigned char func, int bar, void* pci_dev_handle)
-{
-  unsigned long ret = 0;
-  struct pci_dev	*dev = (struct pci_dev*)pci_dev_handle;
-
-  if (bar < 6) {
-    ret = dev->resource[bar].start;
-  }
-
-  DBG_TRC(("GOT BAR[%d]=%08x", bar, ret));
-
-  {
-    unsigned long type = (ret & 0x00000001);
-    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
-        DBG_TRC(("  I/O"));
-        ret &= PCI_BASE_ADDRESS_IO_MASK;
-    } else {
-        DBG_TRC(("  memory"));
-        ret &= PCI_BASE_ADDRESS_MEM_MASK;
-    }
-    DBG_TRC(("  final=%08x", ret));  
-  }
-
-  return(ret);
-}
-
-void PCIwrite (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle)
-{
-  struct pci_dev	*dev = (struct pci_dev*)pci_dev_handle;
-
-  switch (length) {
-      case 1: /* byte */
-          pci_write_config_byte (dev, offset, *(unsigned char*)data);
-          break;
-      case 2: /* word */
-          pci_write_config_word (dev, offset, *(unsigned short*)data);
-          break;
-      case 4: /* dword */
-          pci_write_config_dword (dev, offset, *(unsigned int*)data);
-          break;
- 
-      default: /* buffer */
-          if (!(length % 4) && !(length & 0x03)) { /* Copy as dword */ 
-            dword* p = (dword*) data;
-            length /= 4;
- 
-            while (length--) {
-              pci_write_config_dword (dev, offset, *(unsigned int*)p++);
-            }
-          } else { /* copy as byte stream */
-            byte* p = (byte*)data;
- 
-            while (length--) {
-              pci_write_config_byte (dev, offset, *(unsigned char*)p++);
-            }
-          }
-  } 
-}
-
-void PCIread (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle)
-{
-  struct pci_dev	*dev = (struct pci_dev*)pci_dev_handle;
-
-  switch (length) {
-      case 1: /* byte */
-          pci_read_config_byte (dev, offset, (unsigned char*)data);
-          break;
-      case 2: /* word */
-          pci_read_config_word (dev, offset, (unsigned short*)data);
-          break;
-      case 4: /* dword */
-          pci_read_config_dword (dev, offset, (unsigned int*)data);
-          break;
- 
-      default: /* buffer */
-          if (!(length % 4) && !(length & 0x03)) { /* Copy as dword */
-              dword* p = (dword*)data;
-              length /= 4;
- 
-              while (length--) {
-                pci_read_config_dword (dev, offset, (unsigned int*)p++);
-              }
-          } else { /* copy as byte stream */
-              byte* p = (byte*) data;
- 
-              while (length--) {
-                pci_read_config_byte (dev, offset, (unsigned char*)p++);
-              }
-          }
-  }
-} 
+
+	return ((unsigned long) irq);
+}
+
+unsigned long divasa_get_pci_bar(unsigned char bus, unsigned char func,
+				 int bar, void *pci_dev_handle)
+{
+	unsigned long ret = 0;
+	struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
+
+	if (bar < 6) {
+		ret = dev->resource[bar].start;
+	}
+
+	DBG_TRC(("GOT BAR[%d]=%08x", bar, ret));
+
+	{
+		unsigned long type = (ret & 0x00000001);
+		if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+			DBG_TRC(("  I/O"));
+			ret &= PCI_BASE_ADDRESS_IO_MASK;
+		} else {
+			DBG_TRC(("  memory"));
+			ret &= PCI_BASE_ADDRESS_MEM_MASK;
+		}
+		DBG_TRC(("  final=%08x", ret));
+	}
+
+	return (ret);
+}
+
+void PCIwrite(byte bus, byte func, int offset, void *data, int length,
+	      void *pci_dev_handle)
+{
+	struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
+
+	switch (length) {
+	case 1:		/* byte */
+		pci_write_config_byte(dev, offset,
+				      *(unsigned char *) data);
+		break;
+	case 2:		/* word */
+		pci_write_config_word(dev, offset,
+				      *(unsigned short *) data);
+		break;
+	case 4:		/* dword */
+		pci_write_config_dword(dev, offset,
+				       *(unsigned int *) data);
+		break;
+
+	default:		/* buffer */
+		if (!(length % 4) && !(length & 0x03)) {	/* Copy as dword */
+			dword *p = (dword *) data;
+			length /= 4;
+
+			while (length--) {
+				pci_write_config_dword(dev, offset,
+						       *(unsigned int *)
+						       p++);
+			}
+		} else {	/* copy as byte stream */
+			byte *p = (byte *) data;
+
+			while (length--) {
+				pci_write_config_byte(dev, offset,
+						      *(unsigned char *)
+						      p++);
+			}
+		}
+	}
+}
+
+void PCIread(byte bus, byte func, int offset, void *data, int length,
+	     void *pci_dev_handle)
+{
+	struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
+
+	switch (length) {
+	case 1:		/* byte */
+		pci_read_config_byte(dev, offset, (unsigned char *) data);
+		break;
+	case 2:		/* word */
+		pci_read_config_word(dev, offset, (unsigned short *) data);
+		break;
+	case 4:		/* dword */
+		pci_read_config_dword(dev, offset, (unsigned int *) data);
+		break;
+
+	default:		/* buffer */
+		if (!(length % 4) && !(length & 0x03)) {	/* Copy as dword */
+			dword *p = (dword *) data;
+			length /= 4;
+
+			while (length--) {
+				pci_read_config_dword(dev, offset,
+						      (unsigned int *)
+						      p++);
+			}
+		} else {	/* copy as byte stream */
+			byte *p = (byte *) data;
+
+			while (length--) {
+				pci_read_config_byte(dev, offset,
+						     (unsigned char *)
+						     p++);
+			}
+		}
+	}
+}
 
 /*
   Init map with DMA pages. It is not problem if some allocations fail -
   the channels that will not get one DMA page will use standard PIO
   interface
   */
-static void *diva_pci_alloc_consistent (struct pci_dev *hwdev,
-                                        size_t size,
-                                        dma_addr_t * dma_handle,
-                                        void** addr_handle) {
-  void* addr = pci_alloc_consistent (hwdev, size, dma_handle);
-
-  *addr_handle = addr;
-
-  return (addr);
-}
-
-void diva_init_dma_map (void* hdev,
-                        struct _diva_dma_map_entry** ppmap,
-                        int nentries) {
-	struct pci_dev* pdev = (struct pci_dev*)hdev;
-	struct _diva_dma_map_entry* pmap = diva_alloc_dma_map (hdev, nentries);
-
-  if (pmap) {
-    int i;
-    dma_addr_t dma_handle;
-    void* cpu_addr;
-    void* addr_handle;
-
-    for (i = 0; i < nentries; i++) {
-      if (!(cpu_addr = diva_pci_alloc_consistent (pdev,
-                                             PAGE_SIZE,
-                                             &dma_handle,
-                                             &addr_handle))) {
-        break;
-      }
-      diva_init_dma_map_entry (pmap, i, cpu_addr,
-                               (dword)dma_handle, addr_handle);
-      DBG_TRC(("dma map alloc [%d]=(%08lx:%08x:%08lx)",
-               i, (unsigned long)cpu_addr, (dword)dma_handle, (unsigned long)addr_handle))
-    }
-  }
+static void *diva_pci_alloc_consistent(struct pci_dev *hwdev,
+				       size_t size,
+				       dma_addr_t * dma_handle,
+				       void **addr_handle)
+{
+	void *addr = pci_alloc_consistent(hwdev, size, dma_handle);
+
+	*addr_handle = addr;
+
+	return (addr);
+}
+
+void diva_init_dma_map(void *hdev,
+		       struct _diva_dma_map_entry **ppmap, int nentries)
+{
+	struct pci_dev *pdev = (struct pci_dev *) hdev;
+	struct _diva_dma_map_entry *pmap =
+	    diva_alloc_dma_map(hdev, nentries);
+
+	if (pmap) {
+		int i;
+		dma_addr_t dma_handle;
+		void *cpu_addr;
+		void *addr_handle;
+
+		for (i = 0; i < nentries; i++) {
+			if (!(cpu_addr = diva_pci_alloc_consistent(pdev,
+								   PAGE_SIZE,
+								   &dma_handle,
+								   &addr_handle)))
+			{
+				break;
+			}
+			diva_init_dma_map_entry(pmap, i, cpu_addr,
+						(dword) dma_handle,
+						addr_handle);
+			DBG_TRC(("dma map alloc [%d]=(%08lx:%08x:%08lx)",
+				 i, (unsigned long) cpu_addr,
+				 (dword) dma_handle,
+				 (unsigned long) addr_handle))}
+	}
 
-  *ppmap = pmap;
+	*ppmap = pmap;
 }
 
 /*
   Free all contained in the map entries and memory used by the map
   Should be always called after adapter removal from DIDD array
   */
-void diva_free_dma_map (void* hdev,
-                        struct _diva_dma_map_entry* pmap) {
-  struct pci_dev* pdev = (struct pci_dev*)hdev;
-  int i;
-  dword      phys_addr;
-  void*      cpu_addr;
-  dma_addr_t dma_handle;
-  void* addr_handle;
-
-  for (i = 0; (pmap != 0); i++) {
-    diva_get_dma_map_entry (pmap, i, &cpu_addr, &phys_addr);
-    if (!cpu_addr) {
-      break;
-    }
-    addr_handle = diva_get_entry_handle (pmap, i);
-    dma_handle = (dma_addr_t)phys_addr;
-    pci_free_consistent (pdev, PAGE_SIZE, addr_handle, dma_handle);
-    DBG_TRC(("dma map free [%d]=(%08lx:%08x:%08lx)",
-             i, (unsigned long)cpu_addr, (dword)dma_handle, (unsigned long)addr_handle))
-  }
+void diva_free_dma_map(void *hdev, struct _diva_dma_map_entry *pmap)
+{
+	struct pci_dev *pdev = (struct pci_dev *) hdev;
+	int i;
+	dword phys_addr;
+	void *cpu_addr;
+	dma_addr_t dma_handle;
+	void *addr_handle;
+
+	for (i = 0; (pmap != 0); i++) {
+		diva_get_dma_map_entry(pmap, i, &cpu_addr, &phys_addr);
+		if (!cpu_addr) {
+			break;
+		}
+		addr_handle = diva_get_entry_handle(pmap, i);
+		dma_handle = (dma_addr_t) phys_addr;
+		pci_free_consistent(pdev, PAGE_SIZE, addr_handle,
+				    dma_handle);
+		DBG_TRC(("dma map free [%d]=(%08lx:%08x:%08lx)", i,
+			 (unsigned long) cpu_addr, (dword) dma_handle,
+			 (unsigned long) addr_handle))
+	}
 
-  diva_free_dma_mapping (pmap);
+	diva_free_dma_mapping(pmap);
 }
 
 
@@ -497,89 +508,86 @@
  *********************************************************/
 
 int
-diva_os_register_io_port (int on, unsigned long port, unsigned long length, const char* name)
+diva_os_register_io_port(int on, unsigned long port, unsigned long length,
+			 const char *name)
 {
-  int ret;
+	int ret;
 
-  if (on) {
-    if ((ret = check_region (port, length)) < 0) {
-        DBG_ERR(("A: I/O: can't register port=%08x, error=%d", port, ret))
-        return (-1);
-    }
-    request_region (port, length, name);
-  } else {
-    release_region (port, length);
-  }
-  return (0);
+	if (on) {
+		if ((ret = check_region(port, length)) < 0) {
+			DBG_ERR(("A: I/O: can't register port=%08x, error=%d",
+				 port, ret))
+			return (-1);
+		}
+		request_region(port, length, name);
+	} else {
+		release_region(port, length);
+	}
+	return (0);
 }
 
-void *
-divasa_remap_pci_bar (unsigned long  bar, unsigned long area_length)
+void *divasa_remap_pci_bar(unsigned long bar, unsigned long area_length)
 {
-  void *ret;
+	void *ret;
 
-  ret = (void*)ioremap(bar, area_length);
-  DBG_TRC(("remap(%08x)->%08x", bar, ret));
-  return (ret);
+	ret = (void *) ioremap(bar, area_length);
+	DBG_TRC(("remap(%08x)->%08x", bar, ret));
+	return (ret);
 }
 
-void
-divasa_unmap_pci_bar (void* bar)
+void divasa_unmap_pci_bar(void *bar)
 {
-  if (bar) {
-    iounmap (bar);
-  }
+	if (bar) {
+		iounmap(bar);
+	}
 }
 
 /*********************************************************
  ** I/O port access 
  *********************************************************/
-byte __inline__
-inpp (void* addr) {
-  return (inb((unsigned long)addr));
+byte __inline__ inpp(void *addr)
+{
+	return (inb((unsigned long) addr));
 }
 
-word __inline__
-inppw (void* addr)
+word __inline__ inppw(void *addr)
 {
-  return (inw((unsigned long)addr));
+	return (inw((unsigned long) addr));
 }
 
-void __inline__
-inppw_buffer (void* addr, void* P, int length)
+void __inline__ inppw_buffer(void *addr, void *P, int length)
 {
-  insw ((unsigned long)addr, (word*)P, length>>1);
+	insw((unsigned long) addr, (word *) P, length >> 1);
 }
 
-void __inline__
-outppw_buffer (void* addr, void* P, int length)
+void __inline__ outppw_buffer(void *addr, void *P, int length)
 {
-  outsw ((unsigned long)addr, (word*)P, length>>1);
+	outsw((unsigned long) addr, (word *) P, length >> 1);
 }
 
-void __inline__
-outppw (void* addr, word w)
+void __inline__ outppw(void *addr, word w)
 {
-  outw (w, (unsigned long)addr);
+	outw(w, (unsigned long) addr);
 }
 
-void __inline__
-outpp (void* addr, word p)
+void __inline__ outpp(void *addr, word p)
 {
-  outb (p, (unsigned long)addr);
+	outb(p, (unsigned long) addr);
 }
 
 /* --------------------------------------------------------------------------
     IRQ request / remove  
    -------------------------------------------------------------------------- */
-int diva_os_register_irq (void* context, byte irq, const char* name) {
-  int result = request_irq (irq, diva_os_irq_wrapper,
-                            SA_INTERRUPT | SA_SHIRQ, name, context);
-  return (result);
+int diva_os_register_irq(void *context, byte irq, const char *name)
+{
+	int result = request_irq(irq, diva_os_irq_wrapper,
+				 SA_INTERRUPT | SA_SHIRQ, name, context);
+	return (result);
 }
 
-void diva_os_remove_irq (void* context, byte irq) {
-  free_irq (irq, context);
+void diva_os_remove_irq(void *context, byte irq)
+{
+	free_irq(irq, context);
 }
 
 /* --------------------------------------------------------------------------
@@ -587,64 +595,68 @@
    -------------------------------------------------------------------------- */
 static void diva_os_dpc_proc(unsigned long context)
 {
-  diva_os_thread_dpc_t* psoft_isr = (diva_os_thread_dpc_t*)context;
-  diva_os_soft_isr_t* pisr = psoft_isr->psoft_isr;
+	diva_os_thread_dpc_t *psoft_isr = (diva_os_thread_dpc_t *) context;
+	diva_os_soft_isr_t *pisr = psoft_isr->psoft_isr;
 
-	(*(pisr->callback))(pisr, pisr->callback_context);
+	(*(pisr->callback)) (pisr, pisr->callback_context);
 }
 
-int diva_os_initialize_soft_isr (diva_os_soft_isr_t* psoft_isr,
-                                 diva_os_soft_isr_callback_t callback,
-                                 void*   callback_context)
+int diva_os_initialize_soft_isr(diva_os_soft_isr_t * psoft_isr,
+				diva_os_soft_isr_callback_t callback,
+				void *callback_context)
 {
-  diva_os_thread_dpc_t* pdpc;
+	diva_os_thread_dpc_t *pdpc;
 
-  pdpc = (diva_os_thread_dpc_t*)diva_os_malloc (0, sizeof (*pdpc));
-  if (!(psoft_isr->object = pdpc)) {
+	pdpc = (diva_os_thread_dpc_t *) diva_os_malloc(0, sizeof(*pdpc));
+	if (!(psoft_isr->object = pdpc)) {
 		return (-1);
 	}
-  memset (pdpc, 0x00, sizeof (*pdpc));
-  psoft_isr->callback         = callback;
-  psoft_isr->callback_context = callback_context;
-  pdpc->psoft_isr             = psoft_isr;
-  INIT_WORK(&pdpc->trap_script_task, diva_adapter_trapped, pdpc);
-	tasklet_init(&pdpc->divas_task, diva_os_dpc_proc, (unsigned long)pdpc);
-
-  return (0);
-}
-
-int diva_os_schedule_soft_isr (diva_os_soft_isr_t* psoft_isr)
-{
-  if (psoft_isr && psoft_isr->object) {
-  	diva_os_thread_dpc_t* pdpc = (diva_os_thread_dpc_t*)psoft_isr->object;
+	memset(pdpc, 0x00, sizeof(*pdpc));
+	psoft_isr->callback = callback;
+	psoft_isr->callback_context = callback_context;
+	pdpc->psoft_isr = psoft_isr;
+	INIT_WORK(&pdpc->trap_script_task, diva_adapter_trapped, pdpc);
+	tasklet_init(&pdpc->divas_task, diva_os_dpc_proc,
+		     (unsigned long) pdpc);
+
+	return (0);
+}
+
+int diva_os_schedule_soft_isr(diva_os_soft_isr_t * psoft_isr)
+{
+	if (psoft_isr && psoft_isr->object) {
+		diva_os_thread_dpc_t *pdpc =
+		    (diva_os_thread_dpc_t *) psoft_isr->object;
 
 		tasklet_schedule(&pdpc->divas_task);
 	}
 
-  return (1);
+	return (1);
 }
 
-int diva_os_cancel_soft_isr (diva_os_soft_isr_t* psoft_isr)
+int diva_os_cancel_soft_isr(diva_os_soft_isr_t * psoft_isr)
 {
-  if (psoft_isr && psoft_isr->object) {
-  	diva_os_thread_dpc_t* pdpc = (diva_os_thread_dpc_t*)psoft_isr->object;
+	if (psoft_isr && psoft_isr->object) {
+		diva_os_thread_dpc_t *pdpc =
+		    (diva_os_thread_dpc_t *) psoft_isr->object;
 		tasklet_kill(&pdpc->divas_task);
 	}
-  return (0);
-} 
-  
-void diva_os_remove_soft_isr (diva_os_soft_isr_t* psoft_isr)
-{
-  if (psoft_isr && psoft_isr->object) {
-    diva_os_thread_dpc_t* pdpc = (diva_os_thread_dpc_t*)psoft_isr->object;
-    void* mem;
+	return (0);
+}
+
+void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr)
+{
+	if (psoft_isr && psoft_isr->object) {
+		diva_os_thread_dpc_t *pdpc =
+		    (diva_os_thread_dpc_t *) psoft_isr->object;
+		void *mem;
 
 		tasklet_kill(&pdpc->divas_task);
 
-    mem = psoft_isr->object;
-    psoft_isr->object = 0;
-    flush_scheduled_work();
-    diva_os_free (0, mem);
+		mem = psoft_isr->object;
+		psoft_isr->object = 0;
+		flush_scheduled_work();
+		diva_os_free(0, mem);
 	}
 }
 
@@ -652,290 +664,296 @@
  * kernel/user space copy functions
  */
 static int
-xdi_copy_to_user(void* os_handle, void* dst, const void* src, int length)
+xdi_copy_to_user(void *os_handle, void *dst, const void *src, int length)
 {
-		if (copy_to_user (dst, src, length)) {
-				return (-EFAULT);
-		}
-		return (length);
-} 
+	if (copy_to_user(dst, src, length)) {
+		return (-EFAULT);
+	}
+	return (length);
+}
 
 static int
-xdi_copy_from_user (void* os_handle, void* dst, const void* src, int length)
+xdi_copy_from_user(void *os_handle, void *dst, const void *src, int length)
 {
-		if (copy_from_user(dst, src, length)) {
-				return (-EFAULT);
-		}
-		return (length);
+	if (copy_from_user(dst, src, length)) {
+		return (-EFAULT);
+	}
+	return (length);
 }
 
 /*
  * device node operations
  */
-static int divas_open(struct inode * inode, struct file * file)
+static int divas_open(struct inode *inode, struct file *file)
 {
-		return(0);
+	return (0);
 }
 
-static int divas_release(struct inode * inode, struct file * file)
+static int divas_release(struct inode *inode, struct file *file)
 {
-		if (file->private_data) {
-				diva_xdi_close_adapter (file->private_data, file);
-		}
-		return(0);
-}
-
-static int divas_ioctl(struct inode *inode, struct file *file,
-            unsigned int cmd, unsigned long arg)
-{
-		return(-EINVAL);
+	if (file->private_data) {
+		diva_xdi_close_adapter(file->private_data, file);
+	}
+	return (0);
 }
 
-static ssize_t divas_write(struct file * file, const char * buf,
-            size_t count, loff_t *ppos)
+static ssize_t divas_write(struct file *file, const char *buf,
+			   size_t count, loff_t * ppos)
 {
-		int ret = -EINVAL;
+	int ret = -EINVAL;
 
-		if (!file->private_data) {
-				file->private_data = diva_xdi_open_adapter(file, buf,
-									count, xdi_copy_from_user);
-		}
-		if (!file->private_data) {
-				return (-ENODEV);
-		}
+	if (!file->private_data) {
+		file->private_data = diva_xdi_open_adapter(file, buf,
+							   count,
+							   xdi_copy_from_user);
+	}
+	if (!file->private_data) {
+		return (-ENODEV);
+	}
 
-		ret = diva_xdi_write(file->private_data, file,
-													buf, count, xdi_copy_from_user);
-		switch(ret) {
-				case -1:	/* Message should be removed from rx mailbox first */
-					ret = -EBUSY;
-					break;
-				case -2:	/* invalid adapter was specified in this call */
-					ret = -ENOMEM;
-					break;
-				case -3:
-					ret = -ENXIO;
-					break;
-		}
-		DBG_TRC(("write: ret %d", ret));
-		return(ret);
+	ret = diva_xdi_write(file->private_data, file,
+			     buf, count, xdi_copy_from_user);
+	switch (ret) {
+	case -1:		/* Message should be removed from rx mailbox first */
+		ret = -EBUSY;
+		break;
+	case -2:		/* invalid adapter was specified in this call */
+		ret = -ENOMEM;
+		break;
+	case -3:
+		ret = -ENXIO;
+		break;
+	}
+	DBG_TRC(("write: ret %d", ret));
+	return (ret);
 }
 
-static ssize_t divas_read(struct file * file, char * buf,
-            size_t count, loff_t *ppos)
+static ssize_t divas_read(struct file *file, char *buf,
+			  size_t count, loff_t * ppos)
 {
-		int ret = -EINVAL;
+	int ret = -EINVAL;
 
-		if (!file->private_data) {
-				file->private_data = diva_xdi_open_adapter(file, buf,
-									count, xdi_copy_from_user);
-		}
-		if (!file->private_data) {
-				return (-ENODEV);
-		}
+	if (!file->private_data) {
+		file->private_data = diva_xdi_open_adapter(file, buf,
+							   count,
+							   xdi_copy_from_user);
+	}
+	if (!file->private_data) {
+		return (-ENODEV);
+	}
 
-		ret = diva_xdi_read(file->private_data, file,
-													buf, count, xdi_copy_to_user);
-		switch(ret) {
-				case -1:	/* RX mailbox is empty */
-					ret = -EAGAIN;
-					break;
-				case -2:	/* no memory, mailbox was cleared, last command is failed */
-					ret = -ENOMEM;
-					break;
-				case -3:	/* can't copy to user, retry */
-					ret = -EFAULT;
-					break;
-		}
-		DBG_TRC(("read: ret %d", ret));
-		return(ret);
+	ret = diva_xdi_read(file->private_data, file,
+			    buf, count, xdi_copy_to_user);
+	switch (ret) {
+	case -1:		/* RX mailbox is empty */
+		ret = -EAGAIN;
+		break;
+	case -2:		/* no memory, mailbox was cleared, last command is failed */
+		ret = -ENOMEM;
+		break;
+	case -3:		/* can't copy to user, retry */
+		ret = -EFAULT;
+		break;
+	}
+	DBG_TRC(("read: ret %d", ret));
+	return (ret);
 }
 
 static unsigned int divas_poll(struct file *file, poll_table * wait)
 {
-		if (!file->private_data) {
-				return (POLLERR);
-		}
-		return (POLLIN | POLLRDNORM);
-}
-
-
-static loff_t divas_lseek(struct file *file, loff_t offset, int orig)
-{
-		return(-ESPIPE);
+	if (!file->private_data) {
+		return (POLLERR);
+	}
+	return (POLLIN | POLLRDNORM);
 }
 
-static struct file_operations divas_fops =
-{
-		owner:			THIS_MODULE,
-		llseek:			divas_lseek,
-		read:				divas_read,
-		write:			divas_write,
-		poll:				divas_poll,
-		ioctl:			divas_ioctl,
-		open:				divas_open,
-		release:		divas_release,
+static struct file_operations divas_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = divas_read,
+	.write   = divas_write,
+	.poll    = divas_poll,
+	.open    = divas_open,
+	.release = divas_release
 };
 
 static void divas_unregister_chrdev(void)
 {
-		if (devfs_handle)
-				devfs_unregister (devfs_handle);
-		unregister_chrdev(major, "Divas");
+	if (devfs_handle)
+		devfs_unregister(devfs_handle);
+	unregister_chrdev(major, "Divas");
 }
 
 static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
 {
-		if (register_chrdev (major, "Divas", &divas_fops))
-		{
-				printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME);
-				return(0);
-		}
-		devfs_handle = devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0,
-					S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL);
+	if (register_chrdev(major, "Divas", &divas_fops))
+	{
+		printk(KERN_ERR "%s: failed to create /dev entry.\n",
+		       DRIVERLNAME);
+		return (0);
+	}
+	devfs_handle =
+	    devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0,
+			   S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL);
 
-		return(1);
+	return (1);
 }
 
 /* --------------------------------------------------------------------------
     PCI driver section
    -------------------------------------------------------------------------- */
-static int __devinit divas_init_one (struct pci_dev *pdev,
-                                     const struct pci_device_id *ent) {
-  void* pdiva = 0;
-  u8 pci_latency;
-  u8 new_latency = 32;
-
-  DBG_TRC(("%s bus: %08x fn: %08x insertion.\n",
-          CardProperties[ent->driver_data].Name,
-          pdev->bus->number, pdev->devfn))
-  printk(KERN_INFO "%s: %s bus: %08x fn: %08x insertion.\n",
-         DRIVERLNAME, CardProperties[ent->driver_data].Name,
-         pdev->bus->number, pdev->devfn);
-
-  if (pci_enable_device (pdev)) {
-    DBG_TRC(("%s: %s bus: %08x fn: %08x device init failed.\n",
-           DRIVERLNAME, CardProperties[ent->driver_data].Name,
-           pdev->bus->number, pdev->devfn))
-    printk(KERN_ERR "%s: %s bus: %08x fn: %08x device init failed.\n",
-           DRIVERLNAME, CardProperties[ent->driver_data].Name,
-           pdev->bus->number, pdev->devfn);
-    return (-EIO);
-  }
-
-  pci_set_master (pdev);
-
-  pci_read_config_byte (pdev, PCI_LATENCY_TIMER, &pci_latency);
-  if (!pci_latency) {
-    DBG_TRC(("%s: bus: %08x fn: %08x fix latency.\n",
-           DRIVERLNAME, pdev->bus->number, pdev->devfn))
-    printk(KERN_INFO "%s: bus: %08x fn: %08x fix latency.\n",
-           DRIVERLNAME, pdev->bus->number, pdev->devfn);
-    pci_write_config_byte (pdev, PCI_LATENCY_TIMER, new_latency);
-  }
-
-  if (!(pdiva = diva_driver_add_card (pdev, ent->driver_data))) {
-    DBG_TRC(("%s: %s bus: %08x fn: %08x card init failed.\n",
-           DRIVERLNAME, CardProperties[ent->driver_data].Name,
-           pdev->bus->number, pdev->devfn))
-    printk(KERN_ERR "%s: %s bus: %08x fn: %08x card init failed.\n",
-           DRIVERLNAME, CardProperties[ent->driver_data].Name,
-           pdev->bus->number, pdev->devfn);
-    return (-EIO);
-  }
-
-  pci_set_drvdata(pdev, pdiva);
-
-  return (0);
-}
-
-static void __devexit divas_remove_one (struct pci_dev *pdev) {
-  void* pdiva = pci_get_drvdata (pdev);
-
-  DBG_TRC(("bus: %08x fn: %08x removal.\n",
-          pdev->bus->number, pdev->devfn))
-  printk(KERN_INFO "%s: bus: %08x fn: %08x removal.\n",
-         DRIVERLNAME, pdev->bus->number, pdev->devfn);
-
-  if (pdiva) {
-    diva_driver_remove_card (pdiva);
-  }
+static int __devinit divas_init_one(struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
+{
+	void *pdiva = 0;
+	u8 pci_latency;
+	u8 new_latency = 32;
+
+	DBG_TRC(("%s bus: %08x fn: %08x insertion.\n",
+		 CardProperties[ent->driver_data].Name,
+		 pdev->bus->number, pdev->devfn))
+	printk(KERN_INFO "%s: %s bus: %08x fn: %08x insertion.\n",
+		DRIVERLNAME, CardProperties[ent->driver_data].Name,
+		pdev->bus->number, pdev->devfn);
+
+	if (pci_enable_device(pdev)) {
+		DBG_TRC(("%s: %s bus: %08x fn: %08x device init failed.\n",
+			 DRIVERLNAME,
+			 CardProperties[ent->driver_data].Name,
+			 pdev->bus->number,
+			 pdev->devfn))
+		printk(KERN_ERR
+			"%s: %s bus: %08x fn: %08x device init failed.\n",
+			DRIVERLNAME,
+			CardProperties[ent->driver_data].
+			Name, pdev->bus->number,
+			pdev->devfn);
+		return (-EIO);
+	}
+
+	pci_set_master(pdev);
+
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+	if (!pci_latency) {
+		DBG_TRC(("%s: bus: %08x fn: %08x fix latency.\n",
+			 DRIVERLNAME, pdev->bus->number, pdev->devfn))
+		printk(KERN_INFO
+			"%s: bus: %08x fn: %08x fix latency.\n",
+			 DRIVERLNAME, pdev->bus->number, pdev->devfn);
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+	}
+
+	if (!(pdiva = diva_driver_add_card(pdev, ent->driver_data))) {
+		DBG_TRC(("%s: %s bus: %08x fn: %08x card init failed.\n",
+			 DRIVERLNAME,
+			 CardProperties[ent->driver_data].Name,
+			 pdev->bus->number,
+			 pdev->devfn))
+		printk(KERN_ERR
+			"%s: %s bus: %08x fn: %08x card init failed.\n",
+			DRIVERLNAME,
+			CardProperties[ent->driver_data].
+			Name, pdev->bus->number,
+			pdev->devfn);
+		return (-EIO);
+	}
+
+	pci_set_drvdata(pdev, pdiva);
+
+	return (0);
+}
+
+static void __devexit divas_remove_one(struct pci_dev *pdev)
+{
+	void *pdiva = pci_get_drvdata(pdev);
+
+	DBG_TRC(("bus: %08x fn: %08x removal.\n",
+		 pdev->bus->number, pdev->devfn))
+	printk(KERN_INFO "%s: bus: %08x fn: %08x removal.\n",
+		DRIVERLNAME, pdev->bus->number, pdev->devfn);
+
+	if (pdiva) {
+		diva_driver_remove_card(pdiva);
+	}
 
 }
 
 /* --------------------------------------------------------------------------
     Driver Load / Startup  
    -------------------------------------------------------------------------- */
-static int DIVA_INIT_FUNCTION divas_init(void) {
-  char tmprev[50];
-  int ret = 0;
-
-  MOD_INC_USE_COUNT;
-
-  printk(KERN_INFO "%s\n", DRIVERNAME);
-  printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
-  strcpy(tmprev, main_revision);
-  printk("%s  Build: %s(%s) Major: %d\n", getrev(tmprev),
-        diva_xdi_common_code_build, DIVA_BUILD, major);
-  printk(KERN_INFO "%s: support for: ", DRIVERLNAME);
+static int DIVA_INIT_FUNCTION divas_init(void)
+{
+	char tmprev[50];
+	int ret = 0;
+
+	MOD_INC_USE_COUNT;
+
+	printk(KERN_INFO "%s\n", DRIVERNAME);
+	printk(KERN_INFO "%s: Rel:%s  Rev:", DRIVERLNAME, DRIVERRELEASE);
+	strcpy(tmprev, main_revision);
+	printk("%s  Build: %s(%s) Major: %d\n", getrev(tmprev),
+	       diva_xdi_common_code_build, DIVA_BUILD, major);
+	printk(KERN_INFO "%s: support for: ", DRIVERLNAME);
 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
-  printk("BRI/PCI ");
+	printk("BRI/PCI ");
 #endif
 #ifdef CONFIG_ISDN_DIVAS_4BRIPCI
-  printk("4BRI/PCI ");
+	printk("4BRI/PCI ");
 #endif
 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
-  printk("PRI/PCI ");
+	printk("PRI/PCI ");
 #endif
-  printk("\n");
+	printk("\n");
 
-  if(!divasfunc_init()) {
-    printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME);
-    ret = -EIO;
-    goto out;
-  }
+	if (!divasfunc_init()) {
+		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
+		       DRIVERLNAME);
+		ret = -EIO;
+		goto out;
+	}
 
-	if (!divas_register_chrdev())
-	{
-    divasfunc_exit();
-    ret = -EIO;
-    goto out;
+	if (!divas_register_chrdev()) {
+		divasfunc_exit();
+		ret = -EIO;
+		goto out;
 	}
 
-  if(!create_divas_proc()) {
-    remove_divas_proc();
+	if (!create_divas_proc()) {
+		remove_divas_proc();
 		divas_unregister_chrdev();
-    divasfunc_exit();
-    printk(KERN_ERR "%s: failed to create proc entry.\n", DRIVERLNAME);
-    ret = -EIO;
-    goto out;
-  }
+		divasfunc_exit();
+		printk(KERN_ERR "%s: failed to create proc entry.\n",
+		       DRIVERLNAME);
+		ret = -EIO;
+		goto out;
+	}
 
-  if ((ret = pci_module_init(&diva_pci_driver))) {
-    remove_divas_proc();
+	if ((ret = pci_module_init(&diva_pci_driver))) {
+		remove_divas_proc();
 		divas_unregister_chrdev();
-    divasfunc_exit();
-    printk(KERN_ERR "%s: failed to init pci driver.\n", DRIVERLNAME);
-    goto out;
-  }
-
-out:
-  MOD_DEC_USE_COUNT;
-  return(ret);  
+		divasfunc_exit();
+		printk(KERN_ERR "%s: failed to init pci driver.\n",
+		       DRIVERLNAME);
+		goto out;
+	}
+
+      out:
+	MOD_DEC_USE_COUNT;
+	return (ret);
 }
 
 /* --------------------------------------------------------------------------
     Driver Unload
    -------------------------------------------------------------------------- */
-static void DIVA_EXIT_FUNCTION divas_exit(void) {
-  pci_unregister_driver (&diva_pci_driver);
-  remove_divas_proc ();
+static void DIVA_EXIT_FUNCTION divas_exit(void)
+{
+	pci_unregister_driver(&diva_pci_driver);
+	remove_divas_proc();
 	divas_unregister_chrdev();
 	divasfunc_exit();
 
-  printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
+	printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
 }
 
 module_init(divas_init);
 module_exit(divas_exit);
-
diff -Nru a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
--- a/drivers/isdn/hardware/eicon/divasproc.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/divasproc.c	Sun Nov 17 20:30:15 2002
@@ -1,10 +1,10 @@
-/* $Id: divasproc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: divasproc.c,v 1.1.2.4 2001/02/16 08:40:36 armin Exp $
  *
  * Low level driver for Eicon DIVA Server ISDN cards.
  * /proc functions
  *
- * Copyright 2000,2001 by Armin Schindler (mac@melware.de)
- * Copyright 2000,2001 Cytronics & Melware (info@melware.de)
+ * Copyright 2000-2002 by Armin Schindler (mac@melware.de)
+ * Copyright 2000-2002 Cytronics & Melware (info@melware.de)
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
+#include <linux/interrupt.h>
 
 #include "platform.h"
 #include "debuglib.h"
@@ -59,159 +60,151 @@
 static ssize_t
 divas_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
-  int len = 0;
-  int cadapter;
-  char tmpbuf[80];
-  char tmpser[16];
-
-  if (*off)
-      return 0;
-  if (off != &file->f_pos)
-      return -ESPIPE;
-
-  divas_get_version(tmpbuf);
-  if(copy_to_user(buf+len, &tmpbuf, strlen(tmpbuf)))
-      return -EFAULT;
-  len += strlen(tmpbuf);
-
-  for(cadapter = 0; cadapter < MAX_ADAPTER; cadapter++) {
-    if (IoAdapters[cadapter]) {
-      diva_get_vserial_number(IoAdapters[cadapter], tmpser);
-      sprintf(tmpbuf, "%2d: %-30s Serial:%-10s IRQ:%2d\n", cadapter + 1,
-          IoAdapters[cadapter]->Properties.Name,
-          tmpser,
-          IoAdapters[cadapter]->irq_info.irq_nr);
-      if((strlen(tmpbuf)+len) > count)
-        break;
-      if(copy_to_user(buf+len, &tmpbuf, strlen(tmpbuf)))
-        return -EFAULT;
-      len += strlen(tmpbuf);
-    }
-  }
+	int len = 0;
+	int cadapter;
+	char tmpbuf[80];
+	char tmpser[16];
+
+	if (*off)
+		return 0;
+	if (off != &file->f_pos)
+		return -ESPIPE;
+
+	divas_get_version(tmpbuf);
+	if (copy_to_user(buf + len, &tmpbuf, strlen(tmpbuf)))
+		return -EFAULT;
+	len += strlen(tmpbuf);
+
+	for (cadapter = 0; cadapter < MAX_ADAPTER; cadapter++) {
+		if (IoAdapters[cadapter]) {
+			diva_get_vserial_number(IoAdapters[cadapter],
+						tmpser);
+			sprintf(tmpbuf,
+				"%2d: %-30s Serial:%-10s IRQ:%2d\n",
+				cadapter + 1,
+				IoAdapters[cadapter]->Properties.Name,
+				tmpser,
+				IoAdapters[cadapter]->irq_info.irq_nr);
+			if ((strlen(tmpbuf) + len) > count)
+				break;
+			if (copy_to_user
+			    (buf + len, &tmpbuf,
+			     strlen(tmpbuf))) return -EFAULT;
+			len += strlen(tmpbuf);
+		}
+	}
 
-  *off += len;
-  return(len);
+	*off += len;
+	return (len);
 }
 
 static ssize_t
 divas_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-  return (-ENODEV);
-}                                  
-
-static unsigned int
-divas_poll(struct file *file, poll_table * wait)
-{
-  return (POLLERR);
-}
-
-static int
-divas_open(struct inode *inode, struct file *file)
-{
-  return(0);
+	return (-ENODEV);
 }
 
-static int
-divas_close(struct inode *inode, struct file *file)
+static unsigned int divas_poll(struct file *file, poll_table * wait)
 {
-  return(0);
+	return (POLLERR);
 }
 
-static int
-divas_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+static int divas_open(struct inode *inode, struct file *file)
 {
-		return(-EINVAL);
+	return (0);
 }
 
-static loff_t
-divas_lseek(struct file *file, loff_t offset, int orig)
+static int divas_close(struct inode *inode, struct file *file)
 {
-  return(-ESPIPE);
+	return (0);
 }
 
-static struct file_operations divas_fops =
-{
-	owner: 					THIS_MODULE,
-  llseek:         divas_lseek,
-  read:           divas_read,
-  write:          divas_write,
-  poll:           divas_poll,
-  ioctl:          divas_ioctl,
-  open:           divas_open,
-  release:        divas_close,
+static struct file_operations divas_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = divas_read,
+	.write   = divas_write,
+	.poll    = divas_poll,
+	.open    = divas_open,
+	.release = divas_close
 };
 
-int
-create_divas_proc(void)
+int create_divas_proc(void)
 {
-  divas_proc_entry = create_proc_entry(divas_proc_name,
-                     S_IFREG | S_IRUGO , proc_net_isdn_eicon);
-  if (!divas_proc_entry)
-    return(0);
+	divas_proc_entry = create_proc_entry(divas_proc_name,
+					     S_IFREG | S_IRUGO,
+					     proc_net_isdn_eicon);
+	if (!divas_proc_entry)
+		return (0);
 
-  divas_proc_entry->proc_fops = &divas_fops;   
-  divas_proc_entry->owner = THIS_MODULE;
+	divas_proc_entry->proc_fops = &divas_fops;
+	divas_proc_entry->owner = THIS_MODULE;
 
-  return(1);
+	return (1);
 }
 
-void
-remove_divas_proc(void)
+void remove_divas_proc(void)
 {
-  if (divas_proc_entry) {
-    remove_proc_entry(divas_proc_name, proc_net_isdn_eicon);
-    divas_proc_entry = NULL;
-  }
+	if (divas_proc_entry) {
+		remove_proc_entry(divas_proc_name, proc_net_isdn_eicon);
+		divas_proc_entry = NULL;
+	}
 }
 
 /*
 ** write group_optimization 
 */
 static int
-write_grp_opt(struct file *file, const char *buffer, unsigned long count, void *data)
+write_grp_opt(struct file *file, const char *buffer, unsigned long count,
+	      void *data)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t *)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
-  
-  if ((count == 1) || (count == 2)) {
-    switch(buffer[0]) {
-        case '0':
-          IoAdapter->capi_cfg.cfg_1 &= ~DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
-          break;
-        case '1':
-          IoAdapter->capi_cfg.cfg_1 |= DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
-          break;
-        default:
-          return(-EINVAL);
-    }
-    return(count);
-  }
-  return(-EINVAL);
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
+
+	if ((count == 1) || (count == 2)) {
+		switch (buffer[0]) {
+		case '0':
+			IoAdapter->capi_cfg.cfg_1 &=
+			    ~DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
+			break;
+		case '1':
+			IoAdapter->capi_cfg.cfg_1 |=
+			    DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
+			break;
+		default:
+			return (-EINVAL);
+		}
+		return (count);
+	}
+	return (-EINVAL);
 }
 
 /*
 ** write dynamic_l1_down
 */
 static int
-write_d_l1_down(struct file *file, const char *buffer, unsigned long count, void *data)
+write_d_l1_down(struct file *file, const char *buffer, unsigned long count,
+		void *data)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t *)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
-  if ((count == 1) || (count == 2)) {
-    switch(buffer[0]) {
-        case '0':
-          IoAdapter->capi_cfg.cfg_1 &= ~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
-          break;
-        case '1':
-          IoAdapter->capi_cfg.cfg_1 |= DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
-          break;
-        default:
-          return(-EINVAL);
-    }
-    return(count);
-  }
-  return(-EINVAL);
+	if ((count == 1) || (count == 2)) {
+		switch (buffer[0]) {
+		case '0':
+			IoAdapter->capi_cfg.cfg_1 &=
+			    ~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
+			break;
+		case '1':
+			IoAdapter->capi_cfg.cfg_1 |=
+			    DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
+			break;
+		default:
+			return (-EINVAL);
+		}
+		return (count);
+	}
+	return (-EINVAL);
 }
 
 
@@ -219,129 +212,151 @@
 ** read dynamic_l1_down 
 */
 static int
-read_d_l1_down(char *page, char **start, off_t off, int count, int *eof, void *data)
+read_d_l1_down(char *page, char **start, off_t off, int count, int *eof,
+	       void *data)
 {
-  int len = 0;
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t *)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
-
-  len += sprintf(page+len, "%s\n",
-         (IoAdapter->capi_cfg.cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ?
-          "1" : "0");
-
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	int len = 0;
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
+
+	len += sprintf(page + len, "%s\n",
+		       (IoAdapter->capi_cfg.
+			cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" :
+		       "0");
+
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
 /*
 ** read group_optimization
 */
 static int
-read_grp_opt(char *page, char **start, off_t off, int count, int *eof, void *data)
+read_grp_opt(char *page, char **start, off_t off, int count, int *eof,
+	     void *data)
 {
-  int len = 0;
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t *)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
-
-  len += sprintf(page+len, "%s\n",
-         (IoAdapter->capi_cfg.cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) ?
-          "1" : "0");
-
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	int len = 0;
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
+
+	len += sprintf(page + len, "%s\n",
+		       (IoAdapter->capi_cfg.
+			cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON)
+		       ? "1" : "0");
+
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
 /*
 ** info write
 */
 static int
-info_write(struct file *file, const char *buffer, unsigned long count, void *data)
+info_write(struct file *file, const char *buffer, unsigned long count,
+	   void *data)
 {
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t *)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
-  /* this is for test purposes only */
-  if ((count > 4) && (!memcmp(buffer, "trap", 4))) {
-    (*(IoAdapter->os_trap_nfy_Fnc))(IoAdapter, IoAdapter->ANum);
-    return(count);
-  }
-  return(-EINVAL);
+	/* this is for test purposes only */
+	if ((count > 4) && (!memcmp(buffer, "trap", 4))) {
+		(*(IoAdapter->os_trap_nfy_Fnc)) (IoAdapter, IoAdapter->ANum);
+		return (count);
+	}
+	return (-EINVAL);
 }
 
 /*
 ** info read
 */
 static int
-info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+info_read(char *page, char **start, off_t off, int count, int *eof,
+	  void *data)
 {
-  int i = 0;
-  int len = 0;
-  char *p;
-  char tmpser[16];
-  diva_os_xdi_adapter_t* a = (diva_os_xdi_adapter_t*)data;
-  PISDN_ADAPTER IoAdapter = IoAdapters[a->controller-1];
-
-  len += sprintf(page+len, "Name        : %s\n", IoAdapter->Properties.Name);
-  len += sprintf(page+len, "DSP state   : %08x\n", a->dsp_mask);
-  len += sprintf(page+len, "Channels    : %02d\n",
-                                          IoAdapter->Properties.Channels);
-  len += sprintf(page+len, "E. max/used : %03d/%03d\n",
-                                          IoAdapter->e_max, IoAdapter->e_count);
-  diva_get_vserial_number(IoAdapter, tmpser);
-  len += sprintf(page+len, "Serial      : %s\n", tmpser);
-  len += sprintf(page+len, "IRQ         : %d\n", IoAdapter->irq_info.irq_nr);
-  len += sprintf(page+len, "CardIndex   : %d\n", a->CardIndex);
-  len += sprintf(page+len, "CardOrdinal : %d\n", a->CardOrdinal);
-  len += sprintf(page+len, "Controller  : %d\n", a->controller);
-  len += sprintf(page+len, "Bus-Type    : %s\n",
-      (a->Bus == DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA":"PCI");
-  len += sprintf(page+len, "Port-Name   : %s\n", a->port_name);
-  if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {
-    len += sprintf(page+len, "PCI-bus     : %d\n", a->resources.pci.bus);
-    len += sprintf(page+len, "PCI-func    : %d\n", a->resources.pci.func);
-    for(i = 0; i < 8; i++) {
-      if(a->resources.pci.bar[i]) {
-        len += sprintf(page+len, "Mem / I/O %d : 0x%x / mapped : 0x%lx",
-          i, a->resources.pci.bar[i], (unsigned long)a->resources.pci.addr[i]);
-        if(a->resources.pci.length[i]) {
-          len += sprintf(page+len, " / length : %d",
-               a->resources.pci.length[i]);
-        }
-        len += sprintf(page+len, "\n");
-      }
-    }
-  }
-  if ((!a->xdi_adapter.port) &&
-      ((!a->xdi_adapter.ram) || (!a->xdi_adapter.reset) || (!a->xdi_adapter.cfg)))
-  {
-    if(!IoAdapter->irq_info.irq_nr) {
-      p = "slave";
-    } else {
-      p = "out of service";
-    }
-  } else if (a->xdi_adapter.trapped) {
-     p = "trapped";
-  } else if (a->xdi_adapter.Initialized) {
-     p = "active";
-  } else {
-     p = "ready";
-  }
-  len += sprintf(page+len, "State       : %s\n", p);
-
-  if (off + count >= len)
-    *eof = 1;
-  if (len < off)
-    return 0;
-  *start = page + off;
-  return((count < len-off) ? count : len-off);
+	int i = 0;
+	int len = 0;
+	char *p;
+	char tmpser[16];
+	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
+	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
+
+	len +=
+	    sprintf(page + len, "Name        : %s\n",
+		    IoAdapter->Properties.Name);
+	len += sprintf(page + len, "DSP state   : %08x\n", a->dsp_mask);
+	len += sprintf(page + len, "Channels    : %02d\n",
+		       IoAdapter->Properties.Channels);
+	len += sprintf(page + len, "E. max/used : %03d/%03d\n",
+		       IoAdapter->e_max, IoAdapter->e_count);
+	diva_get_vserial_number(IoAdapter, tmpser);
+	len += sprintf(page + len, "Serial      : %s\n", tmpser);
+	len +=
+	    sprintf(page + len, "IRQ         : %d\n",
+		    IoAdapter->irq_info.irq_nr);
+	len += sprintf(page + len, "CardIndex   : %d\n", a->CardIndex);
+	len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal);
+	len += sprintf(page + len, "Controller  : %d\n", a->controller);
+	len += sprintf(page + len, "Bus-Type    : %s\n",
+		       (a->Bus ==
+			DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI");
+	len += sprintf(page + len, "Port-Name   : %s\n", a->port_name);
+	if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {
+		len +=
+		    sprintf(page + len, "PCI-bus     : %d\n",
+			    a->resources.pci.bus);
+		len +=
+		    sprintf(page + len, "PCI-func    : %d\n",
+			    a->resources.pci.func);
+		for (i = 0; i < 8; i++) {
+			if (a->resources.pci.bar[i]) {
+				len +=
+				    sprintf(page + len,
+					    "Mem / I/O %d : 0x%x / mapped : 0x%lx",
+					    i, a->resources.pci.bar[i],
+					    (unsigned long) a->resources.
+					    pci.addr[i]);
+				if (a->resources.pci.length[i]) {
+					len +=
+					    sprintf(page + len,
+						    " / length : %d",
+						    a->resources.pci.
+						    length[i]);
+				}
+				len += sprintf(page + len, "\n");
+			}
+		}
+	}
+	if ((!a->xdi_adapter.port) &&
+	    ((!a->xdi_adapter.ram) || (!a->xdi_adapter.reset)
+	     || (!a->xdi_adapter.cfg))) {
+		if (!IoAdapter->irq_info.irq_nr) {
+			p = "slave";
+		} else {
+			p = "out of service";
+		}
+	} else if (a->xdi_adapter.trapped) {
+		p = "trapped";
+	} else if (a->xdi_adapter.Initialized) {
+		p = "active";
+	} else {
+		p = "ready";
+	}
+	len += sprintf(page + len, "State       : %s\n", p);
+
+	if (off + count >= len)
+		*eof = 1;
+	if (len < off)
+		return 0;
+	*start = page + off;
+	return ((count < len - off) ? count : len - off);
 }
 
 /*
@@ -351,62 +366,73 @@
 /* --------------------------------------------------------------------------
     Create adapter directory and files in proc file system
    -------------------------------------------------------------------------- */
-int create_adapter_proc (diva_os_xdi_adapter_t* a) {
-  struct proc_dir_entry *de, *pe;
-  char tmp[16];
-
-    sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
-    if(!(de = create_proc_entry(tmp, S_IFDIR, proc_net_isdn_eicon)))
-          return(0);
-    a->proc_adapter_dir = (void *)de;
-
-    if(!(pe = create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de)))
-          return(0);
-    a->proc_info = (void *)pe;
-    pe->write_proc = info_write;
-    pe->read_proc = info_read;
-    pe->data = a; 
-
-    if((pe = create_proc_entry(grp_opt_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) {
-      a->proc_grp_opt = (void *)pe;
-      pe->write_proc = write_grp_opt;
-      pe->read_proc = read_grp_opt;
-      pe->data = a; 
-    }
-    if((pe = create_proc_entry(d_l1_down_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) {
-      a->proc_d_l1_down = (void *)pe;
-      pe->write_proc = write_d_l1_down;
-      pe->read_proc = read_d_l1_down;
-      pe->data = a; 
-    }
-  
-    DBG_TRC(("proc entry %s created", tmp));
+int create_adapter_proc(diva_os_xdi_adapter_t * a)
+{
+	struct proc_dir_entry *de, *pe;
+	char tmp[16];
+
+	if (in_interrupt()) {
+		printk(KERN_ERR
+		       "divasproc: create_proc in_interrupt, not creating\n");
+		return (1);
+	}
+
+	sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
+	if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_isdn_eicon)))
+		return (0);
+	a->proc_adapter_dir = (void *) de;
+
+	if (!(pe =
+	     create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR,
+			       de))) return (0);
+	a->proc_info = (void *) pe;
+	pe->write_proc = info_write;
+	pe->read_proc = info_read;
+	pe->data = a;
+
+	if ((pe = create_proc_entry(grp_opt_proc_name,
+			       S_IFREG | S_IRUGO | S_IWUSR, de))) {
+		a->proc_grp_opt = (void *) pe;
+		pe->write_proc = write_grp_opt;
+		pe->read_proc = read_grp_opt;
+		pe->data = a;
+	}
+	if ((pe = create_proc_entry(d_l1_down_proc_name,
+			       S_IFREG | S_IRUGO | S_IWUSR, de))) {
+		a->proc_d_l1_down = (void *) pe;
+		pe->write_proc = write_d_l1_down;
+		pe->read_proc = read_d_l1_down;
+		pe->data = a;
+	}
 
-    return(1);
+	DBG_TRC(("proc entry %s created", tmp));
+
+	return (1);
 }
 
 /* --------------------------------------------------------------------------
     Remove adapter directory and files in proc file system
    -------------------------------------------------------------------------- */
-void remove_adapter_proc (diva_os_xdi_adapter_t* a) {
-  char tmp[16];
+void remove_adapter_proc(diva_os_xdi_adapter_t * a)
+{
+	char tmp[16];
 
-    if(a->proc_adapter_dir) {
-      if(a->proc_d_l1_down) {
-      remove_proc_entry (d_l1_down_proc_name,
-                         (struct proc_dir_entry *)a->proc_adapter_dir);
-      }
-      if(a->proc_grp_opt) {
-      remove_proc_entry (grp_opt_proc_name,
-                         (struct proc_dir_entry *)a->proc_adapter_dir);
-      }
-      if(a->proc_info) {
-      remove_proc_entry (info_proc_name,
-                         (struct proc_dir_entry *)a->proc_adapter_dir);
-      }
-      sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
-      remove_proc_entry(tmp, proc_net_isdn_eicon);
-      DBG_TRC(("proc entry %s%d removed", adapter_dir_name, a->controller));
-    }
+	if (a->proc_adapter_dir) {
+		if (a->proc_d_l1_down) {
+			remove_proc_entry(d_l1_down_proc_name,
+					  (struct proc_dir_entry *) a->proc_adapter_dir);
+		}
+		if (a->proc_grp_opt) {
+			remove_proc_entry(grp_opt_proc_name,
+					  (struct proc_dir_entry *) a->proc_adapter_dir);
+		}
+		if (a->proc_info) {
+			remove_proc_entry(info_proc_name,
+					  (struct proc_dir_entry *) a->proc_adapter_dir);
+		}
+		sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
+		remove_proc_entry(tmp, proc_net_isdn_eicon);
+		DBG_TRC(("proc entry %s%d removed", adapter_dir_name,
+			 a->controller));
+	}
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/dlist.c b/drivers/isdn/hardware/eicon/dlist.c
--- a/drivers/isdn/hardware/eicon/dlist.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/isdn/hardware/eicon/dlist.c	Sun Nov 17 20:30:02 2002
@@ -1,4 +1,4 @@
-/* $Id: dlist.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: dlist.c,v 1.1.2.2 2001/02/11 14:40:41 armin Exp $ */
 
 #include "platform.h"
 #include "dlist.h"
@@ -7,102 +7,92 @@
 **  Initialize linked list
 */
 
-void
-diva_q_init (diva_entity_queue_t* q)
+void diva_q_init(diva_entity_queue_t * q)
 {
-  memset (q, 0x00, sizeof(*q));
+	memset(q, 0x00, sizeof(*q));
 }
 
 /*
 **  Remove element from linked list
 */
-void
-diva_q_remove (diva_entity_queue_t* q, diva_entity_link_t* what)
+void diva_q_remove(diva_entity_queue_t * q, diva_entity_link_t * what)
 {
-  if(!what->prev) {
-    if ((q->head = what->next)) {
-      q->head->prev = 0;
-    } else {
-      q->tail = 0;
-    }
-  } else if (!what->next) {
-    q->tail = what->prev;
-    q->tail->next = 0;
-  } else {
-    what->prev->next = what->next;
-    what->next->prev = what->prev;
-  }
-  what->prev = what->next = 0;
+	if (!what->prev) {
+		if ((q->head = what->next)) {
+			q->head->prev = 0;
+		} else {
+			q->tail = 0;
+		}
+	} else if (!what->next) {
+		q->tail = what->prev;
+		q->tail->next = 0;
+	} else {
+		what->prev->next = what->next;
+		what->next->prev = what->prev;
+	}
+	what->prev = what->next = 0;
 }
 
 /*
 **  Add element to the tail of linked list
 */
-void
-diva_q_add_tail (diva_entity_queue_t* q, diva_entity_link_t* what)
+void diva_q_add_tail(diva_entity_queue_t * q, diva_entity_link_t * what)
 {
-  what->next = 0;
-  if (!q->head) {
-    what->prev = 0;
-    q->head = q->tail = what;
-  } else {
-    what->prev = q->tail;
-    q->tail->next = what;
-    q->tail = what;
-  }
+	what->next = 0;
+	if (!q->head) {
+		what->prev = 0;
+		q->head = q->tail = what;
+	} else {
+		what->prev = q->tail;
+		q->tail->next = what;
+		q->tail = what;
+	}
 }
 
-diva_entity_link_t*
-diva_q_find (const diva_entity_queue_t* q, const void* what,
-             diva_q_cmp_fn_t cmp_fn)
+diva_entity_link_t *diva_q_find(const diva_entity_queue_t * q,
+				const void *what, diva_q_cmp_fn_t cmp_fn)
 {
-  diva_entity_link_t* diva_current = q->head;
+	diva_entity_link_t *diva_current = q->head;
 
-  while (diva_current) {
-    if (!(*cmp_fn)(what, diva_current)) {
-      break;
-    }
-    diva_current = diva_current->next;
-  }
+	while (diva_current) {
+		if (!(*cmp_fn) (what, diva_current)) {
+			break;
+		}
+		diva_current = diva_current->next;
+	}
 
-  return (diva_current);
+	return (diva_current);
 }
 
-diva_entity_link_t*
-diva_q_get_head (diva_entity_queue_t* q)
+diva_entity_link_t *diva_q_get_head(diva_entity_queue_t * q)
 {
-  return (q->head);
+	return (q->head);
 }
 
-diva_entity_link_t*
-diva_q_get_tail (diva_entity_queue_t* q)
+diva_entity_link_t *diva_q_get_tail(diva_entity_queue_t * q)
 {
-  return (q->tail);
+	return (q->tail);
 }
 
-diva_entity_link_t*
-diva_q_get_next	(diva_entity_link_t* what)
+diva_entity_link_t *diva_q_get_next(diva_entity_link_t * what)
 {
-  return ((what) ? what->next : 0);
+	return ((what) ? what->next : 0);
 }
 
-diva_entity_link_t*
-diva_q_get_prev	(diva_entity_link_t* what)
+diva_entity_link_t *diva_q_get_prev(diva_entity_link_t * what)
 {
-  return ((what) ? what->prev : 0);
+	return ((what) ? what->prev : 0);
 }
 
-int
-diva_q_get_nr_of_entries (const diva_entity_queue_t* q)
+int diva_q_get_nr_of_entries(const diva_entity_queue_t * q)
 {
-  int i = 0;
-  const diva_entity_link_t* diva_current = q->head;
+	int i = 0;
+	const diva_entity_link_t *diva_current = q->head;
 
-  while (diva_current) {
-    i++;
-    diva_current = diva_current->next;
-  }
+	while (diva_current) {
+		i++;
+		diva_current = diva_current->next;
+	}
 
-  return (i);
+	return (i);
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/dlist.h b/drivers/isdn/hardware/eicon/dlist.h
--- a/drivers/isdn/hardware/eicon/dlist.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/dlist.h	Sun Nov 17 20:30:15 2002
@@ -1,32 +1,32 @@
-/* $Id: dlist.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: dlist.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
 
 #ifndef __DIVA_LINK_H__
 #define __DIVA_LINK_H__
 
 struct _diva_entity_link;
 typedef struct _diva_entity_link {
-	struct _diva_entity_link* prev;
-	struct _diva_entity_link* next;
+	struct _diva_entity_link *prev;
+	struct _diva_entity_link *next;
 } diva_entity_link_t;
 
 typedef struct _diva_entity_queue {
-	diva_entity_link_t* head;
-	diva_entity_link_t* tail;
+	diva_entity_link_t *head;
+	diva_entity_link_t *tail;
 } diva_entity_queue_t;
 
-typedef int (*diva_q_cmp_fn_t)(const void* what,
-                               const diva_entity_link_t*);
+typedef int (*diva_q_cmp_fn_t) (const void *what,
+				const diva_entity_link_t *);
 
-void diva_q_remove   (diva_entity_queue_t* q, diva_entity_link_t* what);
-void diva_q_add_tail (diva_entity_queue_t* q, diva_entity_link_t* what);
-diva_entity_link_t* diva_q_find (const diva_entity_queue_t* q,
-                                 const void* what, diva_q_cmp_fn_t cmp_fn);
-
-diva_entity_link_t* diva_q_get_head	(diva_entity_queue_t* q);
-diva_entity_link_t* diva_q_get_tail	(diva_entity_queue_t* q);
-diva_entity_link_t* diva_q_get_next	(diva_entity_link_t* what);
-diva_entity_link_t* diva_q_get_prev	(diva_entity_link_t* what);
-int diva_q_get_nr_of_entries (const diva_entity_queue_t* q);
-void diva_q_init (diva_entity_queue_t* q);
+void diva_q_remove(diva_entity_queue_t * q, diva_entity_link_t * what);
+void diva_q_add_tail(diva_entity_queue_t * q, diva_entity_link_t * what);
+diva_entity_link_t *diva_q_find(const diva_entity_queue_t * q,
+				const void *what, diva_q_cmp_fn_t cmp_fn);
+
+diva_entity_link_t *diva_q_get_head(diva_entity_queue_t * q);
+diva_entity_link_t *diva_q_get_tail(diva_entity_queue_t * q);
+diva_entity_link_t *diva_q_get_next(diva_entity_link_t * what);
+diva_entity_link_t *diva_q_get_prev(diva_entity_link_t * what);
+int diva_q_get_nr_of_entries(const diva_entity_queue_t * q);
+void diva_q_init(diva_entity_queue_t * q);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/dqueue.c b/drivers/isdn/hardware/eicon/dqueue.c
--- a/drivers/isdn/hardware/eicon/dqueue.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/dqueue.c	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,4 @@
-/* $Id: dqueue.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $
+/* $Id: dqueue.c,v 1.1.2.2 2001/02/11 14:40:41 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * User Mode IDI Interface
@@ -14,104 +14,97 @@
 #include "dqueue.h"
 
 int
-diva_data_q_init(diva_um_idi_data_queue_t* q,
-                 int max_length,
-                 int max_segments)
-{
-  int i;
-
-  q->max_length	= max_length;
-  q->segments = max_segments;
-	
-  for (i = 0; i < q->segments; i++) {
-    q->data[i] = 0;
-    q->length[i]  = 0;
-  }
-  q->read = q->write = q->count = q->segment_pending = 0;
-
-  for (i = 0; i < q->segments; i++) {
-    if (!(q->data[i] = diva_os_malloc (0, q->max_length))) {
-      diva_data_q_finit (q);
-      return (-1);
-    }
-  }
+diva_data_q_init(diva_um_idi_data_queue_t * q,
+		 int max_length, int max_segments)
+{
+	int i;
+
+	q->max_length = max_length;
+	q->segments = max_segments;
+
+	for (i = 0; i < q->segments; i++) {
+		q->data[i] = 0;
+		q->length[i] = 0;
+	}
+	q->read = q->write = q->count = q->segment_pending = 0;
 
-  return (0);
+	for (i = 0; i < q->segments; i++) {
+		if (!(q->data[i] = diva_os_malloc(0, q->max_length))) {
+			diva_data_q_finit(q);
+			return (-1);
+		}
+	}
+
+	return (0);
 }
 
-int
-diva_data_q_finit(diva_um_idi_data_queue_t* q)
+int diva_data_q_finit(diva_um_idi_data_queue_t * q)
 {
-  int i;
+	int i;
 
-  for (i = 0; i < q->segments; i++) {
-    if (q->data[i]) {
-      diva_os_free (0, q->data[i]);
-    }
-    q->data[i] = 0;
-    q->length[i] = 0;
-  }
-  q->read = q->write = q->count = q->segment_pending = 0;
+	for (i = 0; i < q->segments; i++) {
+		if (q->data[i]) {
+			diva_os_free(0, q->data[i]);
+		}
+		q->data[i] = 0;
+		q->length[i] = 0;
+	}
+	q->read = q->write = q->count = q->segment_pending = 0;
 
-  return (0);
+	return (0);
 }
 
-int
-diva_data_q_get_max_length(const diva_um_idi_data_queue_t* q)
+int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q)
 {
-  return (q->max_length);
+	return (q->max_length);
 }
 
-void*
-diva_data_q_get_segment4write(diva_um_idi_data_queue_t* q)
+void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q)
 {
-  if ((!q->segment_pending) && (q->count < q->segments)) {
-    q->segment_pending = 1;
-    return (q->data[q->write]);
-  }
+	if ((!q->segment_pending) && (q->count < q->segments)) {
+		q->segment_pending = 1;
+		return (q->data[q->write]);
+	}
 
-  return (0);
+	return (0);
 }
 
 void
-diva_data_q_ack_segment4write(diva_um_idi_data_queue_t* q, int length)
+diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q, int length)
 {
-  if (q->segment_pending) {
-    q->length[q->write] = length;
-    q->count++;
-    q->write++;
-    if (q->write >= q->segments) {
-      q->write = 0;
-    }
-    q->segment_pending = 0;
-  }
-}
-
-const void*
-diva_data_q_get_segment4read(const diva_um_idi_data_queue_t* q)
-{
-  if (q->count) {
-    return (q->data[q->read]);
-  }
-  return (0);
+	if (q->segment_pending) {
+		q->length[q->write] = length;
+		q->count++;
+		q->write++;
+		if (q->write >= q->segments) {
+			q->write = 0;
+		}
+		q->segment_pending = 0;
+	}
 }
 
-int
-diva_data_q_get_segment_length(const diva_um_idi_data_queue_t* q)
+const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t *
+					 q)
 {
-  return (q->length[q->read]);
+	if (q->count) {
+		return (q->data[q->read]);
+	}
+	return (0);
 }
 
-void
-diva_data_q_ack_segment4read(diva_um_idi_data_queue_t* q)
+int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q)
 {
-  if (q->count) {
-    q->length[q->read] = 0;
-    q->count--;
-    q->read++;
-    if (q->read >= q->segments) {
-      q->read = 0;
-    }
-  }
+	return (q->length[q->read]);
 }
 
+void diva_data_q_ack_segment4read(diva_um_idi_data_queue_t * q)
+{
+	if (q->count) {
+		q->length[q->read] = 0;
+		q->count--;
+		q->read++;
+		if (q->read >= q->segments) {
+			q->read = 0;
+		}
+	}
+}
diff -Nru a/drivers/isdn/hardware/eicon/dqueue.h b/drivers/isdn/hardware/eicon/dqueue.h
--- a/drivers/isdn/hardware/eicon/dqueue.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/dqueue.h	Sun Nov 17 20:30:15 2002
@@ -1,31 +1,31 @@
-/* $Id: dqueue.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: dqueue.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
 
 #ifndef _DIVA_USER_MODE_IDI_DATA_QUEUE_H__
 #define _DIVA_USER_MODE_IDI_DATA_QUEUE_H__
 
-#define DIVA_UM_IDI_MAX_MSGS 64 
+#define DIVA_UM_IDI_MAX_MSGS 64
 
 typedef struct _diva_um_idi_data_queue {
-	int		segments;
-	int		max_length;
-	int		read;
-	int		write;
-	int		count;
-	int		segment_pending;
-	void*	data[DIVA_UM_IDI_MAX_MSGS];
-	int		length[DIVA_UM_IDI_MAX_MSGS];
+	int segments;
+	int max_length;
+	int read;
+	int write;
+	int count;
+	int segment_pending;
+	void *data[DIVA_UM_IDI_MAX_MSGS];
+	int length[DIVA_UM_IDI_MAX_MSGS];
 } diva_um_idi_data_queue_t;
 
-int diva_data_q_init(diva_um_idi_data_queue_t* q,
-                      int max_length,
-                      int max_segments);
-int diva_data_q_finit(diva_um_idi_data_queue_t* q);
-int diva_data_q_get_max_length (const diva_um_idi_data_queue_t* q);
-void* diva_data_q_get_segment4write (diva_um_idi_data_queue_t* q);
-void diva_data_q_ack_segment4write (diva_um_idi_data_queue_t* q, int length);
-const void* diva_data_q_get_segment4read (const diva_um_idi_data_queue_t* q);
-int diva_data_q_get_segment_length (const diva_um_idi_data_queue_t* q);
-void diva_data_q_ack_segment4read (diva_um_idi_data_queue_t* q);
+int diva_data_q_init(diva_um_idi_data_queue_t * q,
+		     int max_length, int max_segments);
+int diva_data_q_finit(diva_um_idi_data_queue_t * q);
+int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q);
+void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q);
+void diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q,
+				   int length);
+const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t *
+					 q);
+int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q);
+void diva_data_q_ack_segment4read(diva_um_idi_data_queue_t * q);
 
 #endif
-
diff -Nru a/drivers/isdn/hardware/eicon/dsp_tst.h b/drivers/isdn/hardware/eicon/dsp_tst.h
--- a/drivers/isdn/hardware/eicon/dsp_tst.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/isdn/hardware/eicon/dsp_tst.h	Sun Nov 17 20:30:16 2002
@@ -1,4 +1,4 @@
-/* $Id: dsp_tst.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: dsp_tst.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
 
 #ifndef __DIVA_PRI_HOST_TEST_DSPS_H__
 #define __DIVA_PRI_HOST_TEST_DSPS_H__
@@ -18,7 +18,7 @@
 #define DSP10_PORT      (0x840)
 #define DSP11_PORT      (0x848)
 #define DSP12_PORT      (0x850)
-#define DSP13_PORT      (0x858)        
+#define DSP13_PORT      (0x858)
 #define DSP14_PORT      (0x860)
 #define DSP15_PORT      (0x868)
 #define DSP16_PORT      (0x870)
diff -Nru a/drivers/isdn/hardware/eicon/entity.h b/drivers/isdn/hardware/eicon/entity.h
--- a/drivers/isdn/hardware/eicon/entity.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/entity.h	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,4 @@
-/* $Id: entity.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: entity.h,v 1.1.2.1 2001/02/08 12:25:43 armin Exp $ */
 
 #ifndef __DIVAS_USER_MODE_IDI_ENTITY__
 #define __DIVAS_USER_MODE_IDI_ENTITY__
@@ -10,18 +10,18 @@
 #define DIVA_UM_IDI_ASSIGN_PENDING  0x00000010
 
 typedef struct _divas_um_idi_entity {
-  diva_entity_link_t        link; /* should be first */
-  diva_um_idi_adapter_t*    adapter; /* Back to adapter */
-  ENTITY                    e;
-  void*                     os_ref;
-  dword                     status;
-  void*                     os_context;
-  int                       rc_count;
-  diva_um_idi_data_queue_t  data; /* definad by user 1 ... MAX */
-  diva_um_idi_data_queue_t  rc;   /* two entries */
-  BUFFERS                   XData;
-  BUFFERS                   RData;
-  byte                      buffer[2048+512];
+	diva_entity_link_t        link; /* should be first */
+	diva_um_idi_adapter_t*    adapter; /* Back to adapter */
+	ENTITY                    e;
+	void*                     os_ref;
+	dword                     status;
+	void*                     os_context;
+	int                       rc_count;
+	diva_um_idi_data_queue_t  data; /* definad by user 1 ... MAX */
+	diva_um_idi_data_queue_t  rc;   /* two entries */
+	BUFFERS                   XData;
+	BUFFERS                   RData;
+	byte                      buffer[2048+512];
 } divas_um_idi_entity_t;
 
 
diff -Nru a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
--- a/drivers/isdn/hardware/eicon/idifunc.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/idifunc.c	Sun Nov 17 20:30:15 2002
@@ -21,9 +21,9 @@
 
 extern char *DRIVERRELEASE;
 
-extern void DIVA_DIDD_Read (void *, int);
-extern int diva_user_mode_idi_create_adapter (const DESCRIPTOR*, int);
-extern void diva_user_mode_idi_remove_adapter (int);
+extern void DIVA_DIDD_Read(void *, int);
+extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);
+extern void diva_user_mode_idi_remove_adapter(int);
 
 #define MAX_DESCRIPTORS  32
 
@@ -31,10 +31,11 @@
 static DESCRIPTOR DAdapter;
 static DESCRIPTOR MAdapter;
 
-static void no_printf (unsigned char * x ,...)
+static void no_printf(unsigned char *x, ...)
 {
-  /* dummy debug function */
+	/* dummy debug function */
 }
+
 DIVA_DI_PRINTF dprintf = no_printf;
 
 #include "debuglib.c"
@@ -44,15 +45,15 @@
  */
 static void stop_dbg(void)
 {
-		DbgDeregister();
-		memset(&MAdapter, 0, sizeof(MAdapter));
-		dprintf = no_printf;
+	DbgDeregister();
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
 
 typedef struct _udiva_card {
-    struct _udiva_card *next;
-    int Id;
-    DESCRIPTOR  d;
+	struct _udiva_card *next;
+	int Id;
+	DESCRIPTOR d;
 } udiva_card;
 
 static udiva_card *cards;
@@ -61,104 +62,108 @@
 /*
  * add card to list
  */
-static void add_card_to_list(udiva_card *c)
+static void add_card_to_list(udiva_card * c)
 {
 	diva_os_spin_lock_magic_t old_irql;
-	
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "add card");
-  c->next = cards;
-  cards = c;
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "add card");
+
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");
+	c->next = cards;
+	cards = c;
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");
 }
 
 /*
  * find card in list
  */
-static udiva_card * find_card_in_list(DESCRIPTOR *d)
+static udiva_card *find_card_in_list(DESCRIPTOR * d)
 {
-  udiva_card *card;
+	udiva_card *card;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "find card");
-  card = cards;
-  while(card) {
-    if (card->d.request == d->request) {
-			diva_os_leave_spin_lock (&ll_lock, &old_irql, "find card");
-      return(card);
-    }
-    card = card->next;
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "find card");
-  return((udiva_card *)NULL);
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card");
+	card = cards;
+	while (card) {
+		if (card->d.request == d->request) {
+			diva_os_leave_spin_lock(&ll_lock, &old_irql,
+						"find card");
+			return (card);
+		}
+		card = card->next;
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card");
+	return ((udiva_card *) NULL);
 }
 
 /*
  * remove card from list
  */
-static void remove_card_from_list(udiva_card *c)
+static void remove_card_from_list(udiva_card * c)
 {
-  udiva_card *list = NULL, *last;
+	udiva_card *list = NULL, *last;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "remove card");
-  list = cards;
-  last = list;
-  while(list) {
-    if(list == c) {
-      if(cards == c) {
-        cards = c->next;
-      } else {
-        last->next = c->next;
-      }
-      break;
-    }
-    last = list;
-    list = list->next;
-  }
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "remove card");
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");
+	list = cards;
+	last = list;
+	while (list) {
+		if (list == c) {
+			if (cards == c) {
+				cards = c->next;
+			} else {
+				last->next = c->next;
+			}
+			break;
+		}
+		last = list;
+		list = list->next;
+	}
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");
 }
 
 /*
  * new card
  */
-static void um_new_card(DESCRIPTOR *d)
+static void um_new_card(DESCRIPTOR * d)
 {
-  int adapter_nr = 0;
-  udiva_card *card = NULL;
-  IDI_SYNC_REQ sync_req;
-
-  if(!(card = diva_os_malloc(0, sizeof(udiva_card)))) {
-    DBG_ERR(("cannot get buffer for card"));
-    return;
-  }
-  memcpy(&card->d, d, sizeof(DESCRIPTOR));
-  sync_req.xdi_logical_adapter_number.Req = 0;
-  sync_req.xdi_logical_adapter_number.Rc = IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
-  card->d.request((ENTITY *)&sync_req);
-  adapter_nr = sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
-  card->Id = adapter_nr;
-  if(!(diva_user_mode_idi_create_adapter(d, adapter_nr))) {
-    add_card_to_list(card);
-  } else {
-    DBG_ERR(("could not create user mode idi card %d", adapter_nr));
-  }
+	int adapter_nr = 0;
+	udiva_card *card = NULL;
+	IDI_SYNC_REQ sync_req;
+
+	if (!(card = diva_os_malloc(0, sizeof(udiva_card)))) {
+		DBG_ERR(("cannot get buffer for card"));
+		return;
+	}
+	memcpy(&card->d, d, sizeof(DESCRIPTOR));
+	sync_req.xdi_logical_adapter_number.Req = 0;
+	sync_req.xdi_logical_adapter_number.Rc =
+	    IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
+	card->d.request((ENTITY *) & sync_req);
+	adapter_nr =
+	    sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
+	card->Id = adapter_nr;
+	if (!(diva_user_mode_idi_create_adapter(d, adapter_nr))) {
+		add_card_to_list(card);
+	} else {
+		DBG_ERR(("could not create user mode idi card %d",
+			 adapter_nr));
+	}
 }
 
 /*
  * remove card
  */
-static void um_remove_card(DESCRIPTOR *d)
+static void um_remove_card(DESCRIPTOR * d)
 {
-  udiva_card *card = NULL;
+	udiva_card *card = NULL;
 
-  if(!(card = find_card_in_list(d))) {
-    DBG_ERR(("cannot find card to remove"));
-    return;
-  }
-  diva_user_mode_idi_remove_adapter(card->Id);
-  remove_card_from_list(card);
-  DBG_LOG(("idi proc entry removed for card %d", card->Id));
-  diva_os_free(0, card);
+	if (!(card = find_card_in_list(d))) {
+		DBG_ERR(("cannot find card to remove"));
+		return;
+	}
+	diva_user_mode_idi_remove_adapter(card->Id);
+	remove_card_from_list(card);
+	DBG_LOG(("idi proc entry removed for card %d", card->Id));
+	diva_os_free(0, card);
 }
 
 /*
@@ -166,58 +171,47 @@
  */
 static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)
 {
-  udiva_card *card, *last;
+	udiva_card *card, *last;
 	diva_os_spin_lock_magic_t old_irql;
 
-	diva_os_enter_spin_lock (&ll_lock, &old_irql, "remove all");
-  card = cards;
-  cards = NULL;
-	diva_os_leave_spin_lock (&ll_lock, &old_irql, "remove all");
-
-  while(card) {
-    diva_user_mode_idi_remove_adapter(card->Id);
-    last = card;
-    card = card->next;
-    diva_os_free(0, last);
-  }
+	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove all");
+	card = cards;
+	cards = NULL;
+	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");
+
+	while (card) {
+		diva_user_mode_idi_remove_adapter(card->Id);
+		last = card;
+		card = card->next;
+		diva_os_free(0, last);
+	}
 }
 
 /*
  * DIDD notify callback
  */
-static void * didd_callback(void *context, DESCRIPTOR* adapter, int removal)
+static void *didd_callback(void *context, DESCRIPTOR * adapter,
+			   int removal)
 {
-  if (adapter->type == IDI_DADAPTER)
-  {
-    DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
-    return(NULL);
-  }
-  else if (adapter->type == IDI_DIMAINT)
-  {
-    if (removal)
-    {
-				stop_dbg();
-    }
-    else
-    {
-      memcpy(&MAdapter, adapter, sizeof(MAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT);
-    }
-  }
-  else if ((adapter->type > 0) &&
-           (adapter->type < 16))
-  {  /* IDI Adapter */
-    if (removal)
-    {
-      um_remove_card(adapter);
-    }
-    else
-    {
-      um_new_card(adapter);
-    }
-  }
-  return(NULL);
+	if (adapter->type == IDI_DADAPTER) {
+		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
+		return (NULL);
+	} else if (adapter->type == IDI_DIMAINT) {
+		if (removal) {
+			stop_dbg();
+		} else {
+			memcpy(&MAdapter, adapter, sizeof(MAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT);
+		}
+	} else if ((adapter->type > 0) && (adapter->type < 16)) {	/* IDI Adapter */
+		if (removal) {
+			um_remove_card(adapter);
+		} else {
+			um_new_card(adapter);
+		}
+	}
+	return (NULL);
 }
 
 /*
@@ -225,50 +219,43 @@
  */
 static int DIVA_INIT_FUNCTION connect_didd(void)
 {
-  int x = 0;
-  int dadapter = 0;
-  IDI_SYNC_REQ req;
-  DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
-
-  DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
-
-  for (x = 0; x < MAX_DESCRIPTORS; x++)
-  {
-    if (DIDD_Table[x].type == IDI_DADAPTER)
-    {  /* DADAPTER found */
-      dadapter = 1;
-      memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      req.didd_notify.e.Req = 0;
-      req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
-      req.didd_notify.info.callback = didd_callback;
-      req.didd_notify.info.context = 0;
-      DAdapter.request((ENTITY *)&req);
-      if (req.didd_notify.e.Rc != 0xff)
-			{
-					stop_dbg();
-					return(0);
+	int x = 0;
+	int dadapter = 0;
+	IDI_SYNC_REQ req;
+	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
+	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
+			dadapter = 1;
+			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			req.didd_notify.e.Req = 0;
+			req.didd_notify.e.Rc =
+			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
+			req.didd_notify.info.callback = didd_callback;
+			req.didd_notify.info.context = 0;
+			DAdapter.request((ENTITY *) & req);
+			if (req.didd_notify.e.Rc != 0xff) {
+				stop_dbg();
+				return (0);
 			}
-      notify_handle = req.didd_notify.info.handle;
-    }
-    else if (DIDD_Table[x].type == IDI_DIMAINT)
-    {  /* MAINT found */
-      memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT);
-    }
-    else if ((DIDD_Table[x].type > 0) &&
-             (DIDD_Table[x].type < 16))
-    {  /* IDI Adapter found */
-      um_new_card(&DIDD_Table[x]);
-    }
-  }
+			notify_handle = req.didd_notify.info.handle;
+		} else if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
+			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT);
+		} else if ((DIDD_Table[x].type > 0)
+			   && (DIDD_Table[x].type < 16)) {	/* IDI Adapter found */
+			um_new_card(&DIDD_Table[x]);
+		}
+	}
 
-	if (!dadapter)
-	{
-			stop_dbg();
+	if (!dadapter) {
+		stop_dbg();
 	}
-	
-  return(dadapter);
+
+	return (dadapter);
 }
 
 /*
@@ -276,14 +263,14 @@
  */
 static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 {
-  IDI_SYNC_REQ req;
+	IDI_SYNC_REQ req;
 
 	stop_dbg();
 
-  req.didd_notify.e.Req = 0;
-  req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
-  req.didd_notify.info.handle = notify_handle;
-  DAdapter.request((ENTITY *)&req);
+	req.didd_notify.e.Req = 0;
+	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
+	req.didd_notify.info.handle = notify_handle;
+	DAdapter.request((ENTITY *) & req);
 }
 
 /*
@@ -291,19 +278,19 @@
  */
 int DIVA_INIT_FUNCTION idifunc_init(void)
 {
-	diva_os_initialize_spin_lock (&ll_lock, "idifunc");
+	diva_os_initialize_spin_lock(&ll_lock, "idifunc");
+
+	if (diva_user_mode_idi_init()) {
+		DBG_ERR(("init: init failed."));
+		return (0);
+	}
 
-	if (diva_user_mode_idi_init ()) {
-    DBG_ERR(("init: init failed."));
-		return(0);
-  }
-
-	if(!connect_didd()) {
-		diva_user_mode_idi_finit ();
-    DBG_ERR(("init: failed to connect to DIDD."));
-		return(0);
-  }
-  return(1);
+	if (!connect_didd()) {
+		diva_user_mode_idi_finit();
+		DBG_ERR(("init: failed to connect to DIDD."));
+		return (0);
+	}
+	return (1);
 }
 
 /*
@@ -311,8 +298,7 @@
  */
 void DIVA_EXIT_FUNCTION idifunc_finit(void)
 {
-  diva_user_mode_idi_finit ();
-  disconnect_didd();
-  remove_all_idi_proc();
+	diva_user_mode_idi_finit();
+	disconnect_didd();
+	remove_all_idi_proc();
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
--- a/drivers/isdn/hardware/eicon/mntfunc.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/isdn/hardware/eicon/mntfunc.c	Sun Nov 17 20:30:02 2002
@@ -22,24 +22,29 @@
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
-extern void DIVA_DIDD_Read (void *, int);
+extern void DIVA_DIDD_Read(void *, int);
 
 #define MAX_DESCRIPTORS  32
 
 static dword notify_handle;
 static DESCRIPTOR DAdapter;
 static DESCRIPTOR MAdapter;
-static DESCRIPTOR MaintDescriptor = { IDI_DIMAINT, 0, 0, (IDI_CALL)diva_maint_prtComp };
+static DESCRIPTOR MaintDescriptor =
+    { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
 
-extern void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size);
-extern void diva_os_free_tbuffer(unsigned long flags, void* ptr);
-extern int diva_os_copy_to_user(void* os_handle, void* dst, const void* src, int length);
-extern int diva_os_copy_from_user(void* os_handle, void* dst, const void* src, int length);
+extern void *diva_os_malloc_tbuffer(unsigned long flags,
+				    unsigned long size);
+extern void diva_os_free_tbuffer(unsigned long flags, void *ptr);
+extern int diva_os_copy_to_user(void *os_handle, void *dst,
+				const void *src, int length);
+extern int diva_os_copy_from_user(void *os_handle, void *dst,
+				  const void *src, int length);
 
-static void no_printf (unsigned char * x ,...)
+static void no_printf(unsigned char *x, ...)
 {
-  /* dummy debug function */
+	/* dummy debug function */
 }
+
 DIVA_DI_PRINTF dprintf = no_printf;
 
 #include "debuglib.c"
@@ -49,34 +54,35 @@
  */
 static void stop_dbg(void)
 {
-  DbgDeregister();
-  memset(&MAdapter, 0, sizeof(MAdapter));
-  dprintf = no_printf;
+	DbgDeregister();
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
 
 /*
  *  DIDD callback function
  */
-static void * didd_callback (void *context, DESCRIPTOR* adapter, int removal)
+static void *didd_callback(void *context, DESCRIPTOR * adapter,
+			   int removal)
 {
-  if (adapter->type == IDI_DADAPTER) {
-    DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
-  } else if (adapter->type == IDI_DIMAINT) {
-    if (removal) {
-      stop_dbg();
-    } else {
-      memcpy(&MAdapter, adapter, sizeof(MAdapter));
-      dprintf = (DIVA_DI_PRINTF)MAdapter.request;
-      DbgRegister("MAINT", DRIVERRELEASE, DBG_DEFAULT);
-    }
-  } else if ((adapter->type > 0) && (adapter->type < 16)) {
-    if (removal) {
-      diva_mnt_remove_xdi_adapter(adapter);
-    } else {
-      diva_mnt_add_xdi_adapter(adapter);
-    }
-  }
-	return(NULL);
+	if (adapter->type == IDI_DADAPTER) {
+		DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
+	} else if (adapter->type == IDI_DIMAINT) {
+		if (removal) {
+			stop_dbg();
+		} else {
+			memcpy(&MAdapter, adapter, sizeof(MAdapter));
+			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
+			DbgRegister("MAINT", DRIVERRELEASE, DBG_DEFAULT);
+		}
+	} else if ((adapter->type > 0) && (adapter->type < 16)) {
+		if (removal) {
+			diva_mnt_remove_xdi_adapter(adapter);
+		} else {
+			diva_mnt_add_xdi_adapter(adapter);
+		}
+	}
+	return (NULL);
 }
 
 /*
@@ -84,39 +90,41 @@
  */
 static int DIVA_INIT_FUNCTION connect_didd(void)
 {
-  int x = 0;
-  int dadapter = 0;
-  IDI_SYNC_REQ req;
-  DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
-
-  DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
-
-  for (x = 0; x < MAX_DESCRIPTORS; x++)
-  {
-    if (DIDD_Table[x].type == IDI_DADAPTER)
-    {  /* DADAPTER found */
-      dadapter = 1;
-      memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
-      req.didd_notify.e.Req = 0;
-      req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
-      req.didd_notify.info.callback = didd_callback;
-      req.didd_notify.info.context = 0;
-      DAdapter.request((ENTITY *)&req);
-      if (req.didd_notify.e.Rc != 0xff)
-        return(0);
-      notify_handle = req.didd_notify.info.handle;
-      /* Register MAINT (me) */
-      req.didd_add_adapter.e.Req = 0;
-      req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
-      req.didd_add_adapter.info.descriptor = (void *)&MaintDescriptor;
-      DAdapter.request((ENTITY *)&req);
-      if (req.didd_add_adapter.e.Rc != 0xff)
-        return(0);
-    } else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) {
-      diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
-    }
-  }
-  return(dadapter);
+	int x = 0;
+	int dadapter = 0;
+	IDI_SYNC_REQ req;
+	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
+	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+	for (x = 0; x < MAX_DESCRIPTORS; x++) {
+		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
+			dadapter = 1;
+			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
+			req.didd_notify.e.Req = 0;
+			req.didd_notify.e.Rc =
+			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
+			req.didd_notify.info.callback = didd_callback;
+			req.didd_notify.info.context = 0;
+			DAdapter.request((ENTITY *) & req);
+			if (req.didd_notify.e.Rc != 0xff)
+				return (0);
+			notify_handle = req.didd_notify.info.handle;
+			/* Register MAINT (me) */
+			req.didd_add_adapter.e.Req = 0;
+			req.didd_add_adapter.e.Rc =
+			    IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
+			req.didd_add_adapter.info.descriptor =
+			    (void *) &MaintDescriptor;
+			DAdapter.request((ENTITY *) & req);
+			if (req.didd_add_adapter.e.Rc != 0xff)
+				return (0);
+		} else if ((DIDD_Table[x].type > 0)
+			   && (DIDD_Table[x].type < 16)) {
+			diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
+		}
+	}
+	return (dadapter);
 }
 
 /*
@@ -124,191 +132,203 @@
  */
 static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 {
-  IDI_SYNC_REQ req;
+	IDI_SYNC_REQ req;
 
 	stop_dbg();
 
-  req.didd_notify.e.Req = 0;
-  req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
-  req.didd_notify.info.handle = notify_handle;
-  DAdapter.request((ENTITY *)&req);
-
-  req.didd_remove_adapter.e.Req = 0;
-  req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
-  req.didd_remove_adapter.info.p_request = (IDI_CALL)MaintDescriptor.request;
-  DAdapter.request((ENTITY *)&req);
+	req.didd_notify.e.Req = 0;
+	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
+	req.didd_notify.info.handle = notify_handle;
+	DAdapter.request((ENTITY *) & req);
+
+	req.didd_remove_adapter.e.Req = 0;
+	req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
+	req.didd_remove_adapter.info.p_request =
+	    (IDI_CALL) MaintDescriptor.request;
+	DAdapter.request((ENTITY *) & req);
 }
 
 /*
  * read/write maint
  */
-int maint_read_write(void * buf)
+int maint_read_write(void *buf)
 {
-  byte data[128];
-  dword cmd, id, mask;
-  int ret = 0;
-
-  if (diva_os_copy_from_user(NULL, (void *)&data[0], buf, 3*sizeof(dword))) {
-    return(-EFAULT);
-  }
-
-  cmd  = *(dword *)&data[0]; /* command */
-  id   = *(dword *)&data[4]; /* driver id */
-  mask = *(dword *)&data[8]; /* mask or size */
-
-  switch (cmd) {
-    case DITRACE_CMD_GET_DRIVER_INFO:
-      if ((ret = diva_get_driver_info (id, data, sizeof(data))) > 0) {
-        if (diva_os_copy_to_user(NULL, buf, (void*)&data[0], ret))
-          ret = -EFAULT;
-      } else {
-        ret = -EINVAL;
-      }
-      break;
-
-    case DITRACE_READ_DRIVER_DBG_MASK:
-      if ((ret = diva_get_driver_dbg_mask (id, (byte*)data)) > 0) {
-        if (diva_os_copy_to_user(NULL, buf, (void*)&data[0], ret))
-          ret = -EFAULT;
-      } else {
-        ret = -ENODEV;
-      }
-      break;
-
-    case DITRACE_WRITE_DRIVER_DBG_MASK:
-      if ((ret = diva_set_driver_dbg_mask (id, mask)) <= 0) {
-        ret = -ENODEV;
-      }
-      break;
-
-    case DITRACE_READ_TRACE_ENTRY: {
-      diva_os_spin_lock_magic_t old_irql;
-      word size;
-      diva_dbg_entry_head_t* pmsg;
-      byte* pbuf;
-
-      if ((pmsg = diva_maint_get_message (&size, &old_irql))) {
-        if (size > mask) {
-          diva_maint_ack_message (0, &old_irql);
-          ret = -EINVAL;
-        } else {
-          if (!(pbuf = diva_os_malloc_tbuffer(0, size))) {
-            diva_maint_ack_message (0, &old_irql);
-            ret = -ENOMEM;
-          } else {
-            ret = size;
-            memcpy (pbuf, pmsg, size);
-            diva_maint_ack_message (1, &old_irql);
-            if (diva_os_copy_to_user(NULL, buf, (void*)pbuf, size))
-              ret = -EFAULT;
-            diva_os_free_tbuffer(0, pbuf);
-          }
-        }
-      } else {
-        ret = 0;
-      }
-    } break;
-
-    case DITRACE_READ_TRACE_ENTRYS: {
-      diva_os_spin_lock_magic_t old_irql;
-      word size;
-      diva_dbg_entry_head_t* pmsg;
-      byte* pbuf = 0;
-      int written = 0;
-
-      if (mask < 4096) {
-        ret = -EINVAL;
-        break;
-      }
-      if (!(pbuf = diva_os_malloc_tbuffer(0, mask))) {
-        return (-ENOMEM);
-      }
-
-      for (;;) {
-        if (!(pmsg = diva_maint_get_message (&size, &old_irql))) {
-          break;
-        }
-        if ((size+8) > mask) {
-          diva_maint_ack_message (0, &old_irql);
-          break;
-        }
-        /*
-          Write entry length
-          */
-        pbuf[written++] = (byte)size;
-        pbuf[written++] = (byte)(size >> 8);
-        pbuf[written++] = 0;
-        pbuf[written++] = 0;
-        /*
-          Write message
-          */
-        memcpy (&pbuf[written], pmsg, size);
-        diva_maint_ack_message (1, &old_irql);
-        written += size;
-        mask -= (size+4);
-      }
-      pbuf[written++] = 0;
-      pbuf[written++] = 0;
-      pbuf[written++] = 0;
-      pbuf[written++] = 0;
-
-      if (diva_os_copy_to_user(NULL, buf, (void*)pbuf, written)) {
-        ret = -EFAULT;
-      } else {
-        ret = written;
-      }
-      diva_os_free_tbuffer(0, pbuf);
-    } break;
-
-    default:
-      ret = -EINVAL;
-  }
-  return (ret);
+	byte data[128];
+	dword cmd, id, mask;
+	int ret = 0;
+
+	if (diva_os_copy_from_user(NULL, (void *) &data[0],
+				   buf, 3 * sizeof(dword))) {
+		return (-EFAULT);
+	}
+
+	cmd = *(dword *) & data[0];	/* command */
+	id = *(dword *) & data[4];	/* driver id */
+	mask = *(dword *) & data[8];	/* mask or size */
+
+	switch (cmd) {
+	case DITRACE_CMD_GET_DRIVER_INFO:
+		if ((ret = diva_get_driver_info(id, data, sizeof(data))) > 0) {
+			if (diva_os_copy_to_user
+			    (NULL, buf, (void *) &data[0], ret))
+				ret = -EFAULT;
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+
+	case DITRACE_READ_DRIVER_DBG_MASK:
+		if ((ret = diva_get_driver_dbg_mask(id, (byte *) data)) > 0) {
+			if (diva_os_copy_to_user
+			    (NULL, buf, (void *) &data[0], ret))
+				ret = -EFAULT;
+		} else {
+			ret = -ENODEV;
+		}
+		break;
+
+	case DITRACE_WRITE_DRIVER_DBG_MASK:
+		if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
+			ret = -ENODEV;
+		}
+		break;
+
+	case DITRACE_READ_TRACE_ENTRY:{
+			diva_os_spin_lock_magic_t old_irql;
+			word size;
+			diva_dbg_entry_head_t *pmsg;
+			byte *pbuf;
+
+			if ((pmsg = diva_maint_get_message(&size, &old_irql))) {
+				if (size > mask) {
+					diva_maint_ack_message(0, &old_irql);
+					ret = -EINVAL;
+				} else {
+					if (!(pbuf = diva_os_malloc_tbuffer(0, size)))
+					{
+						diva_maint_ack_message(0, &old_irql);
+						ret = -ENOMEM;
+					} else {
+						ret = size;
+						memcpy(pbuf, pmsg, size);
+						diva_maint_ack_message(1, &old_irql);
+						if (diva_os_copy_to_user (NULL, buf,
+						     (void *) pbuf, size))
+							ret = -EFAULT;
+						diva_os_free_tbuffer(0, pbuf);
+					}
+				}
+			} else {
+				ret = 0;
+			}
+		}
+		break;
+
+	case DITRACE_READ_TRACE_ENTRYS:{
+			diva_os_spin_lock_magic_t old_irql;
+			word size;
+			diva_dbg_entry_head_t *pmsg;
+			byte *pbuf = 0;
+			int written = 0;
+
+			if (mask < 4096) {
+				ret = -EINVAL;
+				break;
+			}
+			if (!(pbuf = diva_os_malloc_tbuffer(0, mask))) {
+				return (-ENOMEM);
+			}
+
+			for (;;) {
+				if (!(pmsg =
+				     diva_maint_get_message(&size, &old_irql))) {
+					break;
+				}
+				if ((size + 8) > mask) {
+					diva_maint_ack_message(0, &old_irql);
+					break;
+				}
+				/*
+				   Write entry length
+				 */
+				pbuf[written++] = (byte) size;
+				pbuf[written++] = (byte) (size >> 8);
+				pbuf[written++] = 0;
+				pbuf[written++] = 0;
+				/*
+				   Write message
+				 */
+				memcpy(&pbuf[written], pmsg, size);
+				diva_maint_ack_message(1, &old_irql);
+				written += size;
+				mask -= (size + 4);
+			}
+			pbuf[written++] = 0;
+			pbuf[written++] = 0;
+			pbuf[written++] = 0;
+			pbuf[written++] = 0;
+
+			if (diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
+				ret = -EFAULT;
+			} else {
+				ret = written;
+			}
+			diva_os_free_tbuffer(0, pbuf);
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+	return (ret);
 }
 
 /*
  *  init
  */
-int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer, unsigned long diva_dbg_mem)
+int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
+				    unsigned long diva_dbg_mem)
 {
-  if (*buffer_length < 64) {
-    *buffer_length = 64;
-  }
-  if (*buffer_length > 512) {
-    *buffer_length = 512;
-  }
-  *buffer_length *= 1024;
-
-  if (diva_dbg_mem) {
-    *buffer = (void*)diva_dbg_mem;
-  } else {
-    while ((*buffer_length >= (64*1024)) && (!(*buffer = diva_os_malloc_tbuffer(0, *buffer_length)))) {
-      *buffer_length -= 1024;
-    }
-  
-    if (!*buffer) {
-      DBG_ERR(("init: Can not alloc trace buffer"));
-      return(0);
-    }
-  }
-
-  if (diva_maint_init (*buffer, *buffer_length, (diva_dbg_mem == 0))) {
-    if (!diva_dbg_mem) {
-      diva_os_free_tbuffer(0, *buffer);
-    }
+	if (*buffer_length < 64) {
+		*buffer_length = 64;
+	}
+	if (*buffer_length > 512) {
+		*buffer_length = 512;
+	}
+	*buffer_length *= 1024;
+
+	if (diva_dbg_mem) {
+		*buffer = (void *) diva_dbg_mem;
+	} else {
+		while ((*buffer_length >= (64 * 1024))
+		       &&
+		       (!(*buffer = diva_os_malloc_tbuffer(0, *buffer_length)))) {
+			*buffer_length -= 1024;
+		}
+
+		if (!*buffer) {
+			DBG_ERR(("init: Can not alloc trace buffer"));
+			return (0);
+		}
+	}
+
+	if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
+		if (!diva_dbg_mem) {
+			diva_os_free_tbuffer(0, *buffer);
+		}
 		DBG_ERR(("init: maint init failed"));
-    return(0);
-  }
+		return (0);
+	}
 
-  if (!connect_didd()) {
-    DBG_ERR(("init: failed to connect to DIDD."));
-    diva_maint_finit();
-    if (!diva_dbg_mem) {
-      diva_os_free_tbuffer(0, *buffer);
-    }
-		return(0);
-  }
-  return(1);  
+	if (!connect_didd()) {
+		DBG_ERR(("init: failed to connect to DIDD."));
+		diva_maint_finit();
+		if (!diva_dbg_mem) {
+			diva_os_free_tbuffer(0, *buffer);
+		}
+		return (0);
+	}
+	return (1);
 }
 
 /*
@@ -316,17 +336,16 @@
  */
 void DIVA_EXIT_FUNCTION mntfunc_finit(void)
 {
-  void* buffer;
-  int i = 100;
+	void *buffer;
+	int i = 100;
 
-  while (diva_mnt_shutdown_xdi_adapters () && i--) {
-			diva_os_sleep(10);
-  }
+	while (diva_mnt_shutdown_xdi_adapters() && i--) {
+		diva_os_sleep(10);
+	}
 
-  disconnect_didd();
+	disconnect_didd();
 
-  if ((buffer = diva_maint_finit ())) {
+	if ((buffer = diva_maint_finit())) {
 		diva_os_free_tbuffer(0, buffer);
-  }
+	}
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
--- a/drivers/isdn/hardware/eicon/os_4bri.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/isdn/hardware/eicon/os_4bri.c	Sun Nov 17 20:30:13 2002
@@ -1,4 +1,4 @@
-/* $Id: os_4bri.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ */
+/* $Id: os_4bri.c,v 1.1.2.3 2001/02/14 21:10:19 armin Exp $ */
 
 #include "platform.h"
 #include "debuglib.h"
@@ -8,7 +8,7 @@
 #include "pr_pc.h"
 #include "di_defs.h"
 #include "dsp_defs.h"
-#include "di.h" 
+#include "di.h"
 #include "io.h"
 
 #include "xdi_msg.h"
@@ -18,87 +18,83 @@
 #include "mi_pc.h"
 #include "dsrv4bri.h"
 
-void* diva_xdiLoadFileFile   = 0;
+void *diva_xdiLoadFileFile = 0;
 dword diva_xdiLoadFileLength = 0;
 
 /*
 **  IMPORTS
 */
-extern void prepare_qBri_functions (PISDN_ADAPTER IoAdapter);
-extern void prepare_qBri2_functions (PISDN_ADAPTER IoAdapter);
-extern void diva_xdi_display_adapter_features (int card);
-extern void diva_add_slave_adapter (diva_os_xdi_adapter_t* a);
+extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
+extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
+extern void diva_xdi_display_adapter_features(int card);
+extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a);
 
-extern int qBri_FPGA_download (PISDN_ADAPTER IoAdapter);
-extern void start_qBri_hardware (PISDN_ADAPTER IoAdapter);
+extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
+extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
 
-extern int diva_card_read_xlog (diva_os_xdi_adapter_t* a);
+extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
 
 /*
 **  LOCALS
 */
 static unsigned long _4bri_bar_length[4] = {
-  0x100,
-  0x100, /* I/O */
-  MQ_MEMORY_SIZE,
-  0x2000
+	0x100,
+	0x100,			/* I/O */
+	MQ_MEMORY_SIZE,
+	0x2000
 };
 static unsigned long _4bri_v2_bar_length[4] = {
-  0x100,
-  0x100, /* I/O */
-  MQ2_MEMORY_SIZE,
-  0x10000
+	0x100,
+	0x100,			/* I/O */
+	MQ2_MEMORY_SIZE,
+	0x10000
 };
 static unsigned long _4bri_v2_bri_bar_length[4] = {
-  0x100,
-  0x100, /* I/O */
-  BRI2_MEMORY_SIZE,
-  0x10000
+	0x100,
+	0x100,			/* I/O */
+	BRI2_MEMORY_SIZE,
+	0x10000
 };
 
 
-static int diva_4bri_cleanup_adapter (diva_os_xdi_adapter_t* a);
-static int _4bri_get_serial_number (diva_os_xdi_adapter_t* a);
-static int diva_4bri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                                    diva_xdi_um_cfg_cmd_t* cmd,
-                                    int length);
-static int diva_4bri_cleanup_slave_adapters (diva_os_xdi_adapter_t* a);
-static int diva_4bri_write_fpga_image (diva_os_xdi_adapter_t* a,
-                                       byte* data,
-                                       dword length);
-static int diva_4bri_reset_adapter (PISDN_ADAPTER IoAdapter);
-static int diva_4bri_write_sdram_block (PISDN_ADAPTER IoAdapter,
-                                        dword address,
-                                        const byte* data,
-                                        dword length,
-                                        dword limit);
-static int diva_4bri_start_adapter (PISDN_ADAPTER IoAdapter,
-                                    dword start_address,
-                                    dword features);
-static int check_qBri_interrupt (PISDN_ADAPTER IoAdapter);
-static int diva_4bri_stop_adapter (diva_os_xdi_adapter_t* a);
+static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
+static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a);
+static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+				   diva_xdi_um_cfg_cmd_t * cmd,
+				   int length);
+static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a);
+static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,
+				      byte * data, dword length);
+static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
+static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
+				       dword address,
+				       const byte * data,
+				       dword length, dword limit);
+static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
+				   dword start_address, dword features);
+static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
+static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a);
 
-static int
-_4bri_is_rev_2_card (int card_ordinal)
+static int _4bri_is_rev_2_card(int card_ordinal)
 {
-  switch (card_ordinal) {
-    case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
-    case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
-    case CARDTYPE_DIVASRV_B_2M_V2_PCI:
-    case CARDTYPE_DIVASRV_B_2F_PCI:
-    case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
-      return (1);
-  }
-  return (0);
+	switch (card_ordinal) {
+	case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
+	case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
+	case CARDTYPE_DIVASRV_B_2M_V2_PCI:
+	case CARDTYPE_DIVASRV_B_2F_PCI:
+	case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
+		return (1);
+	}
+	return (0);
 }
 
-static int
-_4bri_is_rev_2_bri_card (int card_ordinal) {
-  switch (card_ordinal) {
-    case CARDTYPE_DIVASRV_B_2M_V2_PCI:
-    case CARDTYPE_DIVASRV_B_2F_PCI:
-    case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
-      return (1);
+static int _4bri_is_rev_2_bri_card(int card_ordinal)
+{
+	switch (card_ordinal) {
+	case CARDTYPE_DIVASRV_B_2M_V2_PCI:
+	case CARDTYPE_DIVASRV_B_2F_PCI:
+	case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
+		return (1);
 	}
 	return (0);
 }
@@ -111,309 +107,345 @@
 **
 **  Called by master adapter, that will initialize and add slave adapters
 */
-int
-diva_4bri_init_card (diva_os_xdi_adapter_t* a)
+int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
 {
-  int bar, i;
-  PADAPTER_LIST_ENTRY quadro_list;
-  diva_os_xdi_adapter_t* diva_current;
-  diva_os_xdi_adapter_t* adapter_list[4];
-  PISDN_ADAPTER Slave;
-  dword offset;
-  unsigned long bar_length[sizeof(_4bri_bar_length)/sizeof(_4bri_bar_length[0])];
-  int v2 = _4bri_is_rev_2_card (a->CardOrdinal);
-  int tasks = _4bri_is_rev_2_bri_card (a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
-  int factor = (tasks == 1) ? 1 : 2;
-
-  if (v2) {
-    if (_4bri_is_rev_2_bri_card (a->CardOrdinal)) {
-      memcpy (bar_length, _4bri_v2_bri_bar_length, sizeof(bar_length));
-    } else {
-      memcpy (bar_length, _4bri_v2_bar_length, sizeof(bar_length));
-    }
-  } else {
-    memcpy (bar_length, _4bri_bar_length, sizeof(bar_length));
-  }
-  DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
-           bar_length[2], tasks, factor))
-
-  /*
-    Get Serial Number
-    The serial number of 4BRI is accessible in accordance with PCI spec
-    via command register located in configuration space, also we do not
-    have to map any BAR before we can access it
-  */
-  if (!_4bri_get_serial_number (a)) {
-    DBG_ERR(("A: 4BRI can't ger Serial Number"))
-    diva_4bri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  /*
-    Set properties
-  */
-  a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
-  DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
-            a->xdi_adapter.Properties.Name,
-            a->xdi_adapter.serialNo,
-            a->resources.pci.bus,
-            a->resources.pci.func))
-
-  /*
-    First initialization step: get and check hardware resoures.
-    Do not map resources and do not access card at this step
-  */
-
-  for (bar = 0; bar < 4; bar++) {
-    a->resources.pci.bar[bar] = divasa_get_pci_bar (a->resources.pci.bus,
-                                                    a->resources.pci.func,
-                                                    bar,
-                                                    a->resources.pci.hdev);
-    if (!a->resources.pci.bar[bar] ||
-        (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
-      DBG_ERR(("A: invalid bar[%d]=%08x", bar, a->resources.pci.bar[bar]))
-      return (-1);
-    }
-  }
-  a->resources.pci.irq = (byte)divasa_get_pci_irq (a->resources.pci.bus,
-                                                   a->resources.pci.func,
-                                                   a->resources.pci.hdev);
-  if (!a->resources.pci.irq) {
-    DBG_ERR(("A: invalid irq"));
-    return (-1);
-  }
-
-  a->xdi_adapter.sdram_bar = a->resources.pci.bar [2];
-
-  /*
-    Map all MEMORY BAR's
-  */
-  for (bar = 0; bar < 4; bar++) {
-    if (bar != 1) { /* ignore I/O */
-      a->resources.pci.addr[bar] = divasa_remap_pci_bar (a->resources.pci.bar[bar],
-                                                         bar_length[bar]);
-      if (!a->resources.pci.addr[bar]) {
-        DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
-        diva_4bri_cleanup_adapter (a);
-        return (-1);
-      }
-    }
-  }
-
-  /*
-    Register I/O port
-  */
-  sprintf (&a->port_name[0], "DIVA 4BRI %ld", (long)a->xdi_adapter.serialNo);
-
-  if (diva_os_register_io_port (1, a->resources.pci.bar[1],
-                                bar_length[1],
-                                &a->port_name[0])) {
-    DBG_ERR(("A: 4BRI: can't register bar[1]"))
-    diva_4bri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  a->resources.pci.addr[1] = (void*)(unsigned long)a->resources.pci.bar[1];
-
-  /*
-    Set cleanup pointer for base adapter only, so slave adapter
-    will be unable to get cleanup
-  */
-  a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
-
-  /*
-    Create slave adapters
-  */
-  if (tasks > 1) {
-    if (!(a->slave_adapters[0] = (diva_os_xdi_adapter_t*)diva_os_malloc (0, sizeof(*a)))) {
-      diva_4bri_cleanup_adapter (a);
-      return (-1);
-    }
-    if (!(a->slave_adapters[1] = (diva_os_xdi_adapter_t*)diva_os_malloc (0, sizeof(*a)))) {
-      diva_os_free (0, a->slave_adapters[0]);
-      a->slave_adapters[0] = 0;
-      diva_4bri_cleanup_adapter (a);
-      return (-1);
-    }
-    if (!(a->slave_adapters[2] = (diva_os_xdi_adapter_t*)diva_os_malloc (0, sizeof(*a)))) {
-      diva_os_free (0, a->slave_adapters[0]);
-      diva_os_free (0, a->slave_adapters[1]);
-      a->slave_adapters[0] = 0;
-      a->slave_adapters[1] = 0;
-      diva_4bri_cleanup_adapter (a);
-      return (-1);
-    }
-    memset (a->slave_adapters[0], 0x00, sizeof(*a));
-    memset (a->slave_adapters[1], 0x00, sizeof(*a));
-    memset (a->slave_adapters[2], 0x00, sizeof(*a));
-  }
-
-  adapter_list[0] = a;
-  adapter_list[1] = a->slave_adapters[0];
-  adapter_list[2] = a->slave_adapters[1];
-  adapter_list[3] = a->slave_adapters[2];
-
-  /*
-    Allocate slave list
-  */
-  quadro_list = (PADAPTER_LIST_ENTRY)diva_os_malloc (0, sizeof(*quadro_list));
-  if (!(a->slave_list = quadro_list)) {
-    for (i = 0; i < (tasks-1); i++) {
-      diva_os_free (0, a->slave_adapters[bar]);
-      a->slave_adapters[bar] = 0;
-    }
-    diva_4bri_cleanup_adapter (a);
-    return (-1);
-  }
-  memset (quadro_list, 0x00, sizeof(*quadro_list));
-
-  /*
-    Set interfaces
-  */
-  a->xdi_adapter.QuadroList = quadro_list;
-  for (i = 0; i < tasks; i++) {
-    adapter_list[i]->xdi_adapter.ControllerNumber = i;
-    adapter_list[i]->xdi_adapter.tasks = tasks;
-    quadro_list->QuadroAdapter[i] = &adapter_list[i]->xdi_adapter;
-  }
-
-  for (i = 0; i < tasks; i++) {
-    diva_current = adapter_list[i];
-
-    diva_current->dsp_mask = 0x00000003;
-
-    diva_current->xdi_adapter.a.io = &diva_current->xdi_adapter;
-    diva_current->xdi_adapter.DIRequest = request;
-    diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
-    diva_current->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
-    diva_current->CardOrdinal = a->CardOrdinal;
-
-    diva_current->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
-    diva_current->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
-    diva_current->xdi_adapter.e_tbl = diva_os_malloc (0, diva_current->xdi_adapter.e_max * sizeof(E_INFO)); 
-
-    if (!diva_current->xdi_adapter.e_tbl) {
-      diva_4bri_cleanup_slave_adapters (a);
-      diva_4bri_cleanup_adapter (a);
-      for (i = 1; i < (tasks-1); i++) { diva_os_free (0, adapter_list[i]); }
-      return (-1);
-    }
-    memset (diva_current->xdi_adapter.e_tbl, 0x00, diva_current->xdi_adapter.e_max * sizeof(E_INFO));
-
-    if (diva_os_initialize_spin_lock (&diva_current->xdi_adapter.isr_spin_lock, "isr")) {
-      diva_4bri_cleanup_slave_adapters (a);
-      diva_4bri_cleanup_adapter (a);
-      for (i = 1; i < (tasks-1); i++) { diva_os_free (0, adapter_list[i]); }
-      return (-1);
-    }
-    if (diva_os_initialize_spin_lock (&diva_current->xdi_adapter.data_spin_lock, "data")) {
-      diva_4bri_cleanup_slave_adapters (a);
-      diva_4bri_cleanup_adapter (a);
-      for (i = 1; i < (tasks-1); i++) { diva_os_free (0, adapter_list[i]); }
-      return (-1);
-    }
-
-    strcpy (diva_current->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivas4brid");
-
-    if (diva_os_initialize_soft_isr (&diva_current->xdi_adapter.req_soft_isr,
-                                     DIDpcRoutine,
-                                     &diva_current->xdi_adapter)) {
-      diva_4bri_cleanup_slave_adapters (a);
-      diva_4bri_cleanup_adapter (a);
-      for (i = 1; i < (tasks-1); i++) { diva_os_free (0, adapter_list[i]); }
-      return (-1);
-    }
-
-    /*
-     Do not initialize second DPC - only one thread will be created
-    */
-    diva_current->xdi_adapter.isr_soft_isr.object = diva_current->xdi_adapter.req_soft_isr.object;
-  }
-
-  if (v2) {
-       prepare_qBri2_functions (&a->xdi_adapter);
-  } else {
-       prepare_qBri_functions (&a->xdi_adapter);
-  }
-
-  /*
-    Set up hardware related pointers
-  */
-  a->xdi_adapter.cfg = (void*)(unsigned long)a->resources.pci.bar[0]; /* BAR0 CONFIG */
-  a->xdi_adapter.port = (void*)(unsigned long)a->resources.pci.bar[1]; /* BAR1        */
-  a->xdi_adapter.Address = a->resources.pci.addr[2];        /* BAR2 SDRAM  */
-  a->xdi_adapter.ctlReg = (void*)(unsigned long)a->resources.pci.bar[3]; /* BAR3 CNTRL  */
-
-  a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
-  a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM  */
-  /*
-    ctlReg contains the register address for the MIPS CPU reset control
-  */
-  a->xdi_adapter.ctlReg = a->resources.pci.addr[3];  /* BAR3 CNTRL  */
-  /*
-    prom contains the register address for FPGA and EEPROM programming
-  */
-  a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
-  /*
-    reset contains the base address for the PLX 9054 register set
-  */
-  a->xdi_adapter.reset[PLX9054_INTCSR] = 0x00 ;	/* disable PCI interrupts */
-
-  /*
-    Replicate addresses to all instances, set shared memory
-    address for all instances
-  */
-  for (i = 0; i < tasks; i++) {
-    Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
-    offset = Slave->ControllerNumber * (a->xdi_adapter.MemorySize>>factor);
-    Slave->Address = &a->xdi_adapter.Address[offset];
-    Slave->ram	= &a->xdi_adapter.ram[offset];
-    Slave->reset = a->xdi_adapter.reset;
-    Slave->ctlReg = a->xdi_adapter.ctlReg;
-    Slave->prom	= a->xdi_adapter.prom;
-    Slave->reset = a->xdi_adapter.reset;
-    Slave->sdram_bar = a->xdi_adapter.sdram_bar;
-  }
-  for (i = 0; i < tasks; i++) {
-    Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
-    Slave->ram += ((a->xdi_adapter.MemorySize >> factor) - MQ_SHARED_RAM_SIZE);
-  }
-  for (i = 1; i < tasks; i++) {
-    Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
-    Slave->serialNo = ((dword)(Slave->ControllerNumber << 24)) | a->xdi_adapter.serialNo;
-    Slave->cardType = a->xdi_adapter.cardType;
-  }
-
-  /*
-    Set IRQ handler
-  */
-  a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
-  sprintf (a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld", (long)a->xdi_adapter.serialNo);
-
-  if (diva_os_register_irq (a, a->xdi_adapter.irq_info.irq_nr,
-                            a->xdi_adapter.irq_info.irq_name)) {
-    diva_4bri_cleanup_slave_adapters (a);
-    diva_4bri_cleanup_adapter (a);
-    for (i = 1; i < (tasks-1); i++) { diva_os_free (0, adapter_list[i]); }
-    return (-1);
-  }
-
-  a->xdi_adapter.irq_info.registered = 1;
-
-  /*
-    Add three slave adapters
-  */
-  if (tasks > 1) {
-    diva_add_slave_adapter (adapter_list[1]);
-    diva_add_slave_adapter (adapter_list[2]);
-    diva_add_slave_adapter (adapter_list[3]);
-  }
-
-  diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
-                                      a->resources.pci.irq,
-                                      a->xdi_adapter.serialNo);
+	int bar, i;
+	PADAPTER_LIST_ENTRY quadro_list;
+	diva_os_xdi_adapter_t *diva_current;
+	diva_os_xdi_adapter_t *adapter_list[4];
+	PISDN_ADAPTER Slave;
+	dword offset;
+	unsigned long bar_length[sizeof(_4bri_bar_length) /
+				 sizeof(_4bri_bar_length[0])];
+	int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
+	int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
+	int factor = (tasks == 1) ? 1 : 2;
+
+	if (v2) {
+		if (_4bri_is_rev_2_bri_card(a->CardOrdinal)) {
+			memcpy(bar_length, _4bri_v2_bri_bar_length,
+			       sizeof(bar_length));
+		} else {
+			memcpy(bar_length, _4bri_v2_bar_length,
+			       sizeof(bar_length));
+		}
+	} else {
+		memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
+	}
+	DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
+		 bar_length[2], tasks, factor))
+
+	/*
+	   Get Serial Number
+	   The serial number of 4BRI is accessible in accordance with PCI spec
+	   via command register located in configuration space, also we do not
+	   have to map any BAR before we can access it
+	 */
+	if (!_4bri_get_serial_number(a)) {
+		DBG_ERR(("A: 4BRI can't ger Serial Number"))
+		diva_4bri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	/*
+	   Set properties
+	 */
+	a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
+	DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
+		 a->xdi_adapter.Properties.Name,
+		 a->xdi_adapter.serialNo,
+		 a->resources.pci.bus, a->resources.pci.func))
+
+	/*
+	   First initialization step: get and check hardware resoures.
+	   Do not map resources and do not access card at this step
+	 */
+	for (bar = 0; bar < 4; bar++) {
+		a->resources.pci.bar[bar] =
+		    divasa_get_pci_bar(a->resources.pci.bus,
+				       a->resources.pci.func, bar,
+				       a->resources.pci.hdev);
+		if (!a->resources.pci.bar[bar]
+		    || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
+			DBG_ERR(
+				("A: invalid bar[%d]=%08x", bar,
+				 a->resources.pci.bar[bar]))
+			return (-1);
+		}
+	}
+	a->resources.pci.irq =
+	    (byte) divasa_get_pci_irq(a->resources.pci.bus,
+				      a->resources.pci.func,
+				      a->resources.pci.hdev);
+	if (!a->resources.pci.irq) {
+		DBG_ERR(("A: invalid irq"));
+		return (-1);
+	}
+
+	a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
+
+	/*
+	   Map all MEMORY BAR's
+	 */
+	for (bar = 0; bar < 4; bar++) {
+		if (bar != 1) {	/* ignore I/O */
+			a->resources.pci.addr[bar] =
+			    divasa_remap_pci_bar(a->resources.pci.bar[bar],
+						 bar_length[bar]);
+			if (!a->resources.pci.addr[bar]) {
+				DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
+				diva_4bri_cleanup_adapter(a);
+				return (-1);
+			}
+		}
+	}
+
+	/*
+	   Register I/O port
+	 */
+	sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
+
+	if (diva_os_register_io_port(1, a->resources.pci.bar[1],
+				     bar_length[1], &a->port_name[0])) {
+		DBG_ERR(("A: 4BRI: can't register bar[1]"))
+		diva_4bri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1];
+
+	/*
+	   Set cleanup pointer for base adapter only, so slave adapter
+	   will be unable to get cleanup
+	 */
+	a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
+
+	/*
+	   Create slave adapters
+	 */
+	if (tasks > 1) {
+		if (!(a->slave_adapters[0] =
+		     (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
+		{
+			diva_4bri_cleanup_adapter(a);
+			return (-1);
+		}
+		if (!(a->slave_adapters[1] =
+		     (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
+		{
+			diva_os_free(0, a->slave_adapters[0]);
+			a->slave_adapters[0] = 0;
+			diva_4bri_cleanup_adapter(a);
+			return (-1);
+		}
+		if (!(a->slave_adapters[2] =
+		     (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
+		{
+			diva_os_free(0, a->slave_adapters[0]);
+			diva_os_free(0, a->slave_adapters[1]);
+			a->slave_adapters[0] = 0;
+			a->slave_adapters[1] = 0;
+			diva_4bri_cleanup_adapter(a);
+			return (-1);
+		}
+		memset(a->slave_adapters[0], 0x00, sizeof(*a));
+		memset(a->slave_adapters[1], 0x00, sizeof(*a));
+		memset(a->slave_adapters[2], 0x00, sizeof(*a));
+	}
+
+	adapter_list[0] = a;
+	adapter_list[1] = a->slave_adapters[0];
+	adapter_list[2] = a->slave_adapters[1];
+	adapter_list[3] = a->slave_adapters[2];
+
+	/*
+	   Allocate slave list
+	 */
+	quadro_list =
+	    (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
+	if (!(a->slave_list = quadro_list)) {
+		for (i = 0; i < (tasks - 1); i++) {
+			diva_os_free(0, a->slave_adapters[bar]);
+			a->slave_adapters[bar] = 0;
+		}
+		diva_4bri_cleanup_adapter(a);
+		return (-1);
+	}
+	memset(quadro_list, 0x00, sizeof(*quadro_list));
+
+	/*
+	   Set interfaces
+	 */
+	a->xdi_adapter.QuadroList = quadro_list;
+	for (i = 0; i < tasks; i++) {
+		adapter_list[i]->xdi_adapter.ControllerNumber = i;
+		adapter_list[i]->xdi_adapter.tasks = tasks;
+		quadro_list->QuadroAdapter[i] =
+		    &adapter_list[i]->xdi_adapter;
+	}
+
+	for (i = 0; i < tasks; i++) {
+		diva_current = adapter_list[i];
+
+		diva_current->dsp_mask = 0x00000003;
+
+		diva_current->xdi_adapter.a.io =
+		    &diva_current->xdi_adapter;
+		diva_current->xdi_adapter.DIRequest = request;
+		diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
+		diva_current->xdi_adapter.Properties =
+		    CardProperties[a->CardOrdinal];
+		diva_current->CardOrdinal = a->CardOrdinal;
+
+		diva_current->xdi_adapter.Channels =
+		    CardProperties[a->CardOrdinal].Channels;
+		diva_current->xdi_adapter.e_max =
+		    CardProperties[a->CardOrdinal].E_info;
+		diva_current->xdi_adapter.e_tbl =
+		    diva_os_malloc(0,
+				   diva_current->xdi_adapter.e_max *
+				   sizeof(E_INFO));
+
+		if (!diva_current->xdi_adapter.e_tbl) {
+			diva_4bri_cleanup_slave_adapters(a);
+			diva_4bri_cleanup_adapter(a);
+			for (i = 1; i < (tasks - 1); i++) {
+				diva_os_free(0, adapter_list[i]);
+			}
+			return (-1);
+		}
+		memset(diva_current->xdi_adapter.e_tbl, 0x00,
+		       diva_current->xdi_adapter.e_max * sizeof(E_INFO));
+
+		if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.isr_spin_lock, "isr")) {
+			diva_4bri_cleanup_slave_adapters(a);
+			diva_4bri_cleanup_adapter(a);
+			for (i = 1; i < (tasks - 1); i++) {
+				diva_os_free(0, adapter_list[i]);
+			}
+			return (-1);
+		}
+		if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.data_spin_lock, "data")) {
+			diva_4bri_cleanup_slave_adapters(a);
+			diva_4bri_cleanup_adapter(a);
+			for (i = 1; i < (tasks - 1); i++) {
+				diva_os_free(0, adapter_list[i]);
+			}
+			return (-1);
+		}
+
+		strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
+
+		if (diva_os_initialize_soft_isr (&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
+		     &diva_current->xdi_adapter)) {
+			diva_4bri_cleanup_slave_adapters(a);
+			diva_4bri_cleanup_adapter(a);
+			for (i = 1; i < (tasks - 1); i++) {
+				diva_os_free(0, adapter_list[i]);
+			}
+			return (-1);
+		}
+
+		/*
+		   Do not initialize second DPC - only one thread will be created
+		 */
+		diva_current->xdi_adapter.isr_soft_isr.object =
+		    diva_current->xdi_adapter.req_soft_isr.object;
+	}
+
+	if (v2) {
+		prepare_qBri2_functions(&a->xdi_adapter);
+	} else {
+		prepare_qBri_functions(&a->xdi_adapter);
+	}
 
-  return (0);
+	/*
+	   Set up hardware related pointers
+	 */
+	a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0];	/* BAR0 CONFIG */
+	a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1];	/* BAR1        */
+	a->xdi_adapter.Address = a->resources.pci.addr[2];	/* BAR2 SDRAM  */
+	a->xdi_adapter.ctlReg =
+	    (void *) (unsigned long) a->resources.pci.bar[3];	/* BAR3 CNTRL  */
+
+	a->xdi_adapter.reset = a->resources.pci.addr[0];	/* BAR0 CONFIG */
+	a->xdi_adapter.ram = a->resources.pci.addr[2];	/* BAR2 SDRAM  */
+	/*
+	   ctlReg contains the register address for the MIPS CPU reset control
+	 */
+	a->xdi_adapter.ctlReg = a->resources.pci.addr[3];	/* BAR3 CNTRL  */
+	/*
+	   prom contains the register address for FPGA and EEPROM programming
+	 */
+	a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
+	/*
+	   reset contains the base address for the PLX 9054 register set
+	 */
+	a->xdi_adapter.reset[PLX9054_INTCSR] = 0x00;	/* disable PCI interrupts */
+
+	/*
+	   Replicate addresses to all instances, set shared memory
+	   address for all instances
+	 */
+	for (i = 0; i < tasks; i++) {
+		Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
+		offset =
+		    Slave->ControllerNumber *
+		    (a->xdi_adapter.MemorySize >> factor);
+		Slave->Address = &a->xdi_adapter.Address[offset];
+		Slave->ram = &a->xdi_adapter.ram[offset];
+		Slave->reset = a->xdi_adapter.reset;
+		Slave->ctlReg = a->xdi_adapter.ctlReg;
+		Slave->prom = a->xdi_adapter.prom;
+		Slave->reset = a->xdi_adapter.reset;
+		Slave->sdram_bar = a->xdi_adapter.sdram_bar;
+	}
+	for (i = 0; i < tasks; i++) {
+		Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
+		Slave->ram +=
+		    ((a->xdi_adapter.MemorySize >> factor) -
+		     MQ_SHARED_RAM_SIZE);
+	}
+	for (i = 1; i < tasks; i++) {
+		Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
+		Slave->serialNo =
+		    ((dword) (Slave->ControllerNumber << 24)) | a->
+		    xdi_adapter.serialNo;
+		Slave->cardType = a->xdi_adapter.cardType;
+	}
+
+	/*
+	   Set IRQ handler
+	 */
+	a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
+	sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld",
+		(long) a->xdi_adapter.serialNo);
+
+	if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
+				 a->xdi_adapter.irq_info.irq_name)) {
+		diva_4bri_cleanup_slave_adapters(a);
+		diva_4bri_cleanup_adapter(a);
+		for (i = 1; i < (tasks - 1); i++) {
+			diva_os_free(0, adapter_list[i]);
+		}
+		return (-1);
+	}
+
+	a->xdi_adapter.irq_info.registered = 1;
+
+	/*
+	   Add three slave adapters
+	 */
+	if (tasks > 1) {
+		diva_add_slave_adapter(adapter_list[1]);
+		diva_add_slave_adapter(adapter_list[2]);
+		diva_add_slave_adapter(adapter_list[3]);
+	}
+
+	diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
+		      a->resources.pci.irq, a->xdi_adapter.serialNo);
+
+	return (0);
 }
 
 /*
@@ -421,594 +453,659 @@
 **  this is garanteed by design: cleanup callback is set
 **  by master adapter only
 */
-static int
-diva_4bri_cleanup_adapter (diva_os_xdi_adapter_t* a)
+static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
 {
-  int bar;
+	int bar;
 
-  /*
-    Stop adapter if running
-  */
-  if (a->xdi_adapter.Initialized) {
-    diva_4bri_stop_adapter (a);
-  }
-
-  /*
-    Remove IRQ handler
-  */
-  if (a->xdi_adapter.irq_info.registered) {
-    diva_os_remove_irq (a, a->xdi_adapter.irq_info.irq_nr);
-  }
-  a->xdi_adapter.irq_info.registered = 0;
-
-  /*
-    Free DPC's and spin locks on all adapters
-  */
-  diva_4bri_cleanup_slave_adapters (a);
-
-  /*
-    Unmap all BARS
-  */
-  for (bar = 0; bar < 4; bar++) {
-    if (bar != 1) {
-      if (a->resources.pci.bar[bar] && a->resources.pci.addr[bar]) {
-        divasa_unmap_pci_bar (a->resources.pci.addr[bar]);
-        a->resources.pci.bar[bar]  = 0;
-        a->resources.pci.addr[bar] = 0;
-      }
-    }
-  }
-
-  /*
-    Unregister I/O
-  */
-  if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
-    diva_os_register_io_port (0, a->resources.pci.bar[1], 
-      _4bri_is_rev_2_card (a->CardOrdinal) ? _4bri_v2_bar_length[1] : _4bri_bar_length[1],
-      &a->port_name[0]);
-    a->resources.pci.bar[1]  = 0;
-    a->resources.pci.addr[1] = 0;
-  }
-
-  if (a->slave_list) {
-    diva_os_free (0, a->slave_list);
-    a->slave_list = 0;
-  }
+	/*
+	   Stop adapter if running
+	 */
+	if (a->xdi_adapter.Initialized) {
+		diva_4bri_stop_adapter(a);
+	}
+
+	/*
+	   Remove IRQ handler
+	 */
+	if (a->xdi_adapter.irq_info.registered) {
+		diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
+	}
+	a->xdi_adapter.irq_info.registered = 0;
 
-  return (0);
+	/*
+	   Free DPC's and spin locks on all adapters
+	 */
+	diva_4bri_cleanup_slave_adapters(a);
+
+	/*
+	   Unmap all BARS
+	 */
+	for (bar = 0; bar < 4; bar++) {
+		if (bar != 1) {
+			if (a->resources.pci.bar[bar]
+			    && a->resources.pci.addr[bar]) {
+				divasa_unmap_pci_bar(a->resources.pci.
+						     addr[bar]);
+				a->resources.pci.bar[bar] = 0;
+				a->resources.pci.addr[bar] = 0;
+			}
+		}
+	}
+
+	/*
+	   Unregister I/O
+	 */
+	if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
+		diva_os_register_io_port(0, a->resources.pci.bar[1],
+					 _4bri_is_rev_2_card(a->
+							     CardOrdinal) ?
+					 _4bri_v2_bar_length[1] :
+					 _4bri_bar_length[1],
+					 &a->port_name[0]);
+		a->resources.pci.bar[1] = 0;
+		a->resources.pci.addr[1] = 0;
+	}
+
+	if (a->slave_list) {
+		diva_os_free(0, a->slave_list);
+		a->slave_list = 0;
+	}
+
+	return (0);
 }
 
-static int
-_4bri_get_serial_number (diva_os_xdi_adapter_t* a)
+static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a)
 {
-  dword data[64] ;
-  dword serNo ;
-  word addr, status, i, j ;
-  byte Bus, Slot;
-  void* hdev;
-
-  Bus = a->resources.pci.bus;
-  Slot = a->resources.pci.func;
-  hdev = a->resources.pci.hdev;
-
-  for ( i = 0 ; i < 64 ; ++i )
-  {
-    addr = i * 4 ;
-    for ( j = 0 ; j < 5; ++j )
-    {
-      PCIwrite (Bus, Slot, 0x4E, &addr, sizeof(addr), hdev) ;
-      diva_os_wait (1) ;
-      PCIread (Bus, Slot, 0x4E, &status, sizeof(status), hdev) ;
-      if (status & 0x8000)
-        break ;
-    }
-    if (j >= 5){
-      DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
-      return(0) ;
-    }
-    PCIread (Bus, Slot, 0x50, &data[i], sizeof (data[i]), hdev) ;
-  }
-  DBG_BLK(( (char *)&data[0], sizeof(data) ))
-
-  serNo  = data[32] ;
-  if (serNo == 0 || serNo == 0xffffffff)
-    serNo  = data[63] ;
-
-  if (!serNo) {
-    DBG_LOG(("W: Serial Number == 0, create one serial number"));
-    serNo  = a->resources.pci.bar[1] & 0xffff0000;
-    serNo |= a->resources.pci.bus << 8;
-    serNo |= a->resources.pci.func;
-  }
-	
-  a->xdi_adapter.serialNo = serNo;
+	dword data[64];
+	dword serNo;
+	word addr, status, i, j;
+	byte Bus, Slot;
+	void *hdev;
+
+	Bus = a->resources.pci.bus;
+	Slot = a->resources.pci.func;
+	hdev = a->resources.pci.hdev;
+
+	for (i = 0; i < 64; ++i) {
+		addr = i * 4;
+		for (j = 0; j < 5; ++j) {
+			PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr),
+				 hdev);
+			diva_os_wait(1);
+			PCIread(Bus, Slot, 0x4E, &status, sizeof(status),
+				hdev);
+			if (status & 0x8000)
+				break;
+		}
+		if (j >= 5) {
+			DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
+			return (0);
+		}
+		PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
+	}
+	DBG_BLK(((char *) &data[0], sizeof(data)))
+
+	serNo = data[32];
+	if (serNo == 0 || serNo == 0xffffffff)
+		serNo = data[63];
+
+	if (!serNo) {
+		DBG_LOG(("W: Serial Number == 0, create one serial number"));
+		serNo = a->resources.pci.bar[1] & 0xffff0000;
+		serNo |= a->resources.pci.bus << 8;
+		serNo |= a->resources.pci.func;
+	}
 
-  DBG_REG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
+	a->xdi_adapter.serialNo = serNo;
 
-  return (serNo) ;
+	DBG_REG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
+
+	return (serNo);
 }
 
 /*
 **  Release resources of slave adapters
 */
-static int
-diva_4bri_cleanup_slave_adapters (diva_os_xdi_adapter_t* a)
+static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a)
 {
-  diva_os_xdi_adapter_t* adapter_list[4];
-  diva_os_xdi_adapter_t* diva_current;
-  int i;
-
-  adapter_list[0] = a;
-  adapter_list[1] = a->slave_adapters[0];
-  adapter_list[2] = a->slave_adapters[1];
-  adapter_list[3] = a->slave_adapters[2];
-
-  for (i = 0; i < a->xdi_adapter.tasks; i++) {
-    diva_current = adapter_list[i];
-    if (diva_current) {
-      diva_os_destroy_spin_lock (&diva_current->xdi_adapter.isr_spin_lock, "unload");
-      diva_os_destroy_spin_lock (&diva_current->xdi_adapter.data_spin_lock,"unload");
-
-      diva_os_cancel_soft_isr (&diva_current->xdi_adapter.req_soft_isr);
-      diva_os_cancel_soft_isr (&diva_current->xdi_adapter.isr_soft_isr);
-
-      diva_os_remove_soft_isr (&diva_current->xdi_adapter.req_soft_isr);
-      diva_current->xdi_adapter.isr_soft_isr.object = 0;
-
-      if (diva_current->xdi_adapter.e_tbl) {
-        diva_os_free (0, diva_current->xdi_adapter.e_tbl);
-      }
-      diva_current->xdi_adapter.e_tbl   = 0;
-      diva_current->xdi_adapter.e_max   = 0;
-      diva_current->xdi_adapter.e_count = 0;
-    }
-  }
+	diva_os_xdi_adapter_t *adapter_list[4];
+	diva_os_xdi_adapter_t *diva_current;
+	int i;
+
+	adapter_list[0] = a;
+	adapter_list[1] = a->slave_adapters[0];
+	adapter_list[2] = a->slave_adapters[1];
+	adapter_list[3] = a->slave_adapters[2];
+
+	for (i = 0; i < a->xdi_adapter.tasks; i++) {
+		diva_current = adapter_list[i];
+		if (diva_current) {
+			diva_os_destroy_spin_lock(&diva_current->
+						  xdi_adapter.
+						  isr_spin_lock, "unload");
+			diva_os_destroy_spin_lock(&diva_current->
+						  xdi_adapter.
+						  data_spin_lock,
+						  "unload");
+
+			diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
+						req_soft_isr);
+			diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
+						isr_soft_isr);
+
+			diva_os_remove_soft_isr(&diva_current->xdi_adapter.
+						req_soft_isr);
+			diva_current->xdi_adapter.isr_soft_isr.object = 0;
+
+			if (diva_current->xdi_adapter.e_tbl) {
+				diva_os_free(0,
+					     diva_current->xdi_adapter.
+					     e_tbl);
+			}
+			diva_current->xdi_adapter.e_tbl = 0;
+			diva_current->xdi_adapter.e_max = 0;
+			diva_current->xdi_adapter.e_count = 0;
+		}
+	}
 
-  return (0);
+	return (0);
 }
 
 static int
-diva_4bri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                         diva_xdi_um_cfg_cmd_t* cmd,
-                         int length)
-{
-  int ret = -1;
-
-  if (cmd->adapter != a->controller) {
-    DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
-                  cmd->adapter, a->controller))
-    return (-1);
-  }
-
-  switch (cmd->command) {
-    case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->CardOrdinal;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->xdi_adapter.serialNo;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
-      if (!a->xdi_adapter.ControllerNumber) {
-        /*
-          Only master adapter can access hardware config
-        */
-        a->xdi_mbox.data_length = sizeof(dword)*9;
-        a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-        if (a->xdi_mbox.data) {
-          int i;
-          dword* data = (dword*)a->xdi_mbox.data;
-
-          for (i = 0; i < 8; i++) {
-            *data++ = a->resources.pci.bar[i];
-          }
-          *data++ = (dword)a->resources.pci.irq;
-          a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-          ret = 0;
-        }
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_CARD_STATE:
-      if (!a->xdi_adapter.ControllerNumber) {
-        a->xdi_mbox.data_length = sizeof(dword);
-        a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-        if (a->xdi_mbox.data) {
-          dword* data = (dword*)a->xdi_mbox.data;
-          if (!a->xdi_adapter.ram || !a->xdi_adapter.reset ||
-              !a->xdi_adapter.cfg) {
-            *data = 3;
-          } else if (a->xdi_adapter.trapped) {
-            *data = 2;
-          } else if (a->xdi_adapter.Initialized) {
-            *data = 1;
-          } else {
-            *data = 0;
-          }
-          a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-          ret = 0;
-        }
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_WRITE_FPGA:
-      if (!a->xdi_adapter.ControllerNumber) {
-        ret = diva_4bri_write_fpga_image (a, (byte*)&cmd[1], 
-                                          cmd->command_data.write_fpga.image_length);
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_RESET_ADAPTER:
-      if (!a->xdi_adapter.ControllerNumber) {
-        ret = diva_4bri_reset_adapter (&a->xdi_adapter);
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
-      if (!a->xdi_adapter.ControllerNumber) {
-        ret = diva_4bri_write_sdram_block (&a->xdi_adapter,
-                                           cmd->command_data.write_sdram.offset,
-                                           (byte*)&cmd[1],
-                                           cmd->command_data.write_sdram.length,
-                                           a->xdi_adapter.MemorySize);
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_START_ADAPTER:
-      if (!a->xdi_adapter.ControllerNumber) {
-        ret = diva_4bri_start_adapter (&a->xdi_adapter,
-                                       cmd->command_data.start.offset,
-                                       cmd->command_data.start.features);
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
-      if (!a->xdi_adapter.ControllerNumber) {
-        a->xdi_adapter.features = cmd->command_data.features.features;
-        a->xdi_adapter.a.protocol_capabilities = a->xdi_adapter.features;
-        DBG_TRC(("Set raw protocol features (%08x)", a->xdi_adapter.features))
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_STOP_ADAPTER:
-      if (!a->xdi_adapter.ControllerNumber) {
-        ret = diva_4bri_stop_adapter (a);
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
-      ret = diva_card_read_xlog (a);
-      break;
-
-    case DIVA_XDI_UM_CMD_READ_SDRAM:
-      if (!a->xdi_adapter.ControllerNumber && a->xdi_adapter.Address) {
-        if ((a->xdi_mbox.data_length = cmd->command_data.read_sdram.length)) {
-          if ((a->xdi_mbox.data_length+cmd->command_data.read_sdram.offset) < a->xdi_adapter.MemorySize) {
-            a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-            if (a->xdi_mbox.data) {
-              byte* src = a->xdi_adapter.Address;
-              byte* dst = a->xdi_mbox.data;
-              dword len = a->xdi_mbox.data_length;
-
-              src += cmd->command_data.read_sdram.offset;
-
-              while (len--) {
-                *dst++ = *src++;
-              }
-              a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-              ret = 0;
-            }
-          }
-        }
-      }
-      break;
-
-    default:
-      DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller, cmd->command))
-  }
-
-  return (ret);
-}
-
-void *
-xdiLoadFile (char *FileName, unsigned long *FileLength, unsigned long lim)
-{
-  void* ret = diva_xdiLoadFileFile;
-
-  if (FileLength) {
-    *FileLength = diva_xdiLoadFileLength;
-  }
-  diva_xdiLoadFileFile	 = 0;
-  diva_xdiLoadFileLength = 0;
-
-  return (ret);
+diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+			diva_xdi_um_cfg_cmd_t * cmd, int length)
+{
+	int ret = -1;
+
+	if (cmd->adapter != a->controller) {
+		DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
+			 cmd->adapter, a->controller))
+		return (-1);
+	}
+
+	switch (cmd->command) {
+	case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->CardOrdinal;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->xdi_adapter.serialNo;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
+		if (!a->xdi_adapter.ControllerNumber) {
+			/*
+			   Only master adapter can access hardware config
+			 */
+			a->xdi_mbox.data_length = sizeof(dword) * 9;
+			a->xdi_mbox.data =
+			    diva_os_malloc(0, a->xdi_mbox.data_length);
+			if (a->xdi_mbox.data) {
+				int i;
+				dword *data = (dword *) a->xdi_mbox.data;
+
+				for (i = 0; i < 8; i++) {
+					*data++ = a->resources.pci.bar[i];
+				}
+				*data++ = (dword) a->resources.pci.irq;
+				a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+				ret = 0;
+			}
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_CARD_STATE:
+		if (!a->xdi_adapter.ControllerNumber) {
+			a->xdi_mbox.data_length = sizeof(dword);
+			a->xdi_mbox.data =
+			    diva_os_malloc(0, a->xdi_mbox.data_length);
+			if (a->xdi_mbox.data) {
+				dword *data = (dword *) a->xdi_mbox.data;
+				if (!a->xdi_adapter.ram
+				    || !a->xdi_adapter.reset
+				    || !a->xdi_adapter.cfg) {
+					*data = 3;
+				} else if (a->xdi_adapter.trapped) {
+					*data = 2;
+				} else if (a->xdi_adapter.Initialized) {
+					*data = 1;
+				} else {
+					*data = 0;
+				}
+				a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+				ret = 0;
+			}
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_WRITE_FPGA:
+		if (!a->xdi_adapter.ControllerNumber) {
+			ret =
+			    diva_4bri_write_fpga_image(a,
+						       (byte *) & cmd[1],
+						       cmd->command_data.
+						       write_fpga.
+						       image_length);
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_RESET_ADAPTER:
+		if (!a->xdi_adapter.ControllerNumber) {
+			ret = diva_4bri_reset_adapter(&a->xdi_adapter);
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
+		if (!a->xdi_adapter.ControllerNumber) {
+			ret = diva_4bri_write_sdram_block(&a->xdi_adapter,
+							  cmd->
+							  command_data.
+							  write_sdram.
+							  offset,
+							  (byte *) &
+							  cmd[1],
+							  cmd->
+							  command_data.
+							  write_sdram.
+							  length,
+							  a->xdi_adapter.
+							  MemorySize);
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_START_ADAPTER:
+		if (!a->xdi_adapter.ControllerNumber) {
+			ret = diva_4bri_start_adapter(&a->xdi_adapter,
+						      cmd->command_data.
+						      start.offset,
+						      cmd->command_data.
+						      start.features);
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
+		if (!a->xdi_adapter.ControllerNumber) {
+			a->xdi_adapter.features =
+			    cmd->command_data.features.features;
+			a->xdi_adapter.a.protocol_capabilities =
+			    a->xdi_adapter.features;
+			DBG_TRC(("Set raw protocol features (%08x)",
+				 a->xdi_adapter.features))
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_STOP_ADAPTER:
+		if (!a->xdi_adapter.ControllerNumber) {
+			ret = diva_4bri_stop_adapter(a);
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
+		ret = diva_card_read_xlog(a);
+		break;
+
+	case DIVA_XDI_UM_CMD_READ_SDRAM:
+		if (!a->xdi_adapter.ControllerNumber
+		    && a->xdi_adapter.Address) {
+			if (
+			    (a->xdi_mbox.data_length =
+			     cmd->command_data.read_sdram.length)) {
+				if (
+				    (a->xdi_mbox.data_length +
+				     cmd->command_data.read_sdram.offset) <
+				    a->xdi_adapter.MemorySize) {
+					a->xdi_mbox.data =
+					    diva_os_malloc(0,
+							   a->xdi_mbox.
+							   data_length);
+					if (a->xdi_mbox.data) {
+						byte *src =
+						    a->xdi_adapter.Address;
+						byte *dst =
+						    a->xdi_mbox.data;
+						dword len =
+						    a->xdi_mbox.
+						    data_length;
+
+						src +=
+						    cmd->command_data.
+						    read_sdram.offset;
+
+						while (len--) {
+							*dst++ = *src++;
+						}
+						a->xdi_mbox.status =
+						    DIVA_XDI_MBOX_BUSY;
+						ret = 0;
+					}
+				}
+			}
+		}
+		break;
+
+	default:
+		DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
+			 cmd->command))
+	}
+
+	return (ret);
 }
 
-void
-diva_os_set_qBri_functions (PISDN_ADAPTER IoAdapter)
+void *xdiLoadFile(char *FileName, unsigned long *FileLength,
+		  unsigned long lim)
 {
+	void *ret = diva_xdiLoadFileFile;
+
+	if (FileLength) {
+		*FileLength = diva_xdiLoadFileLength;
+	}
+	diva_xdiLoadFileFile = 0;
+	diva_xdiLoadFileLength = 0;
+
+	return (ret);
 }
 
-void
-diva_os_set_qBri2_functions (PISDN_ADAPTER IoAdapter)
+void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
+{
+}
+
+void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
 {
 }
 
 static int
-diva_4bri_write_fpga_image (diva_os_xdi_adapter_t* a, byte* data, dword length)
+diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, byte * data,
+			   dword length)
 {
-  int ret;
+	int ret;
 
-  diva_xdiLoadFileFile = data;
-  diva_xdiLoadFileLength = length;
+	diva_xdiLoadFileFile = data;
+	diva_xdiLoadFileLength = length;
 
-  ret = qBri_FPGA_download (&a->xdi_adapter);
+	ret = qBri_FPGA_download(&a->xdi_adapter);
 
-  diva_xdiLoadFileFile = 0;
-  diva_xdiLoadFileLength = 0;
+	diva_xdiLoadFileFile = 0;
+	diva_xdiLoadFileLength = 0;
 
-  return (ret ? 0 : -1);
+	return (ret ? 0 : -1);
 }
 
-static int
-diva_4bri_reset_adapter (PISDN_ADAPTER IoAdapter)
+static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
 {
-  PISDN_ADAPTER Slave;
-  int i;
+	PISDN_ADAPTER Slave;
+	int i;
 
-  if (!IoAdapter->Address || !IoAdapter->reset) {
-    return (-1);
-  }
-  if (IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first", IoAdapter->ANum))
-    return (-1);
-  }
-
-  /*
-    Forget all entities on all adapters
-  */
-  for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
-    Slave = IoAdapter->QuadroList->QuadroAdapter[i];
-    Slave->e_count =  0;
-    if (Slave->e_tbl) {
-      memset (Slave->e_tbl, 0x00, Slave->e_max * sizeof(E_INFO));
-    }
-    Slave->head	= 0;
-    Slave->tail = 0;
-    Slave->assign = 0;
-    Slave->trapped = 0;
-
-    memset (&Slave->a.IdTable[0],              0x00, sizeof(Slave->a.IdTable));
-    memset (&Slave->a.IdTypeTable[0],          0x00, sizeof(Slave->a.IdTypeTable));
-    memset (&Slave->a.FlowControlIdTable[0],   0x00, sizeof(Slave->a.FlowControlIdTable));
-    memset (&Slave->a.FlowControlSkipTable[0], 0x00, sizeof(Slave->a.FlowControlSkipTable));
-    memset (&Slave->a.misc_flags_table[0],     0x00, sizeof(Slave->a.misc_flags_table));
-    memset (&Slave->a.rx_stream[0],            0x00, sizeof(Slave->a.rx_stream));
-    memset (&Slave->a.tx_stream[0],            0x00, sizeof(Slave->a.tx_stream));
-    memset (&Slave->a.tx_pos[0],               0x00, sizeof(Slave->a.tx_pos));
-    memset (&Slave->a.rx_pos[0],               0x00, sizeof(Slave->a.rx_pos));
-  }
+	if (!IoAdapter->Address || !IoAdapter->reset) {
+		return (-1);
+	}
+	if (IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
+			 IoAdapter->ANum))
+		return (-1);
+	}
+
+	/*
+	   Forget all entities on all adapters
+	 */
+	for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
+		Slave = IoAdapter->QuadroList->QuadroAdapter[i];
+		Slave->e_count = 0;
+		if (Slave->e_tbl) {
+			memset(Slave->e_tbl, 0x00,
+			       Slave->e_max * sizeof(E_INFO));
+		}
+		Slave->head = 0;
+		Slave->tail = 0;
+		Slave->assign = 0;
+		Slave->trapped = 0;
+
+		memset(&Slave->a.IdTable[0], 0x00,
+		       sizeof(Slave->a.IdTable));
+		memset(&Slave->a.IdTypeTable[0], 0x00,
+		       sizeof(Slave->a.IdTypeTable));
+		memset(&Slave->a.FlowControlIdTable[0], 0x00,
+		       sizeof(Slave->a.FlowControlIdTable));
+		memset(&Slave->a.FlowControlSkipTable[0], 0x00,
+		       sizeof(Slave->a.FlowControlSkipTable));
+		memset(&Slave->a.misc_flags_table[0], 0x00,
+		       sizeof(Slave->a.misc_flags_table));
+		memset(&Slave->a.rx_stream[0], 0x00,
+		       sizeof(Slave->a.rx_stream));
+		memset(&Slave->a.tx_stream[0], 0x00,
+		       sizeof(Slave->a.tx_stream));
+		memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos));
+		memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos));
+	}
 
-  return (0);
+	return (0);
 }
 
 
 static int
-diva_4bri_write_sdram_block (PISDN_ADAPTER IoAdapter,
-                             dword address,
-                             const byte* data,
-                             dword length,
-                             dword limit)
-{
-  byte* mem = IoAdapter->Address;
-
-  if (((address + length) >= limit) || !mem) {
-    DBG_ERR(("A: A(%d) write PRI address=0x%08lx", IoAdapter->ANum, address+length))
-    return (-1);
-  }
-  mem += address;
-
-  while (length--) {
-    *mem++ = *data++;
-  }
+diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
+			    dword address,
+			    const byte * data, dword length, dword limit)
+{
+	byte *mem = IoAdapter->Address;
+
+	if (((address + length) >= limit) || !mem) {
+		DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
+			 IoAdapter->ANum, address + length))
+		return (-1);
+	}
+	mem += address;
 
-  return (0);
+	while (length--) {
+		*mem++ = *data++;
+	}
+
+	return (0);
 }
 
 static int
-diva_4bri_start_adapter (PISDN_ADAPTER IoAdapter,
-                         dword start_address,
-                         dword features)
-{
-  volatile word *signature;
-  int started = 0;
-  int i;
-
-  /*
-    start adapter
-  */
-  start_qBri_hardware (IoAdapter);
-
-  /*
-    wait for signature in shared memory (max. 3 seconds)
-  */
-  signature = (volatile word *)(&IoAdapter->ram[0x1E]) ;
-
-  for ( i = 0 ; i < 300 ; ++i ) {
-    diva_os_wait (10) ;
-    if (READ_WORD(&signature[0]) == 0x4447) {
-      DBG_TRC(("Protocol startup time %d.%02d seconds", (i / 100), (i % 100) ))
-      started = 1;
-      break;
-    }
-  }
-
-  for (i = 1; i < IoAdapter->tasks; i++) {
-    IoAdapter->QuadroList->QuadroAdapter[i]->features = IoAdapter->features;
-    IoAdapter->QuadroList->QuadroAdapter[i]->a.protocol_capabilities =
-                          IoAdapter->features;
-  }
-
-  if (!started) {
-    DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
-              IoAdapter->Properties.Name, READ_WORD(&signature[0])))
-      (*(IoAdapter->trapFnc))(IoAdapter);
-    IoAdapter->stop(IoAdapter);
-    return (-1);
-  }
-
-  for (i = 0; i < IoAdapter->tasks; i++) {
-    IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
-    IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
-  }
-
-  if (check_qBri_interrupt (IoAdapter)) {
-    DBG_ERR(("A: A(%d) interrupt test failed", IoAdapter->ANum))
-    for (i = 0; i < IoAdapter->tasks; i++) {
-      IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
-    }
-    IoAdapter->stop(IoAdapter);
-    return (-1);
-  }
-
-  IoAdapter->Properties.Features = (word)features;
-  diva_xdi_display_adapter_features (IoAdapter->ANum);
-
-  for (i = 0; i < IoAdapter->tasks; i++) {
-    DBG_LOG(("A(%d) %s adapter successfull started",
-              IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
-              (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
-    diva_xdi_didd_register_adapter (IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
-    IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word)features;
-  }
+diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
+			dword start_address, dword features)
+{
+	volatile word *signature;
+	int started = 0;
+	int i;
+
+	/*
+	   start adapter
+	 */
+	start_qBri_hardware(IoAdapter);
+
+	/*
+	   wait for signature in shared memory (max. 3 seconds)
+	 */
+	signature = (volatile word *) (&IoAdapter->ram[0x1E]);
+
+	for (i = 0; i < 300; ++i) {
+		diva_os_wait(10);
+		if (READ_WORD(&signature[0]) == 0x4447) {
+			DBG_TRC(("Protocol startup time %d.%02d seconds",
+				 (i / 100), (i % 100)))
+			started = 1;
+			break;
+		}
+	}
+
+	for (i = 1; i < IoAdapter->tasks; i++) {
+		IoAdapter->QuadroList->QuadroAdapter[i]->features =
+		    IoAdapter->features;
+		IoAdapter->QuadroList->QuadroAdapter[i]->a.
+		    protocol_capabilities = IoAdapter->features;
+	}
 
-  return (0);
+	if (!started) {
+		DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
+			 IoAdapter->Properties.Name,
+			 READ_WORD(&signature[0])))
+		(*(IoAdapter->trapFnc)) (IoAdapter);
+		IoAdapter->stop(IoAdapter);
+		return (-1);
+	}
+
+	for (i = 0; i < IoAdapter->tasks; i++) {
+		IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
+		IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
+	}
+
+	if (check_qBri_interrupt(IoAdapter)) {
+		DBG_ERR(("A: A(%d) interrupt test failed",
+			 IoAdapter->ANum))
+		for (i = 0; i < IoAdapter->tasks; i++) {
+			IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
+		}
+		IoAdapter->stop(IoAdapter);
+		return (-1);
+	}
+
+	IoAdapter->Properties.Features = (word) features;
+	diva_xdi_display_adapter_features(IoAdapter->ANum);
+
+	for (i = 0; i < IoAdapter->tasks; i++) {
+		DBG_LOG(("A(%d) %s adapter successfull started",
+			 IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
+			 (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
+		diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
+		IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
+	}
+
+	return (0);
 }
 
-static int
-check_qBri_interrupt (PISDN_ADAPTER IoAdapter)
+static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
 {
 #ifdef	SUPPORT_INTERRUPT_TEST_ON_4BRI
-  int i ;
-  ADAPTER *a = &IoAdapter->a ;
+	int i;
+	ADAPTER *a = &IoAdapter->a;
 
-  IoAdapter->IrqCount = 0 ;
+	IoAdapter->IrqCount = 0;
 
-  if ( IoAdapter->ControllerNumber > 0 )
-    return (-1) ;
+	if (IoAdapter->ControllerNumber > 0)
+		return (-1);
 
-  IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE ;
-  /*
-    interrupt test
-  */
-  a->ReadyInt = 1 ;
-  a->ram_out (a, &PR_RAM->ReadyInt, 1) ;
+	IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE;
+	/*
+	   interrupt test
+	 */
+	a->ReadyInt = 1;
+	a->ram_out(a, &PR_RAM->ReadyInt, 1);
 
-  for ( i = 100 ; !IoAdapter->IrqCount && (i-- > 0) ; diva_os_wait(10)) ;
+	for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
 
-  return ((IoAdapter->IrqCount > 0) ? 0 : -1);
+	return ((IoAdapter->IrqCount > 0) ? 0 : -1);
 #else
-  dword volatile *qBriIrq ;
-  /*
-    Reset on-board interrupt register
-  */
-  IoAdapter->IrqCount = 0 ;
-  qBriIrq = (dword volatile *)(&IoAdapter->ctlReg[_4bri_is_rev_2_card (IoAdapter->cardType) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]);
+	dword volatile *qBriIrq;
+	/*
+	   Reset on-board interrupt register
+	 */
+	IoAdapter->IrqCount = 0;
+	qBriIrq =
+	    (dword volatile *) (&IoAdapter->
+				ctlReg[_4bri_is_rev_2_card
+				       (IoAdapter->
+					cardType) ? (MQ2_BREG_IRQ_TEST)
+				       : (MQ_BREG_IRQ_TEST)]);
 
-  WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
+	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
 
-  IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE ;
+	IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE;
 
-  diva_os_wait(100);
+	diva_os_wait(100);
 
-  return (0) ;
-#endif	/* SUPPORT_INTERRUPT_TEST_ON_4BRI */
+	return (0);
+#endif				/* SUPPORT_INTERRUPT_TEST_ON_4BRI */
 }
 
-static void
-diva_4bri_clear_interrupts (diva_os_xdi_adapter_t* a)
+static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a)
 {
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-
-  /*
-    clear any pending interrupt
-  */
-  IoAdapter->disIrq (IoAdapter) ;
-
-  IoAdapter->tst_irq (&IoAdapter->a) ;
-  IoAdapter->clr_irq (&IoAdapter->a) ;
-  IoAdapter->tst_irq (&IoAdapter->a) ;
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
 
-  /*
-    kill pending dpcs
-  */
-  diva_os_cancel_soft_isr (&IoAdapter->req_soft_isr);
-  diva_os_cancel_soft_isr (&IoAdapter->isr_soft_isr);
+	/*
+	   clear any pending interrupt
+	 */
+	IoAdapter->disIrq(IoAdapter);
+
+	IoAdapter->tst_irq(&IoAdapter->a);
+	IoAdapter->clr_irq(&IoAdapter->a);
+	IoAdapter->tst_irq(&IoAdapter->a);
+
+	/*
+	   kill pending dpcs
+	 */
+	diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
+	diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
 }
 
-static int
-diva_4bri_stop_adapter (diva_os_xdi_adapter_t* a)
+static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a)
 {
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-  int i;
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
+	int i;
 
-  if (!IoAdapter->ram) {
-    return (-1);
-  }
-
-  if (!IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't stop PRI adapter - not running", IoAdapter->ANum))
-    return (-1); /* nothing to stop */
-  }
-
-  for (i = 0; i < IoAdapter->tasks; i++) {
-    IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
-  }
-
-  /*
-    Disconnect Adapters from DIDD
-  */
-  for (i = 0; i < IoAdapter->tasks; i++) {
-    diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
-  }
-
-  i = 100;
-
-  /*
-    Stop interrupts
-  */
-  a->clear_interrupts_proc = diva_4bri_clear_interrupts;
-  IoAdapter->a.ReadyInt = 1;
-  IoAdapter->a.ram_inc (&IoAdapter->a, &PR_RAM->ReadyInt) ;
-  do {
-    diva_os_sleep (10);
-  } while (i-- && a->clear_interrupts_proc);
-  if (a->clear_interrupts_proc) {
-    diva_4bri_clear_interrupts (a);
-    a->clear_interrupts_proc = 0;
-    DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter", IoAdapter->ANum))
-  }
-  IoAdapter->a.ReadyInt = 0;
-
-  /*
-    Stop and reset adapter
-  */
-  IoAdapter->stop (IoAdapter) ;
+	if (!IoAdapter->ram) {
+		return (-1);
+	}
 
-  return (0);
-}
+	if (!IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
+			 IoAdapter->ANum))
+		return (-1);	/* nothing to stop */
+	}
+
+	for (i = 0; i < IoAdapter->tasks; i++) {
+		IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
+	}
+
+	/*
+	   Disconnect Adapters from DIDD
+	 */
+	for (i = 0; i < IoAdapter->tasks; i++) {
+		diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
+	}
+
+	i = 100;
+
+	/*
+	   Stop interrupts
+	 */
+	a->clear_interrupts_proc = diva_4bri_clear_interrupts;
+	IoAdapter->a.ReadyInt = 1;
+	IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
+	do {
+		diva_os_sleep(10);
+	} while (i-- && a->clear_interrupts_proc);
+
+	if (a->clear_interrupts_proc) {
+		diva_4bri_clear_interrupts(a);
+		a->clear_interrupts_proc = 0;
+		DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter",
+			 IoAdapter->ANum))
+	}
+	IoAdapter->a.ReadyInt = 0;
 
+	/*
+	   Stop and reset adapter
+	 */
+	IoAdapter->stop(IoAdapter);
+
+	return (0);
+}
diff -Nru a/drivers/isdn/hardware/eicon/os_4bri.h b/drivers/isdn/hardware/eicon/os_4bri.h
--- a/drivers/isdn/hardware/eicon/os_4bri.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/os_4bri.h	Sun Nov 17 20:30:15 2002
@@ -1,8 +1,8 @@
-/* $Id: os_4bri.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: os_4bri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
 
 #ifndef __DIVA_OS_4_BRI_H__
 #define __DIVA_OS_4_BRI_H__
 
-int diva_4bri_init_card (diva_os_xdi_adapter_t* a);
+int diva_4bri_init_card(diva_os_xdi_adapter_t * a);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c
--- a/drivers/isdn/hardware/eicon/os_bri.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/isdn/hardware/eicon/os_bri.c	Sun Nov 17 20:30:02 2002
@@ -1,4 +1,4 @@
-/* $Id: os_bri.c,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: os_bri.c,v 1.1.2.2 2001/02/12 20:23:46 armin Exp $ */
 
 #include "platform.h"
 #include "debuglib.h"
@@ -21,725 +21,753 @@
 /*
 **  IMPORTS
 */
-extern void prepare_maestra_functions (PISDN_ADAPTER IoAdapter);
-extern void diva_xdi_display_adapter_features (int card);
-extern int diva_card_read_xlog (diva_os_xdi_adapter_t* a);
+extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter);
+extern void diva_xdi_display_adapter_features(int card);
+extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
 
 /*
 **  LOCALS
 */
 static int bri_bar_length[3] = {
-  0x80,
-  0x80,
-  0x20
+	0x80,
+	0x80,
+	0x20
 };
-static int diva_bri_cleanup_adapter (diva_os_xdi_adapter_t* a);
-static dword diva_bri_get_serial_number (diva_os_xdi_adapter_t* a);
-static int diva_bri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                                   diva_xdi_um_cfg_cmd_t* cmd,
-                                   int length);
-static int diva_bri_reregister_io (diva_os_xdi_adapter_t* a);
-static int diva_bri_reset_adapter (PISDN_ADAPTER IoAdapter);
-static int diva_bri_write_sdram_block (PISDN_ADAPTER IoAdapter,
-                                       dword  address,
-                                       const byte* data,
-                                       dword length);
-static int diva_bri_start_adapter (PISDN_ADAPTER IoAdapter,
-                                   dword start_address,
-                                   dword features);
-static int diva_bri_stop_adapter (diva_os_xdi_adapter_t* a);
+static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
+static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a);
+static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+				  diva_xdi_um_cfg_cmd_t * cmd, int length);
+static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a);
+static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter);
+static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
+				      dword address,
+				      const byte * data, dword length);
+static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
+				  dword start_address, dword features);
+static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a);
 
 /*
 **  BAR0 - MEM Addr  - 0x80  - NOT USED
 **  BAR1 - I/O Addr  - 0x80
 **  BAR2 - I/O Addr  - 0x20
 */
-int
-diva_bri_init_card (diva_os_xdi_adapter_t* a)
+int diva_bri_init_card(diva_os_xdi_adapter_t * a)
 {
-  int  bar;
-  dword bar2 = 0, bar2_length = 0xffffffff;
-  word cmd = 0, cmd_org;
-  byte Bus, Slot;
-	void* hdev;
-
-  /*
-    Set properties
-  */
-  a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
-  DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
-
-  /*
-    Get resources
-  */
-  for (bar = 0; bar < 3; bar++) {
-    a->resources.pci.bar[bar] = divasa_get_pci_bar (a->resources.pci.bus,
-                                                    a->resources.pci.func,
-                                                    bar,
-                                                    a->resources.pci.hdev);
-    if (!a->resources.pci.bar[bar]) {
-      DBG_ERR(("A: can't get BAR[%d]", bar))
-      return (-1);
-    }
-  }
-
-  a->resources.pci.irq = (byte)divasa_get_pci_irq (a->resources.pci.bus,
-                                                   a->resources.pci.func,
-                                                   a->resources.pci.hdev);
-  if (!a->resources.pci.irq) {
-    DBG_ERR(("A: invalid irq"));
-    return (-1);
-  }
-
-  /*
-    Get length of I/O bar 2 - it is different by older
-    EEPROM version
-  */
-  Bus  = a->resources.pci.bus;
-  Slot = a->resources.pci.func;
-  hdev = a->resources.pci.hdev;
-
-  /*
-    Get plain original values of the BAR2 CDM registers
-  */
-  PCIread (Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev) ;
-  PCIread (Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
-  /*
-    Disable device and get BAR2 length
-  */
-  PCIwrite (Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
-  PCIwrite (Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
-  PCIread  (Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
-  /*
-    Restore BAR2 and CMD registers
-  */
-  PCIwrite (Bus, Slot, 0x18, &bar2 ,sizeof(bar2), hdev) ;
-  PCIwrite (Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
-
-  /*
-    Calculate BAR2 length
-  */
-  bar2_length = (~(bar2_length & ~7)) + 1;
-  DBG_LOG(("BAR[2] length=%lx", bar2_length))
-
-  /*
-    Map and register resources
-  */
-  if (!(a->resources.pci.addr[0] = divasa_remap_pci_bar (a->resources.pci.bar[0],
-                                                         bri_bar_length[0])))
-  {
-    DBG_ERR(("A: BRI, can't map BAR[0]"))
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  sprintf (&a->port_name[0], "BRI %02x:%02x",
-                              a->resources.pci.bus,
-                              a->resources.pci.func);
-
-  if (diva_os_register_io_port (1, a->resources.pci.bar[1],
-                                bri_bar_length[1],
-                                &a->port_name[0])) {
-    DBG_ERR(("A: BRI, can't register BAR[1]"))
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  a->resources.pci.addr[1]   = (void*)(unsigned long)a->resources.pci.bar[1];
-  a->resources.pci.length[1] = bri_bar_length[1];
-
-  if (diva_os_register_io_port (1, a->resources.pci.bar[2],
-                                bar2_length,
-                                &a->port_name[0])) {
-    DBG_ERR(("A: BRI, can't register BAR[2]"))
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  a->resources.pci.addr[2]   = (void*)(unsigned long)a->resources.pci.bar[2];
-  a->resources.pci.length[2] = bar2_length;
-
-  /*
-    Get Serial Number
-  */
-  a->xdi_adapter.serialNo = diva_bri_get_serial_number (a);
-
-  /*
-    Register I/O ports with correct name now
-  */
-  if (diva_bri_reregister_io (a)) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  /*
-    Initialize OS dependent objects
-  */
-  if (diva_os_initialize_spin_lock (&a->xdi_adapter.isr_spin_lock, "isr")) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  if (diva_os_initialize_spin_lock (&a->xdi_adapter.data_spin_lock, "data")) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  strcpy (a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid");
-
-  if (diva_os_initialize_soft_isr (&a->xdi_adapter.req_soft_isr,
-                                   DIDpcRoutine, &a->xdi_adapter)) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  /*
-    Do not initialize second DPC - only one thread will be created
-  */
-  a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
-
-  /*
-    Create entity table
-  */
-  a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
-  a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
-  a->xdi_adapter.e_tbl = diva_os_malloc (0, a->xdi_adapter.e_max * sizeof(E_INFO));
-  if (!a->xdi_adapter.e_tbl) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  memset (a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
-
-  /*
-    Set up interface
-  */
-  a->xdi_adapter.a.io = &a->xdi_adapter;
-  a->xdi_adapter.DIRequest = request;
-  a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter;
-  a->interface.cmd_proc = diva_bri_cmd_card_proc;
-
-  a->xdi_adapter.cfg = a->resources.pci.addr[1];
-  a->xdi_adapter.Address = a->resources.pci.addr[2];
-
-  a->xdi_adapter.reset = a->xdi_adapter.cfg;
-  a->xdi_adapter.port = a->xdi_adapter.Address;
-
-  a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET ;
-  a->xdi_adapter.reset += 0x4C ;	/* PLX 9050 !! */
-  outpp (a->xdi_adapter.reset, 0x41) ;
-
-  prepare_maestra_functions (&a->xdi_adapter);
-
-  a->dsp_mask = 0x00000003;
-
-  /*
-    Set IRQ handler
-  */
-  a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
-  sprintf (a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld",
-                                            (long)a->xdi_adapter.serialNo);
-  if (diva_os_register_irq (a, a->xdi_adapter.irq_info.irq_nr,
-                            a->xdi_adapter.irq_info.irq_name)) {
-    diva_bri_cleanup_adapter (a);
-    return (-1);
-  }
-  a->xdi_adapter.irq_info.registered = 1;
-
-  diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
-                                      a->resources.pci.irq,
-                                      a->xdi_adapter.serialNo);
+	int bar;
+	dword bar2 = 0, bar2_length = 0xffffffff;
+	word cmd = 0, cmd_org;
+	byte Bus, Slot;
+	void *hdev;
+
+	/*
+	   Set properties
+	 */
+	a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
+	DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
+
+	    /*
+	       Get resources
+	     */
+	    for (bar = 0; bar < 3; bar++) {
+		a->resources.pci.bar[bar] =
+		    divasa_get_pci_bar(a->resources.pci.bus,
+				       a->resources.pci.func, bar,
+				       a->resources.pci.hdev);
+		if (!a->resources.pci.bar[bar]) {
+			DBG_ERR(("A: can't get BAR[%d]", bar))
+			return (-1);
+		}
+	}
+
+	a->resources.pci.irq =
+	    (byte) divasa_get_pci_irq(a->resources.pci.bus,
+				      a->resources.pci.func,
+				      a->resources.pci.hdev);
+	if (!a->resources.pci.irq) {
+		DBG_ERR(("A: invalid irq"));
+		return (-1);
+	}
+
+	/*
+	   Get length of I/O bar 2 - it is different by older
+	   EEPROM version
+	 */
+	Bus = a->resources.pci.bus;
+	Slot = a->resources.pci.func;
+	hdev = a->resources.pci.hdev;
+
+	/*
+	   Get plain original values of the BAR2 CDM registers
+	 */
+	PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
+	PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
+	/*
+	   Disable device and get BAR2 length
+	 */
+	PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
+	PCIwrite(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
+	PCIread(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
+	/*
+	   Restore BAR2 and CMD registers
+	 */
+	PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
+	PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
+
+	/*
+	   Calculate BAR2 length
+	 */
+	bar2_length = (~(bar2_length & ~7)) + 1;
+	DBG_LOG(("BAR[2] length=%lx", bar2_length))
+
+	    /*
+	       Map and register resources
+	     */
+	    if (!(a->resources.pci.addr[0] =
+		 divasa_remap_pci_bar(a->resources.pci.bar[0],
+				      bri_bar_length[0]))) {
+		DBG_ERR(("A: BRI, can't map BAR[0]"))
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	sprintf(&a->port_name[0], "BRI %02x:%02x",
+		a->resources.pci.bus, a->resources.pci.func);
+
+	if (diva_os_register_io_port(1, a->resources.pci.bar[1],
+				     bri_bar_length[1], &a->port_name[0])) {
+		DBG_ERR(("A: BRI, can't register BAR[1]"))
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1];
+	a->resources.pci.length[1] = bri_bar_length[1];
+
+	if (diva_os_register_io_port(1, a->resources.pci.bar[2],
+				     bar2_length, &a->port_name[0])) {
+		DBG_ERR(("A: BRI, can't register BAR[2]"))
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2];
+	a->resources.pci.length[2] = bar2_length;
+
+	/*
+	   Get Serial Number
+	 */
+	a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
+
+	/*
+	   Register I/O ports with correct name now
+	 */
+	if (diva_bri_reregister_io(a)) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	/*
+	   Initialize OS dependent objects
+	 */
+	if (diva_os_initialize_spin_lock
+	    (&a->xdi_adapter.isr_spin_lock, "isr")) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	if (diva_os_initialize_spin_lock
+	    (&a->xdi_adapter.data_spin_lock, "data")) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid");
+
+	if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
+					DIDpcRoutine, &a->xdi_adapter)) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	/*
+	   Do not initialize second DPC - only one thread will be created
+	 */
+	a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
+
+	/*
+	   Create entity table
+	 */
+	a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
+	a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
+	a->xdi_adapter.e_tbl = diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
+	if (!a->xdi_adapter.e_tbl) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
+
+	/*
+	   Set up interface
+	 */
+	a->xdi_adapter.a.io = &a->xdi_adapter;
+	a->xdi_adapter.DIRequest = request;
+	a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter;
+	a->interface.cmd_proc = diva_bri_cmd_card_proc;
+
+	a->xdi_adapter.cfg = a->resources.pci.addr[1];
+	a->xdi_adapter.Address = a->resources.pci.addr[2];
+
+	a->xdi_adapter.reset = a->xdi_adapter.cfg;
+	a->xdi_adapter.port = a->xdi_adapter.Address;
+
+	a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET;
+	a->xdi_adapter.reset += 0x4C;	/* PLX 9050 !! */
+	outpp(a->xdi_adapter.reset, 0x41);
+
+	prepare_maestra_functions(&a->xdi_adapter);
+
+	a->dsp_mask = 0x00000003;
+
+	/*
+	   Set IRQ handler
+	 */
+	a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
+	sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld",
+		(long) a->xdi_adapter.serialNo);
+	if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
+				 a->xdi_adapter.irq_info.irq_name)) {
+		diva_bri_cleanup_adapter(a);
+		return (-1);
+	}
+	a->xdi_adapter.irq_info.registered = 1;
+
+	diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
+		      a->resources.pci.irq, a->xdi_adapter.serialNo);
+
+	return (0);
+}
+
+
+static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
+{
+	int i;
+
+	if (a->xdi_adapter.Initialized) {
+		diva_bri_stop_adapter(a);
+	}
+
+	/*
+	   Remove ISR Handler
+	 */
+	if (a->xdi_adapter.irq_info.registered) {
+		diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
+	}
+	a->xdi_adapter.irq_info.registered = 0;
+
+	if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) {
+		divasa_unmap_pci_bar(a->resources.pci.addr[0]);
+		a->resources.pci.addr[0] = 0;
+		a->resources.pci.bar[0] = 0;
+	}
+
+	for (i = 1; i < 3; i++) {
+		if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) {
+			diva_os_register_io_port(0,
+						 a->resources.pci.bar[i],
+						 a->resources.pci.
+						 length[i],
+						 &a->port_name[0]);
+			a->resources.pci.addr[i] = 0;
+			a->resources.pci.bar[i] = 0;
+		}
+	}
+
+	/*
+	   Free OS objects
+	 */
+	diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
+	diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
+
+	diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
+	a->xdi_adapter.isr_soft_isr.object = 0;
+
+	diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
+	diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
+
+	/*
+	   Free memory
+	 */
+	if (a->xdi_adapter.e_tbl) {
+		diva_os_free(0, a->xdi_adapter.e_tbl);
+		a->xdi_adapter.e_tbl = 0;
+	}
 
-  return (0);
+	return (0);
 }
 
-
-static int
-diva_bri_cleanup_adapter (diva_os_xdi_adapter_t* a)
-{
-  int i;
-
-  if (a->xdi_adapter.Initialized) {
-    diva_bri_stop_adapter (a);
-  }
-
-  /*
-    Remove ISR Handler
-  */
-  if (a->xdi_adapter.irq_info.registered) {
-    diva_os_remove_irq (a, a->xdi_adapter.irq_info.irq_nr);
-  }
-  a->xdi_adapter.irq_info.registered = 0;
-
-  if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) {
-    divasa_unmap_pci_bar (a->resources.pci.addr[0]);
-    a->resources.pci.addr[0] = 0;
-    a->resources.pci.bar [0] = 0;
-  }
-
-  for (i = 1; i < 3; i++) {
-    if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) {
-      diva_os_register_io_port (0, a->resources.pci.bar[i],
-                                   a->resources.pci.length[i],
-                                   &a->port_name[0]);
-      a->resources.pci.addr[i] = 0;
-      a->resources.pci.bar [i] = 0;
-    }
-  }
-
-  /*
-    Free OS objects
-  */
-  diva_os_cancel_soft_isr (&a->xdi_adapter.req_soft_isr);
-  diva_os_cancel_soft_isr (&a->xdi_adapter.isr_soft_isr);
-
-  diva_os_remove_soft_isr (&a->xdi_adapter.req_soft_isr);
-  a->xdi_adapter.isr_soft_isr.object = 0;
-
-  diva_os_destroy_spin_lock (&a->xdi_adapter.isr_spin_lock, "rm");
-  diva_os_destroy_spin_lock (&a->xdi_adapter.data_spin_lock, "rm");
-
-  /*
-    Free memory
-  */
-  if (a->xdi_adapter.e_tbl) {
-    diva_os_free (0, a->xdi_adapter.e_tbl);
-    a->xdi_adapter.e_tbl = 0;
-  }  
-
-  return (0);
-}
-
-void
-diva_os_prepare_maestra_functions (PISDN_ADAPTER IoAdapter)
+void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
 {
 }
 
 /*
 **  Get serial number
 */
-static dword
-diva_bri_get_serial_number (diva_os_xdi_adapter_t* a)
+static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a)
 {
-  dword serNo = 0;
-  byte*	confIO;
-  word  serHi, serLo, *confMem;
-
-  confIO = (byte*)a->resources.pci.addr[1];
-  serHi  = (word)(inppw(&confIO[0x22]) & 0x0FFF) ;
-  serLo  = (word)(inppw(&confIO[0x26]) & 0x0FFF) ;
-  serNo  = ((dword)serHi << 16) | (dword)serLo ;
-
-  if ((serNo == 0) || (serNo == 0xFFFFFFFF)) {
-    DBG_FTL(("W: BRI use BAR[0] to get card serial number"))
-
-    confMem = (word*)a->resources.pci.addr[0];
-    serHi   = (word)(READ_WORD(&confMem[0x11]) & 0x0FFF) ;
-    serLo   = (word)(READ_WORD(&confMem[0x13]) & 0x0FFF) ;
-    serNo   = (((dword)serHi) << 16) | ((dword)serLo) ;
-  }
+	dword serNo = 0;
+	byte *confIO;
+	word serHi, serLo, *confMem;
+
+	confIO = (byte *) a->resources.pci.addr[1];
+	serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF);
+	serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF);
+	serNo = ((dword) serHi << 16) | (dword) serLo;
+
+	if ((serNo == 0) || (serNo == 0xFFFFFFFF)) {
+		DBG_FTL(("W: BRI use BAR[0] to get card serial number"))
+
+		confMem = (word *) a->resources.pci.addr[0];
+		serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF);
+		serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF);
+		serNo = (((dword) serHi) << 16) | ((dword) serLo);
+	}
 
-  DBG_LOG(("Serial Number=%ld", serNo))
+	DBG_LOG(("Serial Number=%ld", serNo))
 
-  return (serNo);
+	return (serNo);
 }
 
 /*
 **  Unregister I/O and register it with new name,
 **  based on Serial Number
 */
-static int
-diva_bri_reregister_io (diva_os_xdi_adapter_t* a)
+static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a)
 {
-  int i;
+	int i;
 
-  for (i = 1; i < 3; i++) {
-    diva_os_register_io_port (0, a->resources.pci.bar[i],
-                                 a->resources.pci.length[i],
-                                &a->port_name[0]);
-    a->resources.pci.addr[i] = 0;
-  }
-
-  sprintf (a->port_name, "DIVA BRI %ld", (long)a->xdi_adapter.serialNo);
-
-  for (i = 1; i < 3; i++) {
-    if (diva_os_register_io_port (1, a->resources.pci.bar[i],
-                                     a->resources.pci.length[i],
-                                    &a->port_name[0])) {
-      DBG_ERR(("A: failed to reregister BAR[%d]", i))
-      return (-1);
-    }
-    a->resources.pci.addr[i] = (void*)(unsigned long)a->resources.pci.bar[i];
-  }
+	for (i = 1; i < 3; i++) {
+		diva_os_register_io_port(0, a->resources.pci.bar[i],
+					 a->resources.pci.length[i],
+					 &a->port_name[0]);
+		a->resources.pci.addr[i] = 0;
+	}
+
+	sprintf(a->port_name, "DIVA BRI %ld",
+		(long) a->xdi_adapter.serialNo);
+
+	for (i = 1; i < 3; i++) {
+		if (diva_os_register_io_port(1, a->resources.pci.bar[i],
+					     a->resources.pci.length[i],
+					     &a->port_name[0])) {
+			DBG_ERR(("A: failed to reregister BAR[%d]", i))
+			return (-1);
+		}
+		a->resources.pci.addr[i] =
+		    (void *) (unsigned long) a->resources.pci.bar[i];
+	}
 
-  return (0);
+	return (0);
 }
 
 /*
 **  Process command from user mode
 */
 static int
-diva_bri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                        diva_xdi_um_cfg_cmd_t* cmd,
-                        int length)
-{
-  int ret = -1;
-
-  if (cmd->adapter != a->controller) {
-    DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
-            cmd->adapter, a->controller))
-    return (-1);
-  }
-
-  switch (cmd->command) {
-    case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->CardOrdinal;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->xdi_adapter.serialNo;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
-      a->xdi_mbox.data_length = sizeof(dword)*9;
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        int i;
-        dword* data = (dword*)a->xdi_mbox.data;
-
-        for (i = 0; i < 8; i++) {
-          *data++ = a->resources.pci.bar[i];
-        }
-        *data++ = (dword)a->resources.pci.irq;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_CARD_STATE:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        dword* data = (dword*)a->xdi_mbox.data;
-        if (!a->xdi_adapter.port) {
-          *data = 3;
-        } else if (a->xdi_adapter.trapped) {
-          *data = 2;
-        } else if (a->xdi_adapter.Initialized) {
-          *data = 1;
-        } else {
-          *data = 0;
-        }
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_RESET_ADAPTER:
-      ret = diva_bri_reset_adapter (&a->xdi_adapter);
-      break;
-
-    case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
-      ret = diva_bri_write_sdram_block (&a->xdi_adapter,
-                                        cmd->command_data.write_sdram.offset,
-                                        (byte*)&cmd[1],
-                                        cmd->command_data.write_sdram.length);
-      break;
-
-    case DIVA_XDI_UM_CMD_START_ADAPTER:
-      ret = diva_bri_start_adapter (&a->xdi_adapter,
-                                    cmd->command_data.start.offset,
-                                    cmd->command_data.start.features);
-      break;
-
-    case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
-      a->xdi_adapter.features = cmd->command_data.features.features;
-      a->xdi_adapter.a.protocol_capabilities = a->xdi_adapter.features;
-      DBG_TRC(("Set raw protocol features (%08x)", a->xdi_adapter.features))
-      ret = 0;
-      break;
-
-    case DIVA_XDI_UM_CMD_STOP_ADAPTER:
-      ret = diva_bri_stop_adapter (a);
-      break;
-
-    case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
-      ret = diva_card_read_xlog (a);
-      break;
-
-    default:
-      DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller, cmd->command))
-  }
-
-  return (ret);
-}
-
-static int
-diva_bri_reset_adapter (PISDN_ADAPTER IoAdapter)
+diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+		       diva_xdi_um_cfg_cmd_t * cmd, int length)
 {
-  byte*  addrHi, *addrLo, *ioaddr ;
-  dword i;
+	int ret = -1;
 
-  if (!IoAdapter->port) {
-    return (-1);
-  }
-  if (IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first",
-              IoAdapter->ANum))
-    return (-1);
-  }
-  addrHi = IoAdapter->port + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH);
-  addrLo = IoAdapter->port + ADDR ;
-  ioaddr = IoAdapter->port + DATA ;
-  (*(IoAdapter->rstFnc))(IoAdapter);
-  diva_os_wait(100);
-  /*
-    recover
-  */
-  outpp  (addrHi, (byte) 0) ;
-  outppw (addrLo, (word) 0) ;
-  outppw (ioaddr, (word) 0) ;
-  /*
-    clear shared memory
-  */
-  outpp  (addrHi, (byte)((IoAdapter->MemoryBase + IoAdapter->MemorySize -
-                          BRI_SHARED_RAM_SIZE) >> 16)) ;
-  outppw (addrLo, 0) ;
-  for ( i = 0; i < 0x8000; outppw (ioaddr, 0), ++i);
-  diva_os_wait (100) ;
-
-  /*
-    clear signature
-  */
-  outpp  (addrHi, (byte)((IoAdapter->MemoryBase + IoAdapter->MemorySize -
-                          BRI_SHARED_RAM_SIZE) >> 16)) ;
-  outppw (addrLo, 0x1e) ;
-  outpp (ioaddr, 0) ;
-  outpp (ioaddr, 0) ;
-
-  outpp  (addrHi, (byte) 0) ;
-  outppw (addrLo, (word) 0) ;
-  outppw (ioaddr, (word) 0) ;
-
-  /*
-    Forget all outstanding entities
-  */
-  IoAdapter->e_count =  0;
-  if (IoAdapter->e_tbl) {
-    memset (IoAdapter->e_tbl, 0x00, IoAdapter->e_max * sizeof(E_INFO));
-  }
-  IoAdapter->head = 0;
-  IoAdapter->tail = 0;
-  IoAdapter->assign = 0;
-  IoAdapter->trapped = 0;
-
-  memset (&IoAdapter->a.IdTable[0],              0x00, sizeof(IoAdapter->a.IdTable));
-  memset (&IoAdapter->a.IdTypeTable[0],          0x00, sizeof(IoAdapter->a.IdTypeTable));
-  memset (&IoAdapter->a.FlowControlIdTable[0],   0x00, sizeof(IoAdapter->a.FlowControlIdTable));
-  memset (&IoAdapter->a.FlowControlSkipTable[0], 0x00, sizeof(IoAdapter->a.FlowControlSkipTable));
-  memset (&IoAdapter->a.misc_flags_table[0],     0x00, sizeof(IoAdapter->a.misc_flags_table));
-  memset (&IoAdapter->a.rx_stream[0],            0x00, sizeof(IoAdapter->a.rx_stream));
-  memset (&IoAdapter->a.tx_stream[0],            0x00, sizeof(IoAdapter->a.tx_stream));
-  memset (&IoAdapter->a.tx_pos[0],               0x00, sizeof(IoAdapter->a.tx_pos));
-  memset (&IoAdapter->a.rx_pos[0],               0x00, sizeof(IoAdapter->a.rx_pos));
+	if (cmd->adapter != a->controller) {
+		DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
+			 cmd->adapter, a->controller))
+		return (-1);
+	}
+
+	switch (cmd->command) {
+	case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->CardOrdinal;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->xdi_adapter.serialNo;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
+		a->xdi_mbox.data_length = sizeof(dword) * 9;
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			int i;
+			dword *data = (dword *) a->xdi_mbox.data;
+
+			for (i = 0; i < 8; i++) {
+				*data++ = a->resources.pci.bar[i];
+			}
+			*data++ = (dword) a->resources.pci.irq;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_CARD_STATE:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			dword *data = (dword *) a->xdi_mbox.data;
+			if (!a->xdi_adapter.port) {
+				*data = 3;
+			} else if (a->xdi_adapter.trapped) {
+				*data = 2;
+			} else if (a->xdi_adapter.Initialized) {
+				*data = 1;
+			} else {
+				*data = 0;
+			}
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_RESET_ADAPTER:
+		ret = diva_bri_reset_adapter(&a->xdi_adapter);
+		break;
+
+	case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
+		ret = diva_bri_write_sdram_block(&a->xdi_adapter,
+						 cmd->command_data.
+						 write_sdram.offset,
+						 (byte *) & cmd[1],
+						 cmd->command_data.
+						 write_sdram.length);
+		break;
+
+	case DIVA_XDI_UM_CMD_START_ADAPTER:
+		ret = diva_bri_start_adapter(&a->xdi_adapter,
+					     cmd->command_data.start.
+					     offset,
+					     cmd->command_data.start.
+					     features);
+		break;
+
+	case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
+		a->xdi_adapter.features =
+		    cmd->command_data.features.features;
+		a->xdi_adapter.a.protocol_capabilities =
+		    a->xdi_adapter.features;
+		DBG_TRC(
+			("Set raw protocol features (%08x)",
+			 a->xdi_adapter.features)) ret = 0;
+		break;
+
+	case DIVA_XDI_UM_CMD_STOP_ADAPTER:
+		ret = diva_bri_stop_adapter(a);
+		break;
+
+	case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
+		ret = diva_card_read_xlog(a);
+		break;
+
+	default:
+		DBG_ERR(
+			("A: A(%d) invalid cmd=%d", a->controller,
+			 cmd->command))}
+
+	return (ret);
+}
+
+static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter)
+{
+	byte *addrHi, *addrLo, *ioaddr;
+	dword i;
+
+	if (!IoAdapter->port) {
+		return (-1);
+	}
+	if (IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first",
+			 IoAdapter->ANum)) return (-1);
+	}
+	addrHi =
+	    IoAdapter->port +
+	    ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
+	addrLo = IoAdapter->port + ADDR;
+	ioaddr = IoAdapter->port + DATA;
+	(*(IoAdapter->rstFnc)) (IoAdapter);
+	diva_os_wait(100);
+	/*
+	   recover
+	 */
+	outpp(addrHi, (byte) 0);
+	outppw(addrLo, (word) 0);
+	outppw(ioaddr, (word) 0);
+	/*
+	   clear shared memory
+	 */
+	outpp(addrHi,
+	      (byte) (
+		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
+		       BRI_SHARED_RAM_SIZE) >> 16));
+	outppw(addrLo, 0);
+	for (i = 0; i < 0x8000; outppw(ioaddr, 0), ++i);
+	diva_os_wait(100);
+
+	/*
+	   clear signature
+	 */
+	outpp(addrHi,
+	      (byte) (
+		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
+		       BRI_SHARED_RAM_SIZE) >> 16));
+	outppw(addrLo, 0x1e);
+	outpp(ioaddr, 0);
+	outpp(ioaddr, 0);
+
+	outpp(addrHi, (byte) 0);
+	outppw(addrLo, (word) 0);
+	outppw(ioaddr, (word) 0);
+
+	/*
+	   Forget all outstanding entities
+	 */
+	IoAdapter->e_count = 0;
+	if (IoAdapter->e_tbl) {
+		memset(IoAdapter->e_tbl, 0x00,
+		       IoAdapter->e_max * sizeof(E_INFO));
+	}
+	IoAdapter->head = 0;
+	IoAdapter->tail = 0;
+	IoAdapter->assign = 0;
+	IoAdapter->trapped = 0;
+
+	memset(&IoAdapter->a.IdTable[0], 0x00,
+	       sizeof(IoAdapter->a.IdTable));
+	memset(&IoAdapter->a.IdTypeTable[0], 0x00,
+	       sizeof(IoAdapter->a.IdTypeTable));
+	memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
+	       sizeof(IoAdapter->a.FlowControlIdTable));
+	memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
+	       sizeof(IoAdapter->a.FlowControlSkipTable));
+	memset(&IoAdapter->a.misc_flags_table[0], 0x00,
+	       sizeof(IoAdapter->a.misc_flags_table));
+	memset(&IoAdapter->a.rx_stream[0], 0x00,
+	       sizeof(IoAdapter->a.rx_stream));
+	memset(&IoAdapter->a.tx_stream[0], 0x00,
+	       sizeof(IoAdapter->a.tx_stream));
+	memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
+	memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
 
-  return (0);
+	return (0);
 }
 
 static int
-diva_bri_write_sdram_block (PISDN_ADAPTER IoAdapter,
-                            dword address,
-                            const byte* data,
-                            dword length)
-{
-  byte*  addrHi, *addrLo, *ioaddr;
-
-  if (!IoAdapter->port) {
-    return (-1);
-  }
-
-  addrHi = IoAdapter->port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ;
-  addrLo = IoAdapter->port + ADDR ;
-  ioaddr = IoAdapter->port + DATA ;
-
-  while (length--) {
-    outpp  (addrHi, (word)(address >> 16)) ;
-    outppw (addrLo, (word)(address & 0x0000ffff));
-    outpp (ioaddr, *data++);
-    address++;
-  }
+diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
+			   dword address, const byte * data, dword length)
+{
+	byte *addrHi, *addrLo, *ioaddr;
+
+	if (!IoAdapter->port) {
+		return (-1);
+	}
+
+	addrHi =
+	    IoAdapter->port +
+	    ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
+	addrLo = IoAdapter->port + ADDR;
+	ioaddr = IoAdapter->port + DATA;
+
+	while (length--) {
+		outpp(addrHi, (word) (address >> 16));
+		outppw(addrLo, (word) (address & 0x0000ffff));
+		outpp(ioaddr, *data++);
+		address++;
+	}
 
-  return (0);
+	return (0);
 }
 
 static int
-diva_bri_start_adapter (PISDN_ADAPTER IoAdapter,
-                        dword start_address,
-                        dword features)
-{
-  dword i, test;
-  byte*  addrHi, *addrLo, *ioaddr;
-  int started = 0;
-  ADAPTER *a = &IoAdapter->a ;
-
-  if (IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) bri_start_adapter, adapter already running",
-              IoAdapter->ANum))
-    return (-1);
-  }
-  if (!IoAdapter->port) {
-    DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped",
-              IoAdapter->ANum))
-    return (-1);
-  }
-
-  sprintf (IoAdapter->Name, "A(%d)", (int)IoAdapter->ANum);
-  DBG_LOG(("A(%d) start BRI", IoAdapter->ANum))
-
-  addrHi =   IoAdapter->port + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH);
-  addrLo = IoAdapter->port + ADDR ;
-  ioaddr = IoAdapter->port + DATA ;
-
-  outpp  (addrHi, (byte)((IoAdapter->MemoryBase + IoAdapter->MemorySize -
-                          BRI_SHARED_RAM_SIZE) >> 16)) ;
-  outppw (addrLo, 0x1e) ;
-  outppw (ioaddr, 0x00) ;
-
-  /*
-    start the protocol code
-  */
-  outpp (IoAdapter->ctlReg, 0x08) ;
-
-  /*
-    wait for signature (max. 3 seconds)
-  */
-  for (i = 0; i < 300; ++i) {
-    diva_os_wait (10);
-    outpp (addrHi, (byte)((IoAdapter->MemoryBase + IoAdapter->MemorySize -
-                           BRI_SHARED_RAM_SIZE) >> 16)) ;
-    outppw (addrLo, 0x1e) ;
-    test = (dword)inppw (ioaddr) ;
-    if (test == 0x4447) {
-      DBG_LOG(("Protocol startup time %d.%02d seconds", (i / 100), (i % 100)))
-      started = 1;
-      break;
-    }
-  }
-
-  if (!started) {
-    DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X",
-              IoAdapter->ANum, IoAdapter->Properties.Name, test))
-    (*(IoAdapter->trapFnc))(IoAdapter);
-    return (-1);
-  }
-
-  IoAdapter->Initialized = 1;
-
-  /*
-    Check Interrupt
-  */
-  IoAdapter->IrqCount = 0 ;
-  a->ReadyInt = 1 ;
-
-  if (IoAdapter->reset) {
-    outpp (IoAdapter->reset, 0x41) ;
-  }
-
-  a->ram_out (a, &PR_RAM->ReadyInt, 1);
-  for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) {
-    diva_os_wait (10);
-  }
-  if (!IoAdapter->IrqCount) {
-    DBG_ERR(("A: A(%d) interrupt test failed", IoAdapter->ANum))
-    IoAdapter->Initialized = 0;
-    IoAdapter->stop(IoAdapter);
-    return (-1);
-  }
-
-  IoAdapter->Properties.Features = (word)features;
-  diva_xdi_display_adapter_features (IoAdapter->ANum);
-  DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum))
-  /*
-    Register with DIDD
-  */
-  diva_xdi_didd_register_adapter (IoAdapter->ANum);
-
-  return (0);
-}
-
-static void
-diva_bri_clear_interrupts (diva_os_xdi_adapter_t* a)
-{
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-
-  /*
-    clear any pending interrupt
-  */
-  IoAdapter->disIrq (IoAdapter) ;
-
-  IoAdapter->tst_irq (&IoAdapter->a) ;
-  IoAdapter->clr_irq (&IoAdapter->a) ;
-  IoAdapter->tst_irq (&IoAdapter->a) ;
-
-  /*
-    kill pending dpcs
-  */
-  diva_os_cancel_soft_isr (&IoAdapter->req_soft_isr);
-  diva_os_cancel_soft_isr (&IoAdapter->isr_soft_isr);
+diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
+		       dword start_address, dword features)
+{
+	dword i, test;
+	byte *addrHi, *addrLo, *ioaddr;
+	int started = 0;
+	ADAPTER *a = &IoAdapter->a;
+
+	if (IoAdapter->Initialized) {
+		DBG_ERR(
+			("A: A(%d) bri_start_adapter, adapter already running",
+			 IoAdapter->ANum)) return (-1);
+	}
+	if (!IoAdapter->port) {
+		DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped",
+			 IoAdapter->ANum)) return (-1);
+	}
+
+	sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
+	DBG_LOG(("A(%d) start BRI", IoAdapter->ANum))
+
+	    addrHi =
+	    IoAdapter->port +
+	    ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
+	addrLo = IoAdapter->port + ADDR;
+	ioaddr = IoAdapter->port + DATA;
+
+	outpp(addrHi,
+	      (byte) (
+		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
+		       BRI_SHARED_RAM_SIZE) >> 16));
+	outppw(addrLo, 0x1e);
+	outppw(ioaddr, 0x00);
+
+	/*
+	   start the protocol code
+	 */
+	outpp(IoAdapter->ctlReg, 0x08);
+
+	/*
+	   wait for signature (max. 3 seconds)
+	 */
+	for (i = 0; i < 300; ++i) {
+		diva_os_wait(10);
+		outpp(addrHi,
+		      (byte) (
+			      (IoAdapter->MemoryBase +
+			       IoAdapter->MemorySize -
+			       BRI_SHARED_RAM_SIZE) >> 16));
+		outppw(addrLo, 0x1e);
+		test = (dword) inppw(ioaddr);
+		if (test == 0x4447) {
+			DBG_LOG(
+				("Protocol startup time %d.%02d seconds",
+				 (i / 100), (i % 100)))
+			started = 1;
+			break;
+		}
+	}
+
+	if (!started) {
+		DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X",
+			 IoAdapter->ANum, IoAdapter->Properties.Name,
+			 test))
+		(*(IoAdapter->trapFnc)) (IoAdapter);
+		return (-1);
+	}
+
+	IoAdapter->Initialized = 1;
+
+	/*
+	   Check Interrupt
+	 */
+	IoAdapter->IrqCount = 0;
+	a->ReadyInt = 1;
+
+	if (IoAdapter->reset) {
+		outpp(IoAdapter->reset, 0x41);
+	}
+
+	a->ram_out(a, &PR_RAM->ReadyInt, 1);
+	for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) {
+		diva_os_wait(10);
+	}
+	if (!IoAdapter->IrqCount) {
+		DBG_ERR(
+			("A: A(%d) interrupt test failed",
+			 IoAdapter->ANum))
+		IoAdapter->Initialized = 0;
+		IoAdapter->stop(IoAdapter);
+		return (-1);
+	}
+
+	IoAdapter->Properties.Features = (word) features;
+	diva_xdi_display_adapter_features(IoAdapter->ANum);
+	DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum))
+	    /*
+	       Register with DIDD
+	     */
+	diva_xdi_didd_register_adapter(IoAdapter->ANum);
+
+	return (0);
+}
+
+static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t * a)
+{
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
+
+	/*
+	   clear any pending interrupt
+	 */
+	IoAdapter->disIrq(IoAdapter);
+
+	IoAdapter->tst_irq(&IoAdapter->a);
+	IoAdapter->clr_irq(&IoAdapter->a);
+	IoAdapter->tst_irq(&IoAdapter->a);
+
+	/*
+	   kill pending dpcs
+	 */
+	diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
+	diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
 }
 
 /*
 **  Stop card
 */
-static int
-diva_bri_stop_adapter (diva_os_xdi_adapter_t* a)
+static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a)
 {
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-  int i = 100;
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
+	int i = 100;
 
-  if (!IoAdapter->port) {
-    return (-1);
-  }
-  if (!IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't stop BRI adapter - not running",
-              IoAdapter->ANum))
-    return (-1); /* nothing to stop */
-  }
-  IoAdapter->Initialized = 0;
-
-  /*
-    Disconnect Adapter from DIDD
-  */
-  diva_xdi_didd_remove_adapter (IoAdapter->ANum);
-
-  /*
-    Stop interrupts
-  */
-  a->clear_interrupts_proc = diva_bri_clear_interrupts;
-  IoAdapter->a.ReadyInt = 1 ;
-  IoAdapter->a.ram_inc (&IoAdapter->a, &PR_RAM->ReadyInt);
-  do {
-    diva_os_sleep (10);
-  } while (i-- && a->clear_interrupts_proc);
-  if (a->clear_interrupts_proc) {
-    diva_bri_clear_interrupts (a);
-    a->clear_interrupts_proc = 0;
-    DBG_ERR(("A: A(%d) no final interrupt from BRI adapter", IoAdapter->ANum))
-  }
-  IoAdapter->a.ReadyInt = 0 ;
-
-  /*
-    Stop and reset adapter
-  */
-  IoAdapter->stop (IoAdapter) ;
+	if (!IoAdapter->port) {
+		return (-1);
+	}
+	if (!IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't stop BRI adapter - not running",
+			 IoAdapter->ANum))
+		return (-1);	/* nothing to stop */
+	}
+	IoAdapter->Initialized = 0;
+
+	/*
+	   Disconnect Adapter from DIDD
+	 */
+	diva_xdi_didd_remove_adapter(IoAdapter->ANum);
+
+	/*
+	   Stop interrupts
+	 */
+	a->clear_interrupts_proc = diva_bri_clear_interrupts;
+	IoAdapter->a.ReadyInt = 1;
+	IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
+	do {
+		diva_os_sleep(10);
+	} while (i-- && a->clear_interrupts_proc);
+	if (a->clear_interrupts_proc) {
+		diva_bri_clear_interrupts(a);
+		a->clear_interrupts_proc = 0;
+		DBG_ERR(("A: A(%d) no final interrupt from BRI adapter",
+			 IoAdapter->ANum))
+	}
+	IoAdapter->a.ReadyInt = 0;
+
+	/*
+	   Stop and reset adapter
+	 */
+	IoAdapter->stop(IoAdapter);
 
-  return (0);
+	return (0);
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/os_bri.h b/drivers/isdn/hardware/eicon/os_bri.h
--- a/drivers/isdn/hardware/eicon/os_bri.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/hardware/eicon/os_bri.h	Sun Nov 17 20:30:12 2002
@@ -1,8 +1,8 @@
-/* $Id: os_bri.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: os_bri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
 
 #ifndef __DIVA_OS_BRI_REV_1_H__
 #define __DIVA_OS_BRI_REV_1_H__
 
-int diva_bri_init_card (diva_os_xdi_adapter_t* a);
+int diva_bri_init_card(diva_os_xdi_adapter_t * a);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
--- a/drivers/isdn/hardware/eicon/os_pri.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/isdn/hardware/eicon/os_pri.c	Sun Nov 17 20:30:13 2002
@@ -1,4 +1,4 @@
-/* $Id: os_pri.c,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: os_pri.c,v 1.1.2.3 2001/02/14 21:10:19 armin Exp $ */
 
 #include "platform.h"
 #include "debuglib.h"
@@ -24,39 +24,37 @@
    OS Dependent part of XDI driver for DIVA PRI Adapter
 
    DSP detection/validation by Anthony Booth (Eicon Networks, www.eicon.com)
--------------------------------------------------------------------------- */ 
+-------------------------------------------------------------------------- */
 
 #define DIVA_PRI_NO_PCI_BIOS_WORKAROUND 1
 
-extern int diva_card_read_xlog (diva_os_xdi_adapter_t* a);
+extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
 
 /*
 **  IMPORTS
 */
-extern void prepare_pri_functions  (PISDN_ADAPTER IoAdapter);
-extern void prepare_pri2_functions (PISDN_ADAPTER IoAdapter);
-extern void diva_xdi_display_adapter_features (int card);
-
-static int diva_pri_cleanup_adapter (diva_os_xdi_adapter_t* a);
-static int diva_pri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                                   diva_xdi_um_cfg_cmd_t* cmd,
-                                   int length);
-static int pri_get_serial_number (diva_os_xdi_adapter_t* a);
-static int diva_pri_stop_adapter (diva_os_xdi_adapter_t* a);
-static dword diva_pri_detect_dsps (diva_os_xdi_adapter_t* a);
+extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter);
+extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter);
+extern void diva_xdi_display_adapter_features(int card);
+
+static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a);
+static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+				  diva_xdi_um_cfg_cmd_t * cmd, int length);
+static int pri_get_serial_number(diva_os_xdi_adapter_t * a);
+static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a);
+static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a);
 
 /*
 **  Check card revision
 */
-static int
-pri_is_rev_2_card (int card_ordinal)
+static int pri_is_rev_2_card(int card_ordinal)
 {
-  switch (card_ordinal) {
-    case CARDTYPE_DIVASRV_P_30M_V2_PCI:
-    case CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI:
-      return (1);
-  }
-  return (0);
+	switch (card_ordinal) {
+	case CARDTYPE_DIVASRV_P_30M_V2_PCI:
+	case CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI:
+		return (1);
+	}
+	return (0);
 }
 
 /*
@@ -66,480 +64,493 @@
 **  BAR3 - FLASH (REG),		0x8000
 **  BAR4 - CONFIG (CFG),	0x1000
 */
-int
-diva_pri_init_card (diva_os_xdi_adapter_t* a)
-{
-  int bar = 0;
-  int pri_rev_2;
-  unsigned long bar_length[5] = {
-    MP_MEMORY_SIZE,
-    0x1000,
-    0x2000,
-    0x8000,
-    0x1000
-  };
-
-  pri_rev_2 = pri_is_rev_2_card (a->CardOrdinal);
-
-  if (pri_rev_2) {
-    bar_length[0] = MP2_MEMORY_SIZE;
-  }
-  /*
-    Set properties
-  */
-  a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
-  DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
-
-  /*
-    First initialization step: get and check hardware resoures.
-    Do not map resources and do not acecess card at this step
-  */
-
-  for (bar = 0; bar < 5; bar++) {
-    a->resources.pci.bar[bar] = divasa_get_pci_bar (a->resources.pci.bus,
-                                                    a->resources.pci.func,
-                                                    bar,
-                                                    a->resources.pci.hdev);
-    if (!a->resources.pci.bar[bar] ||
-        (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
-      DBG_ERR(("A: invalid bar[%d]=%08x", bar, a->resources.pci.bar[bar]))
-      return (-1);
-    }
-  }
-  a->resources.pci.irq = (byte)divasa_get_pci_irq (a->resources.pci.bus,
-                                                   a->resources.pci.func,
-                                                   a->resources.pci.hdev);
-  if (!a->resources.pci.irq) {
-    DBG_ERR(("A: invalid irq"));
-    return (-1);
-  }
-
-  /*
-    Map all BAR's
-  */
-  for (bar = 0; bar < 5; bar++) {
-    a->resources.pci.addr[bar] = divasa_remap_pci_bar (a->resources.pci.bar[bar], bar_length[bar]);
-    if (!a->resources.pci.addr[bar]) {
-      DBG_ERR(("A: A(%d), can't map bar[%d]", a->controller, bar))
-      diva_pri_cleanup_adapter (a);
-      return (-1);
-    }
-  }
-
-  /*
-    Get Serial Number of this adapter
-  */
-  if (pri_get_serial_number (a)) {
-    dword serNo;
-    serNo  = a->resources.pci.bar[1] & 0xffff0000;
-    serNo |= ((dword)a->resources.pci.bus) << 8;
-    serNo += (a->resources.pci.func + a->controller + 1);
-    a->xdi_adapter.serialNo = serNo & ~0xFF000000;
-    DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld",
-              a->controller, a->xdi_adapter.serialNo))
-  }
-
-
-  /*
-    Initialize os objects
-  */
-  if (diva_os_initialize_spin_lock (&a->xdi_adapter.isr_spin_lock, "isr")) {
-    diva_pri_cleanup_adapter (a);
-    return (-1);
-  }
-  if (diva_os_initialize_spin_lock (&a->xdi_adapter.data_spin_lock, "data")) {
-    diva_pri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  strcpy (a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasprid");
-
-  if (diva_os_initialize_soft_isr (&a->xdi_adapter.req_soft_isr,
-                                    DIDpcRoutine,
-                                    &a->xdi_adapter)) {
-    diva_pri_cleanup_adapter (a);
-    return (-1);
-  }
-
-  /*
-    Do not initialize second DPC - only one thread will be created
-  */
-  a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
-
-  /*
-    Next step of card initialization:
-    set up all interface pointers
-  */
-  a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
-  a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
-
-  a->xdi_adapter.e_tbl =diva_os_malloc (0, a->xdi_adapter.e_max * sizeof(E_INFO)); 
-  if (!a->xdi_adapter.e_tbl) {
-    diva_pri_cleanup_adapter (a);
-    return (-1);
-  }
-  memset (a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
-
-  a->xdi_adapter.a.io = &a->xdi_adapter;
-  a->xdi_adapter.DIRequest = request;
-  a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter;
-  a->interface.cmd_proc	= diva_pri_cmd_card_proc;
-
-  if (pri_rev_2) {
-    prepare_pri2_functions (&a->xdi_adapter);
-  } else {
-    prepare_pri_functions  (&a->xdi_adapter);
-  }
-
-  /*
-    Set all memory areas
-  */
-  a->xdi_adapter.Address = a->resources.pci.addr[0];
-  a->xdi_adapter.sdram_bar = a->resources.pci.bar [0];
-  a->xdi_adapter.ram = a->resources.pci.addr[0];
-  a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET;
-
-  a->xdi_adapter.reset = a->resources.pci.addr[2];
-  a->xdi_adapter.reset += MP_RESET;
-
-  a->xdi_adapter.prom = (byte*)(unsigned long)a->resources.pci.bar [3];
-
-  a->xdi_adapter.cfg = a->resources.pci.addr[4];
-  a->xdi_adapter.cfg += MP_IRQ_RESET;
-
-  a->dsp_mask = diva_pri_detect_dsps (a);
-
-  /*
-    Allocate DMA map
-    */
-  if (pri_rev_2) {
-    diva_init_dma_map (a->resources.pci.hdev,
-                       (struct _diva_dma_map_entry**)&a->xdi_adapter.dma_map,
-                       32);
-  }
-
-  /*
-    Set IRQ handler
-  */
-  a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
-  sprintf (a->xdi_adapter.irq_info.irq_name,
-            "DIVA PRI %ld", 
-            (long)a->xdi_adapter.serialNo);
-
-  if (diva_os_register_irq (a, a->xdi_adapter.irq_info.irq_nr,
-                            a->xdi_adapter.irq_info.irq_name)) {
-    diva_pri_cleanup_adapter (a);
-    return (-1);
-  }
-  a->xdi_adapter.irq_info.registered = 1;
-
-  diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
-                                      a->resources.pci.irq,
-                                      a->xdi_adapter.serialNo);
-
-  return (0);
-}
-
-static int
-diva_pri_cleanup_adapter (diva_os_xdi_adapter_t* a)
+int diva_pri_init_card(diva_os_xdi_adapter_t * a)
 {
-  int bar = 0;
+	int bar = 0;
+	int pri_rev_2;
+	unsigned long bar_length[5] = {
+		MP_MEMORY_SIZE,
+		0x1000,
+		0x2000,
+		0x8000,
+		0x1000
+	};
+
+	pri_rev_2 = pri_is_rev_2_card(a->CardOrdinal);
+
+	if (pri_rev_2) {
+		bar_length[0] = MP2_MEMORY_SIZE;
+	}
+	/*
+	   Set properties
+	 */
+	a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
+	DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
+
+	/*
+	   First initialization step: get and check hardware resoures.
+	   Do not map resources and do not acecess card at this step
+	 */
+	for (bar = 0; bar < 5; bar++) {
+		a->resources.pci.bar[bar] =
+		    divasa_get_pci_bar(a->resources.pci.bus,
+				       a->resources.pci.func, bar,
+				       a->resources.pci.hdev);
+		if (!a->resources.pci.bar[bar]
+		    || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
+			DBG_ERR(("A: invalid bar[%d]=%08x", bar,
+				 a->resources.pci.bar[bar]))
+			return (-1);
+		}
+	}
+	a->resources.pci.irq =
+	    (byte) divasa_get_pci_irq(a->resources.pci.bus,
+				      a->resources.pci.func,
+				      a->resources.pci.hdev);
+	if (!a->resources.pci.irq) {
+		DBG_ERR(("A: invalid irq"));
+		return (-1);
+	}
+
+	/*
+	   Map all BAR's
+	 */
+	for (bar = 0; bar < 5; bar++) {
+		a->resources.pci.addr[bar] =
+		    divasa_remap_pci_bar(a->resources.pci.bar[bar],
+					 bar_length[bar]);
+		if (!a->resources.pci.addr[bar]) {
+			DBG_ERR(("A: A(%d), can't map bar[%d]",
+				 a->controller, bar))
+			diva_pri_cleanup_adapter(a);
+			return (-1);
+		}
+	}
+
+	/*
+	   Get Serial Number of this adapter
+	 */
+	if (pri_get_serial_number(a)) {
+		dword serNo;
+		serNo = a->resources.pci.bar[1] & 0xffff0000;
+		serNo |= ((dword) a->resources.pci.bus) << 8;
+		serNo += (a->resources.pci.func + a->controller + 1);
+		a->xdi_adapter.serialNo = serNo & ~0xFF000000;
+		DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld",
+			 a->controller, a->xdi_adapter.serialNo))
+	}
+
+
+	/*
+	   Initialize os objects
+	 */
+	if (diva_os_initialize_spin_lock(&a->xdi_adapter.isr_spin_lock, "isr")) {
+		diva_pri_cleanup_adapter(a);
+		return (-1);
+	}
+	if (diva_os_initialize_spin_lock
+	    (&a->xdi_adapter.data_spin_lock, "data")) {
+		diva_pri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasprid");
+
+	if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
+					DIDpcRoutine, &a->xdi_adapter)) {
+		diva_pri_cleanup_adapter(a);
+		return (-1);
+	}
+
+	/*
+	   Do not initialize second DPC - only one thread will be created
+	 */
+	a->xdi_adapter.isr_soft_isr.object =
+	    a->xdi_adapter.req_soft_isr.object;
+
+	/*
+	   Next step of card initialization:
+	   set up all interface pointers
+	 */
+	a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
+	a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
+
+	a->xdi_adapter.e_tbl =
+	    diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
+	if (!a->xdi_adapter.e_tbl) {
+		diva_pri_cleanup_adapter(a);
+		return (-1);
+	}
+	memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
+
+	a->xdi_adapter.a.io = &a->xdi_adapter;
+	a->xdi_adapter.DIRequest = request;
+	a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter;
+	a->interface.cmd_proc = diva_pri_cmd_card_proc;
+
+	if (pri_rev_2) {
+		prepare_pri2_functions(&a->xdi_adapter);
+	} else {
+		prepare_pri_functions(&a->xdi_adapter);
+	}
+
+	/*
+	   Set all memory areas
+	 */
+	a->xdi_adapter.Address = a->resources.pci.addr[0];
+	a->xdi_adapter.sdram_bar = a->resources.pci.bar[0];
+	a->xdi_adapter.ram = a->resources.pci.addr[0];
+	a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET;
+
+	a->xdi_adapter.reset = a->resources.pci.addr[2];
+	a->xdi_adapter.reset += MP_RESET;
+
+	a->xdi_adapter.prom =
+	    (byte *) (unsigned long) a->resources.pci.bar[3];
+
+	a->xdi_adapter.cfg = a->resources.pci.addr[4];
+	a->xdi_adapter.cfg += MP_IRQ_RESET;
+
+	a->dsp_mask = diva_pri_detect_dsps(a);
+
+	/*
+	   Allocate DMA map
+	 */
+	if (pri_rev_2) {
+		diva_init_dma_map(a->resources.pci.hdev,
+				  (struct _diva_dma_map_entry **) &a->xdi_adapter.dma_map, 32);
+	}
+
+	/*
+	   Set IRQ handler
+	 */
+	a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
+	sprintf(a->xdi_adapter.irq_info.irq_name,
+		"DIVA PRI %ld", (long) a->xdi_adapter.serialNo);
+
+	if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
+				 a->xdi_adapter.irq_info.irq_name)) {
+		diva_pri_cleanup_adapter(a);
+		return (-1);
+	}
+	a->xdi_adapter.irq_info.registered = 1;
+
+	diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
+		      a->resources.pci.irq, a->xdi_adapter.serialNo);
+
+	return (0);
+}
+
+static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a)
+{
+	int bar = 0;
+
+	/*
+	   Stop Adapter if adapter is running
+	 */
+	if (a->xdi_adapter.Initialized) {
+		diva_pri_stop_adapter(a);
+	}
+
+	/*
+	   Remove ISR Handler
+	 */
+	if (a->xdi_adapter.irq_info.registered) {
+		diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
+	}
+	a->xdi_adapter.irq_info.registered = 0;
+
+	/*
+	   Step 1: unmap all BAR's, if any was mapped
+	 */
+	for (bar = 0; bar < 5; bar++) {
+		if (a->resources.pci.bar[bar]
+		    && a->resources.pci.addr[bar]) {
+			divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
+			a->resources.pci.bar[bar] = 0;
+			a->resources.pci.addr[bar] = 0;
+		}
+	}
+
+	/*
+	   Free OS objects
+	 */
+	diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
+	diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
+
+	diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
+	a->xdi_adapter.isr_soft_isr.object = 0;
+
+	diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
+	diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
+
+	/*
+	   Free memory accupied by XDI adapter
+	 */
+	if (a->xdi_adapter.e_tbl) {
+		diva_os_free(0, a->xdi_adapter.e_tbl);
+		a->xdi_adapter.e_tbl = 0;
+	}
+	a->xdi_adapter.Channels = 0;
+	a->xdi_adapter.e_max = 0;
+
+
+	/*
+	   Free adapter DMA map
+	 */
+	diva_free_dma_map(a->resources.pci.hdev,
+			  (struct _diva_dma_map_entry *) a->xdi_adapter.
+			  dma_map);
+	a->xdi_adapter.dma_map = 0;
+
+
+	/*
+	   Detach this adapter from debug driver
+	 */
 
-  /*
-    Stop Adapter if adapter is running
-  */
-  if (a->xdi_adapter.Initialized) {
-    diva_pri_stop_adapter (a);
-  }
-
-  /*
-    Remove ISR Handler
-  */
-  if (a->xdi_adapter.irq_info.registered) {
-    diva_os_remove_irq (a, a->xdi_adapter.irq_info.irq_nr);
-  }
-  a->xdi_adapter.irq_info.registered = 0;
-
-  /*
-    Step 1: unmap all BAR's, if any was mapped
-  */
-  for (bar = 0; bar < 5; bar++) {
-    if (a->resources.pci.bar[bar] && a->resources.pci.addr[bar]) {
-      divasa_unmap_pci_bar (a->resources.pci.addr[bar]);
-      a->resources.pci.bar[bar]  = 0;
-      a->resources.pci.addr[bar] = 0;
-    }
-  }
-
-  /*
-    Free OS objects
-  */
-  diva_os_cancel_soft_isr (&a->xdi_adapter.isr_soft_isr);
-  diva_os_cancel_soft_isr (&a->xdi_adapter.req_soft_isr);
-
-  diva_os_remove_soft_isr (&a->xdi_adapter.req_soft_isr);
-  a->xdi_adapter.isr_soft_isr.object = 0;
-
-  diva_os_destroy_spin_lock (&a->xdi_adapter.isr_spin_lock, "rm");
-  diva_os_destroy_spin_lock (&a->xdi_adapter.data_spin_lock, "rm");
-
-  /*
-    Free memory accupied by XDI adapter
-  */
-  if (a->xdi_adapter.e_tbl) {
-    diva_os_free (0, a->xdi_adapter.e_tbl);
-    a->xdi_adapter.e_tbl = 0;
-  }
-  a->xdi_adapter.Channels = 0;
-  a->xdi_adapter.e_max = 0;
-
-
-  /*
-    Free adapter DMA map
-    */
-  diva_free_dma_map (a->resources.pci.hdev,
-                     (struct _diva_dma_map_entry*)a->xdi_adapter.dma_map);
-  a->xdi_adapter.dma_map = 0;
-
-
-  /*
-    Detach this adapter from debug driver
-  */
-
-  return (0);
+	return (0);
 }
 
 /*
 **  Activate On Board Boot Loader
 */
-static int
-diva_pri_reset_adapter (PISDN_ADAPTER IoAdapter)
+static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter)
 {
-  dword  i;
-  struct mp_load *boot = (struct mp_load *)IoAdapter->Address;
+	dword i;
+	struct mp_load *boot = (struct mp_load *) IoAdapter->Address;
 
-  if (!IoAdapter->Address || !IoAdapter->reset) {
-    return (-1);
-  }
-  if (IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first",
-                IoAdapter->ANum))
-    return (-1);
-  }
+	if (!IoAdapter->Address || !IoAdapter->reset) {
+		return (-1);
+	}
+	if (IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first",
+			 IoAdapter->ANum))
+		return (-1);
+	}
 
 	WRITE_DWORD(&boot->err, 0);
-  IoAdapter->rstFnc (IoAdapter) ;
-  diva_os_wait (10) ;
-  i = READ_DWORD(&boot->live);
-  diva_os_wait (10) ;
-  if (i == READ_DWORD(&boot->live)) {
-    DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!",
-              IoAdapter->ANum, IoAdapter->serialNo))
-    return (-1);
-  }
-  if (READ_DWORD(&boot->err)) {
-    DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx",
-              IoAdapter->ANum, IoAdapter->serialNo, READ_DWORD(&boot->err)))
-    return (-1);
-  }
-
-  /*
-    Forget all outstanding entities
-  */
-  IoAdapter->e_count =  0;
-  if (IoAdapter->e_tbl) {
-    memset (IoAdapter->e_tbl, 0x00, IoAdapter->e_max * sizeof(E_INFO));
-  }
-  IoAdapter->head = 0;
-  IoAdapter->tail = 0;
-  IoAdapter->assign = 0;
-  IoAdapter->trapped = 0;
-
-  memset (&IoAdapter->a.IdTable[0],              0x00, sizeof(IoAdapter->a.IdTable));
-  memset (&IoAdapter->a.IdTypeTable[0],          0x00, sizeof(IoAdapter->a.IdTypeTable));
-  memset (&IoAdapter->a.FlowControlIdTable[0],   0x00, sizeof(IoAdapter->a.FlowControlIdTable));
-  memset (&IoAdapter->a.FlowControlSkipTable[0], 0x00, sizeof(IoAdapter->a.FlowControlSkipTable));
-  memset (&IoAdapter->a.misc_flags_table[0],     0x00, sizeof(IoAdapter->a.misc_flags_table));
-  memset (&IoAdapter->a.rx_stream[0],            0x00, sizeof(IoAdapter->a.rx_stream));
-  memset (&IoAdapter->a.tx_stream[0],            0x00, sizeof(IoAdapter->a.tx_stream));
-  memset (&IoAdapter->a.tx_pos[0],               0x00, sizeof(IoAdapter->a.tx_pos));
-  memset (&IoAdapter->a.rx_pos[0],               0x00, sizeof(IoAdapter->a.rx_pos));
+	IoAdapter->rstFnc(IoAdapter);
+	diva_os_wait(10);
+	i = READ_DWORD(&boot->live);
+	diva_os_wait(10);
+	if (i == READ_DWORD(&boot->live)) {
+		DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!",
+			 IoAdapter->ANum, IoAdapter->serialNo))
+		return (-1);
+	}
+	if (READ_DWORD(&boot->err)) {
+		DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx",
+			 IoAdapter->ANum, IoAdapter->serialNo,
+			 READ_DWORD(&boot->err)))
+		return (-1);
+	}
+
+	/*
+	   Forget all outstanding entities
+	 */
+	IoAdapter->e_count = 0;
+	if (IoAdapter->e_tbl) {
+		memset(IoAdapter->e_tbl, 0x00,
+		       IoAdapter->e_max * sizeof(E_INFO));
+	}
+	IoAdapter->head = 0;
+	IoAdapter->tail = 0;
+	IoAdapter->assign = 0;
+	IoAdapter->trapped = 0;
+
+	memset(&IoAdapter->a.IdTable[0], 0x00,
+	       sizeof(IoAdapter->a.IdTable));
+	memset(&IoAdapter->a.IdTypeTable[0], 0x00,
+	       sizeof(IoAdapter->a.IdTypeTable));
+	memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
+	       sizeof(IoAdapter->a.FlowControlIdTable));
+	memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
+	       sizeof(IoAdapter->a.FlowControlSkipTable));
+	memset(&IoAdapter->a.misc_flags_table[0], 0x00,
+	       sizeof(IoAdapter->a.misc_flags_table));
+	memset(&IoAdapter->a.rx_stream[0], 0x00,
+	       sizeof(IoAdapter->a.rx_stream));
+	memset(&IoAdapter->a.tx_stream[0], 0x00,
+	       sizeof(IoAdapter->a.tx_stream));
+	memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
+	memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
 
-  return (0);
+	return (0);
 }
 
 static int
-diva_pri_write_sdram_block (PISDN_ADAPTER IoAdapter,
-                            dword address,
-                            const byte* data,
-                            dword length,
-                            dword limit)
-{
-  byte* mem = IoAdapter->Address;
-
-  if (((address + length) >= limit) || !mem) {
-    DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
-               IoAdapter->ANum, address+length))
-    return (-1);
-  }
-  mem += address;
-
-  while (length--) {
-    *mem++ = *data++;
-  }
+diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter,
+			   dword address,
+			   const byte * data, dword length, dword limit)
+{
+	byte *mem = IoAdapter->Address;
+
+	if (((address + length) >= limit) || !mem) {
+		DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
+			 IoAdapter->ANum, address + length))
+		return (-1);
+	}
+	mem += address;
+
+	while (length--) {
+		*mem++ = *data++;
+	}
 
-  return (0);
+	return (0);
 }
 
 static int
-diva_pri_start_adapter (PISDN_ADAPTER IoAdapter,
-                        dword start_address,
-                        dword features)
-{
-  dword i;
-  int started = 0;
-  struct mp_load *boot = (struct mp_load *)IoAdapter->Address;
-  ADAPTER *a = &IoAdapter->a ;
-
-  if (IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running",
-              IoAdapter->ANum))
-    return (-1);
-  }
-  if (!boot) {
-    DBG_ERR(("A: PRI %ld can't start, adapter not mapped",
-              IoAdapter->serialNo))
-    return (-1);
-  }
-
-  sprintf (IoAdapter->Name, "A(%d)", (int)IoAdapter->ANum);
-  DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum, start_address))
-
-  WRITE_DWORD(&boot->addr, start_address);
-  WRITE_DWORD(&boot->cmd, 3);
-
-  for (i = 0; i < 300; ++i) {
-    diva_os_wait (10);
-    if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) {
-      DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds",
-                IoAdapter->ANum, (i / 100), (i % 100)))
-      started = 1;
-      break;
-    }
-  }
-
-  if (!started) {
-    dword TrapId = READ_DWORD(&IoAdapter->Address[0x80]);
-    dword debug  = READ_DWORD(&IoAdapter->Address[0x1c]);
-    DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx",
-              IoAdapter->ANum, READ_DWORD(&boot->signature), TrapId, debug))
-    if (IoAdapter->trapFnc) {
-      (*(IoAdapter->trapFnc))(IoAdapter);
-    }
-    IoAdapter->stop(IoAdapter);
-    return (-1);
-  }
-
-  IoAdapter->Initialized = TRUE;
-
-  /*
-    Check Interrupt
-  */
-  IoAdapter->IrqCount = 0;
-  WRITE_DWORD(((dword volatile *)IoAdapter->cfg), (dword)~0x03E00000) ;
-  a->ReadyInt = 1 ;
-  a->ram_out (a, &PR_RAM->ReadyInt, 1) ;
-
-  for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait (10));
-
-  if (!IoAdapter->IrqCount) {
-    DBG_ERR(("A: A(%d) interrupt test failed", IoAdapter->ANum))
-    IoAdapter->Initialized = FALSE;
-    IoAdapter->stop(IoAdapter);
-    return (-1);
-  }
-
-  IoAdapter->Properties.Features = (word)features;
-
-  diva_xdi_display_adapter_features (IoAdapter->ANum);
-
-  DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum))
-  /*
-    Register with DIDD
-  */
-  diva_xdi_didd_register_adapter (IoAdapter->ANum);
-
-  return (0);
-}
-
-static void
-diva_pri_clear_interrupts (diva_os_xdi_adapter_t* a)
-{
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-
-  /*
-    clear any pending interrupt
-  */
-  IoAdapter->disIrq (IoAdapter) ;
-
-  IoAdapter->tst_irq (&IoAdapter->a) ;
-  IoAdapter->clr_irq (&IoAdapter->a) ;
-  IoAdapter->tst_irq (&IoAdapter->a) ;
-
-  /*
-    kill pending dpcs
-  */
-  diva_os_cancel_soft_isr (&IoAdapter->req_soft_isr);
-  diva_os_cancel_soft_isr (&IoAdapter->isr_soft_isr);
+diva_pri_start_adapter(PISDN_ADAPTER IoAdapter,
+		       dword start_address, dword features)
+{
+	dword i;
+	int started = 0;
+	struct mp_load *boot = (struct mp_load *) IoAdapter->Address;
+	ADAPTER *a = &IoAdapter->a;
+
+	if (IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running",
+			 IoAdapter->ANum))
+		return (-1);
+	}
+	if (!boot) {
+		DBG_ERR(("A: PRI %ld can't start, adapter not mapped",
+			 IoAdapter->serialNo))
+		return (-1);
+	}
+
+	sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
+	DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum,
+		 start_address))
+
+	WRITE_DWORD(&boot->addr, start_address);
+	WRITE_DWORD(&boot->cmd, 3);
+
+	for (i = 0; i < 300; ++i) {
+		diva_os_wait(10);
+		if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) {
+			DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds",
+				 IoAdapter->ANum, (i / 100), (i % 100)))
+			started = 1;
+			break;
+		}
+	}
+
+	if (!started) {
+		dword TrapId = READ_DWORD(&IoAdapter->Address[0x80]);
+		dword debug = READ_DWORD(&IoAdapter->Address[0x1c]);
+		DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx",
+			 IoAdapter->ANum, READ_DWORD(&boot->signature),
+			 TrapId, debug))
+		if (IoAdapter->trapFnc) {
+			(*(IoAdapter->trapFnc)) (IoAdapter);
+		}
+		IoAdapter->stop(IoAdapter);
+		return (-1);
+	}
+
+	IoAdapter->Initialized = TRUE;
+
+	/*
+	   Check Interrupt
+	 */
+	IoAdapter->IrqCount = 0;
+	WRITE_DWORD(((dword volatile *) IoAdapter->cfg),
+		    (dword) ~ 0x03E00000);
+	a->ReadyInt = 1;
+	a->ram_out(a, &PR_RAM->ReadyInt, 1);
+
+	for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
+
+	if (!IoAdapter->IrqCount) {
+		DBG_ERR(("A: A(%d) interrupt test failed",
+			 IoAdapter->ANum))
+		IoAdapter->Initialized = FALSE;
+		IoAdapter->stop(IoAdapter);
+		return (-1);
+	}
+
+	IoAdapter->Properties.Features = (word) features;
+
+	diva_xdi_display_adapter_features(IoAdapter->ANum);
+
+	DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum))
+	/*
+	   Register with DIDD
+	 */
+	diva_xdi_didd_register_adapter(IoAdapter->ANum);
+
+	return (0);
+}
+
+static void diva_pri_clear_interrupts(diva_os_xdi_adapter_t * a)
+{
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
+
+	/*
+	   clear any pending interrupt
+	 */
+	IoAdapter->disIrq(IoAdapter);
+
+	IoAdapter->tst_irq(&IoAdapter->a);
+	IoAdapter->clr_irq(&IoAdapter->a);
+	IoAdapter->tst_irq(&IoAdapter->a);
+
+	/*
+	   kill pending dpcs
+	 */
+	diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
+	diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
 }
 
 /*
 **  Stop Adapter, but do not unmap/unregister - adapter
 **  will be restarted later
 */
-static int
-diva_pri_stop_adapter (diva_os_xdi_adapter_t* a)
+static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a)
 {
-  PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
-  int i = 100;
+	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
+	int i = 100;
 
-  if (!IoAdapter->ram) {
-    return (-1);
-  }
-  if (!IoAdapter->Initialized) {
-    DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
-              IoAdapter->ANum))
-    return (-1); /* nothing to stop */
-  }
-  IoAdapter->Initialized = 0;
-
-  /*
-    Disconnect Adapter from DIDD
-  */
-  diva_xdi_didd_remove_adapter (IoAdapter->ANum);
-
-  /*
-    Stop interrupts
-  */
-  a->clear_interrupts_proc = diva_pri_clear_interrupts;
-  IoAdapter->a.ReadyInt = 1;
-  IoAdapter->a.ram_inc (&IoAdapter->a, &PR_RAM->ReadyInt) ;
-  do {
-    diva_os_sleep (10);
-  } while (i-- && a->clear_interrupts_proc);
-  if (a->clear_interrupts_proc) {
-    diva_pri_clear_interrupts (a);
-    a->clear_interrupts_proc = 0;
-    DBG_ERR(("A: A(%d) no final interrupt from PRI adapter", IoAdapter->ANum))
-  }
-  IoAdapter->a.ReadyInt = 0;
-
-  /*
-    Stop and reset adapter
-  */
-  IoAdapter->stop (IoAdapter) ;
+	if (!IoAdapter->ram) {
+		return (-1);
+	}
+	if (!IoAdapter->Initialized) {
+		DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
+			 IoAdapter->ANum))
+		return (-1);	/* nothing to stop */
+	}
+	IoAdapter->Initialized = 0;
+
+	/*
+	   Disconnect Adapter from DIDD
+	 */
+	diva_xdi_didd_remove_adapter(IoAdapter->ANum);
+
+	/*
+	   Stop interrupts
+	 */
+	a->clear_interrupts_proc = diva_pri_clear_interrupts;
+	IoAdapter->a.ReadyInt = 1;
+	IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
+	do {
+		diva_os_sleep(10);
+	} while (i-- && a->clear_interrupts_proc);
+
+	if (a->clear_interrupts_proc) {
+		diva_pri_clear_interrupts(a);
+		a->clear_interrupts_proc = 0;
+		DBG_ERR(("A: A(%d) no final interrupt from PRI adapter",
+			 IoAdapter->ANum))
+	}
+	IoAdapter->a.ReadyInt = 0;
+
+	/*
+	   Stop and reset adapter
+	 */
+	IoAdapter->stop(IoAdapter);
 
-  return (0);
+	return (0);
 }
 
 /*
@@ -549,264 +560,301 @@
 **  return 0 on success
 */
 static int
-diva_pri_cmd_card_proc (struct _diva_os_xdi_adapter* a,
-                        diva_xdi_um_cfg_cmd_t* cmd,
-                        int length)
-{
-  int ret = -1;
-
-  if (cmd->adapter != a->controller) {
-    DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
-              cmd->adapter, a->controller))
-    return (-1);
-  }
-
-  switch (cmd->command) {
-    case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->CardOrdinal;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        *(dword*)a->xdi_mbox.data = (dword)a->xdi_adapter.serialNo;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
-      a->xdi_mbox.data_length = sizeof(dword)*9;
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        int i;
-        dword* data = (dword*)a->xdi_mbox.data;
-
-        for (i = 0; i < 8; i++) {
-          *data++ = a->resources.pci.bar[i];
-        }
-        *data++ = (dword)a->resources.pci.irq;
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_RESET_ADAPTER:
-      ret = diva_pri_reset_adapter (&a->xdi_adapter);
-      break;
-
-    case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
-      ret = diva_pri_write_sdram_block (&a->xdi_adapter,
-                                        cmd->command_data.write_sdram.offset,
-                                        (byte*)&cmd[1],
-                                        cmd->command_data.write_sdram.length,
-                                        pri_is_rev_2_card (a->CardOrdinal) ? 
-                                        MP2_MEMORY_SIZE : MP_MEMORY_SIZE);
-      break;
-
-    case DIVA_XDI_UM_CMD_STOP_ADAPTER:
-      ret = diva_pri_stop_adapter (a);
-      break;
-
-    case DIVA_XDI_UM_CMD_START_ADAPTER:
-      ret = diva_pri_start_adapter (&a->xdi_adapter,
-                                    cmd->command_data.start.offset,
-                                    cmd->command_data.start.features);
-      break;
-
-    case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
-      a->xdi_adapter.features = cmd->command_data.features.features;
-      a->xdi_adapter.a.protocol_capabilities = a->xdi_adapter.features;
-      DBG_TRC(("Set raw protocol features (%08x)", a->xdi_adapter.features))
-      ret = 0;
-      break;
-
-    case DIVA_XDI_UM_CMD_GET_CARD_STATE:
-      a->xdi_mbox.data_length = sizeof(dword);
-      a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-      if (a->xdi_mbox.data) {
-        dword* data = (dword*)a->xdi_mbox.data;
-        if (!a->xdi_adapter.ram || !a->xdi_adapter.reset ||
-            !a->xdi_adapter.cfg) {
-          *data = 3;
-        } else if (a->xdi_adapter.trapped) {
-          *data = 2;
-        } else if (a->xdi_adapter.Initialized) {
-          *data = 1;
-        } else {
-          *data = 0;
-        }
-        a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-        ret = 0;
-      }
-      break;
-
-    case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
-      ret = diva_card_read_xlog (a);
-      break;
-
-    case DIVA_XDI_UM_CMD_READ_SDRAM:
-      if (a->xdi_adapter.Address) {
-        if ((a->xdi_mbox.data_length = cmd->command_data.read_sdram.length)) {
-          if ((a->xdi_mbox.data_length+cmd->command_data.read_sdram.offset) < a->xdi_adapter.MemorySize) { 
-            a->xdi_mbox.data = diva_os_malloc (0, a->xdi_mbox.data_length);
-            if (a->xdi_mbox.data) {
-              byte* src = a->xdi_adapter.Address;
-              byte* dst = a->xdi_mbox.data;
-              dword len = a->xdi_mbox.data_length;
-
-              src += cmd->command_data.read_sdram.offset;
-
-              while (len--) {
-                *dst++ = *src++;
-              }
-              a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
-              ret = 0;
-            }
-          }
-        }
-      }
-      break;
-
-    default:
-      DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller, cmd->command))
-  }
+diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
+		       diva_xdi_um_cfg_cmd_t * cmd, int length)
+{
+	int ret = -1;
+
+	if (cmd->adapter != a->controller) {
+		DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
+			 cmd->adapter, a->controller))
+		return (-1);
+	}
+
+	switch (cmd->command) {
+	case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->CardOrdinal;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			*(dword *) a->xdi_mbox.data =
+			    (dword) a->xdi_adapter.serialNo;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
+		a->xdi_mbox.data_length = sizeof(dword) * 9;
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			int i;
+			dword *data = (dword *) a->xdi_mbox.data;
+
+			for (i = 0; i < 8; i++) {
+				*data++ = a->resources.pci.bar[i];
+			}
+			*data++ = (dword) a->resources.pci.irq;
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_RESET_ADAPTER:
+		ret = diva_pri_reset_adapter(&a->xdi_adapter);
+		break;
+
+	case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
+		ret = diva_pri_write_sdram_block(&a->xdi_adapter,
+						 cmd->command_data.
+						 write_sdram.offset,
+						 (byte *) & cmd[1],
+						 cmd->command_data.
+						 write_sdram.length,
+						 pri_is_rev_2_card(a->
+								   CardOrdinal)
+						 ? MP2_MEMORY_SIZE :
+						 MP_MEMORY_SIZE);
+		break;
+
+	case DIVA_XDI_UM_CMD_STOP_ADAPTER:
+		ret = diva_pri_stop_adapter(a);
+		break;
+
+	case DIVA_XDI_UM_CMD_START_ADAPTER:
+		ret = diva_pri_start_adapter(&a->xdi_adapter,
+					     cmd->command_data.start.
+					     offset,
+					     cmd->command_data.start.
+					     features);
+		break;
+
+	case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
+		a->xdi_adapter.features =
+		    cmd->command_data.features.features;
+		a->xdi_adapter.a.protocol_capabilities =
+		    a->xdi_adapter.features;
+		DBG_TRC(("Set raw protocol features (%08x)",
+			 a->xdi_adapter.features))
+		ret = 0;
+		break;
+
+	case DIVA_XDI_UM_CMD_GET_CARD_STATE:
+		a->xdi_mbox.data_length = sizeof(dword);
+		a->xdi_mbox.data =
+		    diva_os_malloc(0, a->xdi_mbox.data_length);
+		if (a->xdi_mbox.data) {
+			dword *data = (dword *) a->xdi_mbox.data;
+			if (!a->xdi_adapter.ram || !a->xdi_adapter.reset ||
+			    !a->xdi_adapter.cfg) {
+				*data = 3;
+			} else if (a->xdi_adapter.trapped) {
+				*data = 2;
+			} else if (a->xdi_adapter.Initialized) {
+				*data = 1;
+			} else {
+				*data = 0;
+			}
+			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
+			ret = 0;
+		}
+		break;
+
+	case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
+		ret = diva_card_read_xlog(a);
+		break;
+
+	case DIVA_XDI_UM_CMD_READ_SDRAM:
+		if (a->xdi_adapter.Address) {
+			if (
+			    (a->xdi_mbox.data_length =
+			     cmd->command_data.read_sdram.length)) {
+				if (
+				    (a->xdi_mbox.data_length +
+				     cmd->command_data.read_sdram.offset) <
+				    a->xdi_adapter.MemorySize) {
+					a->xdi_mbox.data =
+					    diva_os_malloc(0,
+							   a->xdi_mbox.
+							   data_length);
+					if (a->xdi_mbox.data) {
+						byte *src =
+						    a->xdi_adapter.Address;
+						byte *dst =
+						    a->xdi_mbox.data;
+						dword len =
+						    a->xdi_mbox.
+						    data_length;
+
+						src +=
+						    cmd->command_data.
+						    read_sdram.offset;
+
+						while (len--) {
+							*dst++ = *src++;
+						}
+						a->xdi_mbox.status =
+						    DIVA_XDI_MBOX_BUSY;
+						ret = 0;
+					}
+				}
+			}
+		}
+		break;
+
+	default:
+		DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
+			 cmd->command))
+	}
 
-  return (ret);
+	return (ret);
 }
 
 /*
 **  Get Serial Number
 */
-static int
-pri_get_serial_number (diva_os_xdi_adapter_t* a)
+static int pri_get_serial_number(diva_os_xdi_adapter_t * a)
 {
-  byte data[64];
-  int i;
-  dword len = sizeof(data);
-  volatile byte* config = (byte*)a->resources.pci.addr[4];
-  volatile byte* flash  = (byte*)a->resources.pci.addr[3];
+	byte data[64];
+	int i;
+	dword len = sizeof(data);
+	volatile byte *config = (byte *) a->resources.pci.addr[4];
+	volatile byte *flash = (byte *) a->resources.pci.addr[3];
 
 /*
  *  First set some GT6401x config registers before accessing the BOOT-ROM
  */
-  if ( !(config[0xc3c] & 0x08) )
-  {
-    config[0xc3c] |= 0x08 ;  /* Base Address enable register */
-  }
-  config[LOW_BOOTCS_DREG] = 0x00 ;
-  config[HI_BOOTCS_DREG]  = 0xFF ;
+	if (!(config[0xc3c] & 0x08)) {
+		config[0xc3c] |= 0x08;	/* Base Address enable register */
+	}
+	config[LOW_BOOTCS_DREG] = 0x00;
+	config[HI_BOOTCS_DREG] = 0xFF;
 /*
  *  Read only the last 64 bytes of manufacturing data
  */
-  memset (data, '\0', len) ;
-  for (i = 0; i < len; i++) { data[i] = flash[0x8000 - len + i]; }
-
-  config[LOW_BOOTCS_DREG] = 0xFC ;	/* Disable FLASH EPROM access */
-  config[HI_BOOTCS_DREG]  = 0xFF ;
+	memset(data, '\0', len);
+	for (i = 0; i < len; i++) {
+		data[i] = flash[0x8000 - len + i];
+	}
+
+	config[LOW_BOOTCS_DREG] = 0xFC;	/* Disable FLASH EPROM access */
+	config[HI_BOOTCS_DREG] = 0xFF;
+
+	if (memcmp(&data[48], "DIVAserverPR", 12)) {
+#if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND)	/* { */
+		word cmd = 0, cmd_org;
+		void *addr;
+		dword addr1, addr3, addr4;
+		byte Bus, Slot;
+		void *hdev;
+		addr4 = a->resources.pci.bar[4];
+		addr3 = a->resources.pci.bar[3];	/* flash  */
+		addr1 = a->resources.pci.bar[1];	/* unused */
+
+		DBG_ERR(("A: apply Compaq BIOS workaround"))
+		DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+			     data[0], data[1], data[2], data[3],
+			     data[4], data[5], data[6], data[7]))
+
+		Bus = a->resources.pci.bus;
+		Slot = a->resources.pci.func;
+		hdev = a->resources.pci.hdev;
+		PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
+		PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
+
+		PCIwrite(Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev);
+		PCIwrite(Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev);
+
+		PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
+
+		addr = a->resources.pci.addr[1];
+		a->resources.pci.addr[1] = a->resources.pci.addr[4];
+		a->resources.pci.addr[4] = addr;
+
+		addr1 = a->resources.pci.bar[1];
+		a->resources.pci.bar[1] = a->resources.pci.bar[4];
+		a->resources.pci.bar[4] = addr1;
+
+		/*
+		   Try to read Flash again
+		 */
+		config = (byte *) a->resources.pci.addr[4];
+		flash = (byte *) a->resources.pci.addr[3];
+		len = sizeof(data);
+
+		if (!(config[0xc3c] & 0x08)) {
+			config[0xc3c] |= 0x08;	/* Base Address enable register */
+		}
+		config[LOW_BOOTCS_DREG] = 0x00;
+		config[HI_BOOTCS_DREG] = 0xFF;
+
+		memset(data, '\0', len);
+		for (i = 0; i < len; i++) {
+			data[i] = flash[0x8000 - len + i];
+		}
+		config[LOW_BOOTCS_DREG] = 0xFC;
+		config[HI_BOOTCS_DREG] = 0xFF;
+
+		if (memcmp(&data[48], "DIVAserverPR", 12)) {
+			DBG_ERR(("A: failed to read serial number"))
+			DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+				     data[0], data[1], data[2], data[3],
+				     data[4], data[5], data[6], data[7]))
+			return (-1);
+		}
+#else				/* } { */
+		DBG_ERR(("A: failed to read DIVA signature word"))
+		DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+			     data[0], data[1], data[2], data[3],
+			     data[4], data[5], data[6], data[7]))
+		DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46],
+			     data[45], data[44]))
+#endif				/* } */
+	}
+
+	a->xdi_adapter.serialNo =
+	    (data[47] << 24) | (data[46] << 16) | (data[45] << 8) |
+	    data[44];
+	if (!a->xdi_adapter.serialNo
+	    || (a->xdi_adapter.serialNo == 0xffffffff)) {
+		a->xdi_adapter.serialNo = 0;
+		DBG_ERR(("A: failed to read serial number"))
+		return (-1);
+	}
+
+	DBG_LOG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
+	DBG_TRC(("Board Revision      : %d.%02d", (int) data[41],
+		     (int) data[40]))
+	DBG_TRC(("PLD revision        : %d.%02d", (int) data[33],
+		     (int) data[32]))
+	DBG_TRC(("Boot loader version : %d.%02d", (int) data[37],
+		     (int) data[36]))
+
+	DBG_TRC(("Manufacturing Date  : %d/%02d/%02d  (yyyy/mm/dd)",
+		     (int) ((data[28] > 90) ? 1900 : 2000) +
+		     (int) data[28], (int) data[29], (int) data[30]))
 
-  if (memcmp (&data[48], "DIVAserverPR", 12)) {
-#if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND) /* { */
-    word cmd = 0, cmd_org;
-    void* addr;
-    dword addr1, addr3, addr4;
-    byte Bus, Slot;
-    void* hdev;
-    addr4  = a->resources.pci.bar[4];
-    addr3  = a->resources.pci.bar[3]; /* flash  */
-    addr1  = a->resources.pci.bar[1]; /* unused */
-
-    DBG_ERR(("A: apply Compaq BIOS workaround"))
-    DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-              data[0], data[1], data[2], data[3],
-              data[4], data[5], data[6], data[7]))
-
-    Bus = a->resources.pci.bus;
-    Slot = a->resources.pci.func;
-    hdev = a->resources.pci.hdev;
-    PCIread (Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
-    PCIwrite (Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
-
-    PCIwrite (Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev);
-    PCIwrite (Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev) ;
-
-    PCIwrite (Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
-
-    addr = a->resources.pci.addr[1];
-    a->resources.pci.addr[1] = a->resources.pci.addr[4];
-    a->resources.pci.addr[4] = addr;
-
-    addr1 = a->resources.pci.bar[1];
-    a->resources.pci.bar[1] = a->resources.pci.bar[4];
-    a->resources.pci.bar[4] = addr1;
-
-    /*
-      Try to read Flash again
-    */
-    config = (byte*)a->resources.pci.addr[4];
-    flash  = (byte*)a->resources.pci.addr[3];
-    len = sizeof(data);
-
-    if ( !(config[0xc3c] & 0x08) ) {
-      config[0xc3c] |= 0x08 ;  /* Base Address enable register */
-    }
-    config[LOW_BOOTCS_DREG] = 0x00 ;
-    config[HI_BOOTCS_DREG]  = 0xFF ;
-
-    memset (data, '\0', len) ;
-    for (i = 0; i < len; i++) { data[i] = flash[0x8000 - len + i]; }
-    config[LOW_BOOTCS_DREG] = 0xFC;
-    config[HI_BOOTCS_DREG]  = 0xFF;
-
-    if (memcmp (&data[48], "DIVAserverPR", 12)) {
-      DBG_ERR(("A: failed to read serial number"))
-      DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-                data[0], data[1], data[2], data[3],
-                data[4], data[5], data[6], data[7]))
-      return (-1);
-    }
-#else /* } { */
-    DBG_ERR(("A: failed to read DIVA signature word"))
-    DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-              data[0], data[1], data[2], data[3],
-              data[4], data[5], data[6], data[7]))
-    DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46], data[45],  data[44]))
-#endif /* } */
-  }
-
-  a->xdi_adapter.serialNo = (data[47] << 24) | (data[46] << 16) | (data[45] <<  8) |  data[44];
-  if (!a->xdi_adapter.serialNo || (a->xdi_adapter.serialNo == 0xffffffff)) {
-    a->xdi_adapter.serialNo = 0;
-    DBG_ERR(("A: failed to read serial number"))
-    return (-1);
-  }
-
-  DBG_LOG(("Serial No.          : %ld",     a->xdi_adapter.serialNo))
-  DBG_TRC(("Board Revision      : %d.%02d", (int)data[41], (int)data[40]))
-  DBG_TRC(("PLD revision        : %d.%02d", (int)data[33], (int)data[32]))
-  DBG_TRC(("Boot loader version : %d.%02d", (int)data[37], (int)data[36]))
-
-  DBG_TRC(("Manufacturing Date  : %d/%02d/%02d  (yyyy/mm/dd)",
-            (int)((data[28] > 90) ? 1900 : 2000) + (int)data[28],
-            (int)data[29], (int)data[30]))
-
-  return (0);
+	return (0);
 }
 
-void
-diva_os_prepare_pri2_functions (PISDN_ADAPTER IoAdapter)
+void diva_os_prepare_pri2_functions(PISDN_ADAPTER IoAdapter)
 {
 }
 
-void
-diva_os_prepare_pri_functions (PISDN_ADAPTER IoAdapter)
+void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter)
 {
 }
 
@@ -814,37 +862,37 @@
 **  Checks presence of DSP on board
 */
 static int
-dsp_check_presence (volatile byte* addr, volatile byte* data, int dsp)
+dsp_check_presence(volatile byte * addr, volatile byte * data, int dsp)
 {
-  word pattern;
+	word pattern;
 
 	WRITE_WORD(addr, 0x4000);
 	WRITE_WORD(data, DSP_SIGNATURE_PROBE_WORD);
 
 	WRITE_WORD(addr, 0x4000);
-  pattern = READ_WORD(data);
+	pattern = READ_WORD(data);
 
-  if (pattern != DSP_SIGNATURE_PROBE_WORD) {
-    DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
-              dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
-    return (-1);
-  }
+	if (pattern != DSP_SIGNATURE_PROBE_WORD) {
+		DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
+			 dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
+		return (-1);
+	}
 
 	WRITE_WORD(addr, 0x4000);
 	WRITE_WORD(data, ~DSP_SIGNATURE_PROBE_WORD);
 
 	WRITE_WORD(addr, 0x4000);
-  pattern = READ_WORD(data);
+	pattern = READ_WORD(data);
 
-  if (pattern != (word)~DSP_SIGNATURE_PROBE_WORD) {
-    DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
-              dsp, pattern, (word)~DSP_SIGNATURE_PROBE_WORD))
-    return (-2);
-  }
+	if (pattern != (word) ~ DSP_SIGNATURE_PROBE_WORD) {
+		DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
+			 dsp, pattern, (word) ~ DSP_SIGNATURE_PROBE_WORD))
+		return (-2);
+	}
 
-  DBG_TRC (("DSP[%d] present", dsp))
+	DBG_TRC(("DSP[%d] present", dsp))
 
-  return (0);
+	return (0);
 }
 
 
@@ -857,89 +905,93 @@
 **  ...
 **  Bit 29 - DSP30
 */
-static dword
-diva_pri_detect_dsps (diva_os_xdi_adapter_t* a)
+static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a)
 {
-  byte* base = a->resources.pci.addr[2];
-  dword ret = 0;
-  dword row_offset[7] = {
-    0x00000000,
-    0x00000800, /* 1 - ROW 1 */
-    0x00000840, /* 2 - ROW 2 */
-    0x00001000, /* 3 - ROW 3 */
-    0x00001040, /* 4 - ROW 4 */
-    0x00000000  /* 5 - ROW 0 */
-  };
-
-  byte* dsp_addr_port, *dsp_data_port, row_state;
-  int dsp_row = 0, dsp_index, dsp_num;
-
-  if (!base || !a->xdi_adapter.reset) {
-    return (0);
-  }
-
-  *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_DSP_RESET;
-  diva_os_wait (5) ;
-
-  for (dsp_num = 0; dsp_num < 30; dsp_num++) {
-    dsp_row   = dsp_num / 7 + 1;
-    dsp_index = dsp_num % 7;
-
-    dsp_data_port = base;
-    dsp_addr_port = base;
-
-    dsp_data_port += row_offset[dsp_row];
-    dsp_addr_port += row_offset[dsp_row];
-
-    dsp_data_port += (dsp_index * 8);
-    dsp_addr_port += (dsp_index * 8) + 0x80;
-
-    if (!dsp_check_presence (dsp_addr_port, dsp_data_port, dsp_num+1)) {
-      ret |= (1 << dsp_num);
-    }
-  }
-
-  *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2;
-  diva_os_wait (5);
-
-  /*
-    Verify modules
-  */
-  for (dsp_row = 0; dsp_row < 4; dsp_row++) {
-    row_state = ((ret >> (dsp_row*7)) & 0x7F);
-    if (row_state && (row_state != 0x7F)) {
-      for (dsp_index = 0; dsp_index < 7; dsp_index++) {
-        if (!(row_state & (1 << dsp_index))) {
-          DBG_ERR (("A: MODULE[%d]-DSP[%d] failed", dsp_row+1, dsp_index+1))
-        }
-      }
-    }
-  }
-
-  if (!(ret & 0x10000000)) {
-    DBG_ERR (("A: ON BOARD-DSP[1] failed"))
-  }
-  if (!(ret & 0x20000000)) {
-    DBG_ERR (("A: ON BOARD-DSP[2] failed"))
-  }
-
-  /*
-    Print module population now
-  */
-  DBG_LOG(("+-----------------------+"))
-  DBG_LOG(("| DSP MODULE POPULATION |"))
-  DBG_LOG(("+-----------------------+"))
-  DBG_LOG(("|  1  |  2  |  3  |  4  |"))
-  DBG_LOG(("+-----------------------+"))
-  DBG_LOG(("|  %s  |  %s  |  %s  |  %s  |",
-    ((ret >> (0*7)) & 0x7F) ? "Y" : "N",
-    ((ret >> (1*7)) & 0x7F) ? "Y" : "N",
-    ((ret >> (2*7)) & 0x7F) ? "Y" : "N",
-    ((ret >> (3*7)) & 0x7F) ? "Y" : "N"))
-  DBG_LOG(("+-----------------------+"))
+	byte *base = a->resources.pci.addr[2];
+	dword ret = 0;
+	dword row_offset[7] = {
+		0x00000000,
+		0x00000800,	/* 1 - ROW 1 */
+		0x00000840,	/* 2 - ROW 2 */
+		0x00001000,	/* 3 - ROW 3 */
+		0x00001040,	/* 4 - ROW 4 */
+		0x00000000	/* 5 - ROW 0 */
+	};
+
+	byte *dsp_addr_port, *dsp_data_port, row_state;
+	int dsp_row = 0, dsp_index, dsp_num;
+
+	if (!base || !a->xdi_adapter.reset) {
+		return (0);
+	}
+
+	*(volatile byte *) (a->xdi_adapter.reset) =
+	    _MP_RISC_RESET | _MP_DSP_RESET;
+	diva_os_wait(5);
+
+	for (dsp_num = 0; dsp_num < 30; dsp_num++) {
+		dsp_row = dsp_num / 7 + 1;
+		dsp_index = dsp_num % 7;
+
+		dsp_data_port = base;
+		dsp_addr_port = base;
+
+		dsp_data_port += row_offset[dsp_row];
+		dsp_addr_port += row_offset[dsp_row];
+
+		dsp_data_port += (dsp_index * 8);
+		dsp_addr_port += (dsp_index * 8) + 0x80;
+
+		if (!dsp_check_presence
+		    (dsp_addr_port, dsp_data_port, dsp_num + 1)) {
+			ret |= (1 << dsp_num);
+		}
+	}
+
+	*(volatile byte *) (a->xdi_adapter.reset) =
+	    _MP_RISC_RESET | _MP_LED1 | _MP_LED2;
+	diva_os_wait(5);
+
+	/*
+	   Verify modules
+	 */
+	for (dsp_row = 0; dsp_row < 4; dsp_row++) {
+		row_state = ((ret >> (dsp_row * 7)) & 0x7F);
+		if (row_state && (row_state != 0x7F)) {
+			for (dsp_index = 0; dsp_index < 7; dsp_index++) {
+				if (!(row_state & (1 << dsp_index))) {
+					DBG_ERR(("A: MODULE[%d]-DSP[%d] failed",
+						 dsp_row + 1,
+						 dsp_index + 1))
+				}
+			}
+		}
+	}
+
+	if (!(ret & 0x10000000)) {
+		DBG_ERR(("A: ON BOARD-DSP[1] failed"))
+	}
+	if (!(ret & 0x20000000)) {
+		DBG_ERR(("A: ON BOARD-DSP[2] failed"))
+	}
+
+	/*
+	   Print module population now
+	 */
+	DBG_LOG(("+-----------------------+"))
+	DBG_LOG(("| DSP MODULE POPULATION |"))
+	DBG_LOG(("+-----------------------+"))
+	DBG_LOG(("|  1  |  2  |  3  |  4  |"))
+	DBG_LOG(("+-----------------------+"))
+	DBG_LOG(("|  %s  |  %s  |  %s  |  %s  |",
+		 ((ret >> (0 * 7)) & 0x7F) ? "Y" : "N",
+		 ((ret >> (1 * 7)) & 0x7F) ? "Y" : "N",
+		 ((ret >> (2 * 7)) & 0x7F) ? "Y" : "N",
+		 ((ret >> (3 * 7)) & 0x7F) ? "Y" : "N"))
+	DBG_LOG(("+-----------------------+"))
 
-  DBG_LOG(("DSP's(present-absent):%08x-%08x", ret, ~ret & 0x3fffffff))
+	DBG_LOG(("DSP's(present-absent):%08x-%08x", ret,
+		 ~ret & 0x3fffffff))
 
-  return (ret);
+	return (ret);
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/os_pri.h b/drivers/isdn/hardware/eicon/os_pri.h
--- a/drivers/isdn/hardware/eicon/os_pri.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/isdn/hardware/eicon/os_pri.h	Sun Nov 17 20:30:13 2002
@@ -1,8 +1,8 @@
-/* $Id: os_pri.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: os_pri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
 
 #ifndef __DIVA_OS_PRI_REV_1_H__
 #define __DIVA_OS_PRI_REV_1_H__
 
-int diva_pri_init_card (diva_os_xdi_adapter_t* a);
+int diva_pri_init_card(diva_os_xdi_adapter_t * a);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
--- a/drivers/isdn/hardware/eicon/platform.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/platform.h	Sun Nov 17 20:30:15 2002
@@ -1,4 +1,4 @@
-/* $Id: platform.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $
+/* $Id: platform.h,v 1.1.2.6 2001/05/01 15:48:05 armin Exp $
  *
  * platform.h
  * 
diff -Nru a/drivers/isdn/hardware/eicon/s_4bri.c b/drivers/isdn/hardware/eicon/s_4bri.c
--- a/drivers/isdn/hardware/eicon/s_4bri.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/isdn/hardware/eicon/s_4bri.c	Sun Nov 17 20:30:02 2002
@@ -249,12 +249,12 @@
 
 /******************************************************************************/
 
-#define FPGA_PROG   0x0001		// PROG enable low
-#define FPGA_BUSY   0x0002		// BUSY high, DONE low
-#define	FPGA_CS     0x000C		// Enable I/O pins
+#define FPGA_PROG   0x0001		/* PROG enable low */
+#define FPGA_BUSY   0x0002		/* BUSY high, DONE low */
+#define	FPGA_CS     0x000C		/* Enable I/O pins */
 #define FPGA_CCLK   0x0100
 #define FPGA_DOUT   0x0400
-#define FPGA_DIN    FPGA_DOUT   // bidirectional I/O
+#define FPGA_DIN    FPGA_DOUT   /* bidirectional I/O */
 
 int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) {
 	int            bit ;
@@ -296,9 +296,9 @@
 /*
  *	prepare download, pulse PROGRAM pin down.
  */
-	WRITE_WORD(addr, baseval & ~FPGA_PROG) ; // PROGRAM low pulse
-	WRITE_WORD(addr, baseval) ;              // release
-	diva_os_wait (50) ;  // wait until FPGA finished internal memory clear
+	WRITE_WORD(addr, baseval & ~FPGA_PROG) ; /* PROGRAM low pulse */
+	WRITE_WORD(addr, baseval) ;              /* release */
+	diva_os_wait (50) ;  /* wait until FPGA finished internal memory clear */
 /*
  *	check done pin, must be low
  */
@@ -315,14 +315,14 @@
 	{
 		val = ((word)File[code++]) << 3 ;
 
-		for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) // put byte onto FPGA
+		for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) /* put byte onto FPGA */
 		{
-			baseval &= ~FPGA_DOUT ;             // clr  data bit
-			baseval |= (val & FPGA_DOUT) ;      // copy data bit
+			baseval &= ~FPGA_DOUT ;             /* clr  data bit */
+			baseval |= (val & FPGA_DOUT) ;      /* copy data bit */
 			WRITE_WORD(addr, baseval) ;
-			WRITE_WORD(addr, baseval | FPGA_CCLK) ;     // set CCLK hi
-			WRITE_WORD(addr, baseval | FPGA_CCLK) ;     // set CCLK hi
-			WRITE_WORD(addr, baseval) ;                 // set CCLK lo
+			WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
+			WRITE_WORD(addr, baseval | FPGA_CCLK) ;     /* set CCLK hi */
+			WRITE_WORD(addr, baseval) ;                 /* set CCLK lo */
 		}
 	}
 	xdiFreeFile (File) ;
@@ -868,7 +868,7 @@
 /*
  *	clear interrupt line (reset Local Interrupt Test Register)
  */
-	IoAdapter->reset[PLX9054_INTCSR] = 0x00 ;	// disable PCI interrupts
+	IoAdapter->reset[PLX9054_INTCSR] = 0x00 ;	/* disable PCI interrupts */
 	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
 }
 
diff -Nru a/drivers/isdn/hardware/eicon/s_bri.c b/drivers/isdn/hardware/eicon/s_bri.c
--- a/drivers/isdn/hardware/eicon/s_bri.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/s_bri.c	Sun Nov 17 20:30:15 2002
@@ -459,9 +459,9 @@
 static void disable_bri_interrupt (PISDN_ADAPTER IoAdapter) {
  if ( IoAdapter->reset )
  {
-  outpp (IoAdapter->reset, 0x00) ; // disable interrupts !
+  outpp (IoAdapter->reset, 0x00) ; /* disable interrupts ! */
  }
- outpp (IoAdapter->ctlReg, 0x00) ;    // clear int, halt cpu
+ outpp (IoAdapter->ctlReg, 0x00) ; /* clear int, halt cpu */
 }
 /* -------------------------------------------------------------------------
   Fill card entry points
diff -Nru a/drivers/isdn/hardware/eicon/s_pri.c b/drivers/isdn/hardware/eicon/s_pri.c
--- a/drivers/isdn/hardware/eicon/s_pri.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/isdn/hardware/eicon/s_pri.c	Sun Nov 17 20:30:16 2002
@@ -228,7 +228,7 @@
 static dword
 diva_pri_detect_dsps (PISDN_ADAPTER IoAdapter)
 {
-//  byte* base = a->resources.pci.addr[2];
+  /* byte* base = a->resources.pci.addr[2]; */
   byte* base = IoAdapter->reset - MP_RESET ;
   dword ret = 0, DspCount = 0 ;
   dword row_offset[] = {
@@ -242,12 +242,12 @@
   byte *dsp_addr_port, *dsp_data_port, row_state;
   int dsp_row = 0, dsp_index, dsp_num;
  IoAdapter->InitialDspInfo &= 0xffff ;
-//  if (!base || !a->xdi_adapter.reset)
+ /* if (!base || !a->xdi_adapter.reset) */
   if (!base || !IoAdapter->reset)
   {
     return (0);
   }
-//  *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_DSP_RESET;
+  /* *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_DSP_RESET; */
   *(volatile byte*)(IoAdapter->reset) = _MP_RISC_RESET | _MP_DSP_RESET;
   diva_os_wait (5) ;
   for (dsp_num = 0; dsp_num < 30; dsp_num++) {
@@ -264,7 +264,7 @@
    DspCount++ ;
     }
   }
-//  *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2;
+  /* *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; */
   *(volatile byte*)(IoAdapter->reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2;
   diva_os_wait (50) ;
   /*
diff -Nru a/drivers/isdn/hardware/eicon/um_idi.c b/drivers/isdn/hardware/eicon/um_idi.c
--- a/drivers/isdn/hardware/eicon/um_idi.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/um_idi.c	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,4 @@
-/* $Id: um_idi.c,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: um_idi.c,v 1.1.2.2 2001/02/11 14:40:41 armin Exp $ */
 
 #include "platform.h"
 #include "di_defs.h"
@@ -17,110 +17,117 @@
 /* --------------------------------------------------------------------------
 		IMPORTS
    -------------------------------------------------------------------------- */
-extern void diva_os_wakeup_read (void* os_context);
-extern void diva_os_wakeup_close (void* os_context);
+extern void diva_os_wakeup_read(void *os_context);
+extern void diva_os_wakeup_close(void *os_context);
 /* --------------------------------------------------------------------------
 		LOCALS
    -------------------------------------------------------------------------- */
-static diva_entity_queue_t	adapter_q;
+static diva_entity_queue_t adapter_q;
 static diva_os_spin_lock_t adapter_lock;
 
-static diva_um_idi_adapter_t* diva_um_idi_find_adapter (dword nr);
-static void cleanup_adapter (diva_um_idi_adapter_t* a);
-static void cleanup_entity (divas_um_idi_entity_t* e);
-static int diva_user_mode_idi_adapter_features (diva_um_idi_adapter_t* a,
-                                                diva_um_idi_adapter_features_t* features);
-static int process_idi_request (divas_um_idi_entity_t* e,
-                                const diva_um_idi_req_hdr_t* req);
-static int process_idi_rc (divas_um_idi_entity_t* e,	byte rc);
-static int process_idi_ind (divas_um_idi_entity_t* e, byte ind);
-static int write_return_code (divas_um_idi_entity_t* e, byte rc);
+static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr);
+static void cleanup_adapter(diva_um_idi_adapter_t * a);
+static void cleanup_entity(divas_um_idi_entity_t * e);
+static int diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t * a,
+					       diva_um_idi_adapter_features_t
+					       * features);
+static int process_idi_request(divas_um_idi_entity_t * e,
+			       const diva_um_idi_req_hdr_t * req);
+static int process_idi_rc(divas_um_idi_entity_t * e, byte rc);
+static int process_idi_ind(divas_um_idi_entity_t * e, byte ind);
+static int write_return_code(divas_um_idi_entity_t * e, byte rc);
 
 /* --------------------------------------------------------------------------
 		MAIN
    -------------------------------------------------------------------------- */
-int
-diva_user_mode_idi_init (void)
+int diva_user_mode_idi_init(void)
 {
-  diva_q_init(&adapter_q);
-  diva_os_initialize_spin_lock (&adapter_lock, "adapter");
-  return (0);
+	diva_q_init(&adapter_q);
+	diva_os_initialize_spin_lock(&adapter_lock, "adapter");
+	return (0);
 }
 
 /* --------------------------------------------------------------------------
 		Copy adapter features to user supplied buffer
    -------------------------------------------------------------------------- */
 static int
-diva_user_mode_idi_adapter_features (diva_um_idi_adapter_t* a,
-			diva_um_idi_adapter_features_t* features)
+diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t * a,
+				    diva_um_idi_adapter_features_t *
+				    features)
 {
-  IDI_SYNC_REQ sync_req;
+	IDI_SYNC_REQ sync_req;
 
-  if ((a) && (a->d.request)){
-    features->type           = a->d.type;
-    features->features       = a->d.features;
-    features->channels       = a->d.channels;
-    memset(features->name, 0, sizeof(features->name));
-
-    sync_req.GetName.Req = 0;
-    sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
-    (*(a->d.request))((ENTITY *)&sync_req);
-    strncpy(features->name, sync_req.GetName.name, sizeof(features->name)-1);
-
-    sync_req.GetSerial.Req = 0;
-    sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
-    sync_req.GetSerial.serial = 0;
-    (*(a->d.request))((ENTITY *)&sync_req);
-    features->serial_number = sync_req.GetSerial.serial;
-  }
+	if ((a) && (a->d.request)) {
+		features->type = a->d.type;
+		features->features = a->d.features;
+		features->channels = a->d.channels;
+		memset(features->name, 0, sizeof(features->name));
+
+		sync_req.GetName.Req = 0;
+		sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
+		(*(a->d.request)) ((ENTITY *) & sync_req);
+		strncpy(features->name, sync_req.GetName.name,
+			sizeof(features->name) - 1);
+
+		sync_req.GetSerial.Req = 0;
+		sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
+		sync_req.GetSerial.serial = 0;
+		(*(a->d.request)) ((ENTITY *) & sync_req);
+		features->serial_number = sync_req.GetSerial.serial;
+	}
 
-  return ((a) ? 0 : -1);
+	return ((a) ? 0 : -1);
 }
 
 /* --------------------------------------------------------------------------
 		REMOVE ADAPTER
    -------------------------------------------------------------------------- */
-void diva_user_mode_idi_remove_adapter(int adapter_nr) {
-	diva_um_idi_adapter_t* a = (diva_um_idi_adapter_t*)diva_q_get_head (&adapter_q);
+void diva_user_mode_idi_remove_adapter(int adapter_nr)
+{
+	diva_um_idi_adapter_t *a =
+	    (diva_um_idi_adapter_t *) diva_q_get_head(&adapter_q);
 
-  while (a) {
-    if(a->adapter_nr == adapter_nr) {
-      diva_q_remove (&adapter_q, &a->link);
-      cleanup_adapter (a);
-      DBG_LOG (("DIDD: del adapter(%d)", a->adapter_nr));
-      diva_os_free (0, a);
-      break;
-    }
-    a = (diva_um_idi_adapter_t*)diva_q_get_next (&a->link);
-  }
+	while (a) {
+		if (a->adapter_nr == adapter_nr) {
+			diva_q_remove(&adapter_q, &a->link);
+			cleanup_adapter(a);
+			DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
+			diva_os_free(0, a);
+			break;
+		}
+		a = (diva_um_idi_adapter_t *) diva_q_get_next(&a->link);
+	}
 }
 
 /* --------------------------------------------------------------------------
 		CALLED ON DRIVER EXIT (UNLOAD)
    -------------------------------------------------------------------------- */
-void
-diva_user_mode_idi_finit (void)
+void diva_user_mode_idi_finit(void)
 {
-	diva_um_idi_adapter_t* a = (diva_um_idi_adapter_t*)diva_q_get_head (&adapter_q);
+	diva_um_idi_adapter_t *a =
+	    (diva_um_idi_adapter_t *) diva_q_get_head(&adapter_q);
 
 	while (a) {
-		diva_q_remove (&adapter_q, &a->link);
-		cleanup_adapter (a);
-		DBG_LOG (("DIDD: del adapter(%d)", a->adapter_nr));
-		diva_os_free (0, a);
-		a = (diva_um_idi_adapter_t*)diva_q_get_head (&adapter_q);
+		diva_q_remove(&adapter_q, &a->link);
+		cleanup_adapter(a);
+		DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
+		diva_os_free(0, a);
+		a = (diva_um_idi_adapter_t *) diva_q_get_head(&adapter_q);
 	}
-        diva_os_destroy_spin_lock (&adapter_lock, "adapter");
+	diva_os_destroy_spin_lock(&adapter_lock, "adapter");
 }
 
 /* -------------------------------------------------------------------------
 		CREATE AND INIT IDI ADAPTER
 	 ------------------------------------------------------------------------- */
-int diva_user_mode_idi_create_adapter (const DESCRIPTOR* d, int adapter_nr) {
-        diva_os_spin_lock_magic_t old_irql;
-	diva_um_idi_adapter_t* a =
-		(diva_um_idi_adapter_t*)diva_os_malloc (0, sizeof(diva_um_idi_adapter_t));
-	
+int diva_user_mode_idi_create_adapter(const DESCRIPTOR * d, int adapter_nr)
+{
+	diva_os_spin_lock_magic_t old_irql;
+	diva_um_idi_adapter_t *a =
+	    (diva_um_idi_adapter_t *) diva_os_malloc(0,
+						     sizeof
+						     (diva_um_idi_adapter_t));
+
 	if (!a) {
 		return (-1);
 	}
@@ -129,20 +136,21 @@
 	a->d = *d;
 	a->adapter_nr = adapter_nr;
 
-	DBG_LOG (("DIDD_ADD A(%d), type:%02x, features:%04x, channels:%d",
-					 adapter_nr, a->d.type, a->d.features, a->d.channels));
+	DBG_LOG(("DIDD_ADD A(%d), type:%02x, features:%04x, channels:%d",
+		 adapter_nr, a->d.type, a->d.features, a->d.channels));
 
-        diva_os_enter_spin_lock (&adapter_lock, &old_irql, "create_adapter");
-	diva_q_add_tail (&adapter_q, &a->link);
-        diva_os_leave_spin_lock (&adapter_lock, &old_irql, "create_adapter");
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_adapter");
+	diva_q_add_tail(&adapter_q, &a->link);
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_adapter");
 	return (0);
 }
 
-static int cmp_adapter_nr (const void* what, const diva_entity_link_t* p) {
-	diva_um_idi_adapter_t* a = (diva_um_idi_adapter_t*)p;
-	dword nr = (dword)(unsigned long)what;
+static int cmp_adapter_nr(const void *what, const diva_entity_link_t * p)
+{
+	diva_um_idi_adapter_t *a = (diva_um_idi_adapter_t *) p;
+	dword nr = (dword) (unsigned long) what;
 
-	DBG_TRC (("find_adapter: (%d)-(%d)", nr, a->adapter_nr));
+	DBG_TRC(("find_adapter: (%d)-(%d)", nr, a->adapter_nr));
 
 	return (nr != a->adapter_nr);
 }
@@ -150,112 +158,121 @@
 /* ------------------------------------------------------------------------
 			Find adapter by Adapter number
    ------------------------------------------------------------------------ */
-static diva_um_idi_adapter_t* diva_um_idi_find_adapter (dword nr) {
-	return (diva_um_idi_adapter_t*)diva_q_find (&adapter_q,
-                                                    (void*)(unsigned long)nr,
-                                                    cmp_adapter_nr);
+static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr)
+{
+	return (diva_um_idi_adapter_t *) diva_q_find(&adapter_q,
+						     (void *) (unsigned
+							       long) nr,
+						     cmp_adapter_nr);
 }
 
 /* ------------------------------------------------------------------------
 		Return number of adapters in system
    ------------------------------------------------------------------------ */
-int diva_um_idi_nr_of_adapters (void) {
-	return (diva_q_get_nr_of_entries (&adapter_q));
+int diva_um_idi_nr_of_adapters(void)
+{
+	return (diva_q_get_nr_of_entries(&adapter_q));
 }
 
 /* ------------------------------------------------------------------------
 		Cleanup this adapter and cleanup/delete all entities assigned
 		to this adapter
    ------------------------------------------------------------------------ */
-static void cleanup_adapter (diva_um_idi_adapter_t* a) {
-  divas_um_idi_entity_t* e = (divas_um_idi_entity_t*)diva_q_get_head	(&a->entity_q);
+static void cleanup_adapter(diva_um_idi_adapter_t * a)
+{
+	divas_um_idi_entity_t *e =
+	    (divas_um_idi_entity_t *) diva_q_get_head(&a->entity_q);
 
-  while (e) {
-    diva_q_remove (&a->entity_q, &e->link);
-    cleanup_entity (e);
-    if (e->os_context) {
-		  diva_os_wakeup_read (e->os_context);
-		  diva_os_wakeup_close (e->os_context);
-    }
-    e = (divas_um_idi_entity_t*)diva_q_get_head	(&a->entity_q);
-  }
-  memset(&a->d, 0x00, sizeof(DESCRIPTOR));
+	while (e) {
+		diva_q_remove(&a->entity_q, &e->link);
+		cleanup_entity(e);
+		if (e->os_context) {
+			diva_os_wakeup_read(e->os_context);
+			diva_os_wakeup_close(e->os_context);
+		}
+		e = (divas_um_idi_entity_t *) diva_q_get_head(&a->entity_q);
+	}
+	memset(&a->d, 0x00, sizeof(DESCRIPTOR));
 }
 
 /* ------------------------------------------------------------------------
 		Cleanup, but NOT delete this entity
    ------------------------------------------------------------------------ */
-static void cleanup_entity (divas_um_idi_entity_t* e) {
-  e->os_ref   = 0;
-  e->status   = 0;
-  e->adapter  = 0;
-  e->e.Id     = 0;
-  e->rc_count = 0;
+static void cleanup_entity(divas_um_idi_entity_t * e)
+{
+	e->os_ref = 0;
+	e->status = 0;
+	e->adapter = 0;
+	e->e.Id = 0;
+	e->rc_count = 0;
 
-  e->status |= DIVA_UM_IDI_REMOVED;
+	e->status |= DIVA_UM_IDI_REMOVED;
 	e->status |= DIVA_UM_IDI_REMOVE_PENDING;
 
-  diva_data_q_finit	(&e->data);
-  diva_data_q_finit	(&e->rc);
+	diva_data_q_finit(&e->data);
+	diva_data_q_finit(&e->rc);
 }
 
 
 /* ------------------------------------------------------------------------
 		Create ENTITY, link it to the adapter and remove pointer to entity
    ------------------------------------------------------------------------ */
-void* divas_um_idi_create_entity (dword adapter_nr, void* file) {
-  divas_um_idi_entity_t* e;
-  diva_um_idi_adapter_t* a;
-  diva_os_spin_lock_magic_t old_irql;
+void *divas_um_idi_create_entity(dword adapter_nr, void *file)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	diva_os_spin_lock_magic_t old_irql;
 
-	if ((e = (divas_um_idi_entity_t*)diva_os_malloc (0, sizeof(*e)))) {
+	if ((e = (divas_um_idi_entity_t *) diva_os_malloc(0, sizeof(*e)))) {
 		memset(e, 0x00, sizeof(*e));
-		if (!(e->os_context = diva_os_malloc (0, diva_os_get_context_size ()))) {
-			DBG_LOG (("E(%08x) no memory for os context", e));
-			diva_os_free (0, e);
+		if (!
+		    (e->os_context =
+		     diva_os_malloc(0, diva_os_get_context_size()))) {
+			DBG_LOG(("E(%08x) no memory for os context", e));
+			diva_os_free(0, e);
 			return (0);
 		}
-		memset(e->os_context, 0x00, diva_os_get_context_size ());
+		memset(e->os_context, 0x00, diva_os_get_context_size());
 
-		if ((diva_data_q_init (&e->data, 2048+512, 16))) {
-			diva_os_free (0, e->os_context);
-			diva_os_free (0, e);
+		if ((diva_data_q_init(&e->data, 2048 + 512, 16))) {
+			diva_os_free(0, e->os_context);
+			diva_os_free(0, e);
 			return (0);
 		}
-		if ((diva_data_q_init (&e->rc, 64, 2))) {
-			diva_data_q_finit	(&e->data);
-			diva_os_free (0, e->os_context);
-			diva_os_free (0, e);
+		if ((diva_data_q_init(&e->rc, 64, 2))) {
+			diva_data_q_finit(&e->data);
+			diva_os_free(0, e->os_context);
+			diva_os_free(0, e);
 			return (0);
 		}
 
-    diva_os_enter_spin_lock (&adapter_lock, &old_irql, "create_entity");
+		diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_entity");
 		/*
-			Look for Adapter requested
-			*/
-		if (!(a = diva_um_idi_find_adapter (adapter_nr))) {
+		   Look for Adapter requested
+		 */
+		if (!(a = diva_um_idi_find_adapter(adapter_nr))) {
 			/*
-				No adapter was found, or this adapter was removed
-				*/
-      diva_os_leave_spin_lock (&adapter_lock, &old_irql, "create_entity");
-
-			DBG_LOG (("A: no adapter(%ld)", adapter_nr));
-
-			cleanup_entity (e);
-			diva_os_free (0, e->os_context);
-			diva_os_free (0, e);
+			   No adapter was found, or this adapter was removed
+			 */
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
+
+			DBG_LOG(("A: no adapter(%ld)", adapter_nr));
+
+			cleanup_entity(e);
+			diva_os_free(0, e->os_context);
+			diva_os_free(0, e);
 
 			return (0);
 		}
 
-		e->os_ref = file; /* link to os handle */
-		e->adapter = a;   /* link to adapter   */
+		e->os_ref = file;	/* link to os handle */
+		e->adapter = a;	/* link to adapter   */
 
-		diva_q_add_tail (&a->entity_q, &e->link); /* link from adapter */
+		diva_q_add_tail(&a->entity_q, &e->link);	/* link from adapter */
 
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "create_entity");
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
 
-		DBG_LOG (("A(%ld), create E(%08x)", adapter_nr, e));
+		DBG_LOG(("A(%ld), create E(%08x)", adapter_nr, e));
 	}
 
 	return (e);
@@ -264,203 +281,215 @@
 /* ------------------------------------------------------------------------
 		Unlink entity and free memory 
    ------------------------------------------------------------------------ */
-int divas_um_idi_delete_entity (int adapter_nr, void* entity) {
-  divas_um_idi_entity_t* e;
-  diva_um_idi_adapter_t* a;
-  diva_os_spin_lock_magic_t old_irql;
-
-  if (!(e = (divas_um_idi_entity_t*)entity))
-    return(-1);
-
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "delete_entity");
-  if ((a = e->adapter)) {
-    diva_q_remove (&a->entity_q, &e->link);
-  }
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "delete_entity");
-
-  diva_um_idi_stop_wdog (entity);
-  cleanup_entity (e);
-  diva_os_free (0, e->os_context);
-  memset(e, 0x00, sizeof(*e));
-  diva_os_free (0, e);
+int divas_um_idi_delete_entity(int adapter_nr, void *entity)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	diva_os_spin_lock_magic_t old_irql;
+
+	if (!(e = (divas_um_idi_entity_t *) entity))
+		return (-1);
 
-  DBG_LOG (("A(%d) remove E:%08x", adapter_nr, e));
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "delete_entity");
+	if ((a = e->adapter)) {
+		diva_q_remove(&a->entity_q, &e->link);
+	}
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "delete_entity");
+
+	diva_um_idi_stop_wdog(entity);
+	cleanup_entity(e);
+	diva_os_free(0, e->os_context);
+	memset(e, 0x00, sizeof(*e));
+	diva_os_free(0, e);
 
-  return (0);
+	DBG_LOG(("A(%d) remove E:%08x", adapter_nr, e));
+
+	return (0);
 }
 
 /* --------------------------------------------------------------------------
 		Called by application to read data from IDI
 	 -------------------------------------------------------------------------- */
-int diva_um_idi_read (void* entity,
-                      void* os_handle,
-                      void* dst,
-                      int max_length,
-                      divas_um_idi_copy_to_user_fn_t cp_fn) {
-	divas_um_idi_entity_t* e;
-	diva_um_idi_adapter_t* a;
-	const void* data;
+int diva_um_idi_read(void *entity,
+		     void *os_handle,
+		     void *dst,
+		     int max_length, divas_um_idi_copy_to_user_fn_t cp_fn)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	const void *data;
 	int length, ret = 0;
-	diva_um_idi_data_queue_t* q;
-  diva_os_spin_lock_magic_t old_irql;
+	diva_um_idi_data_queue_t *q;
+	diva_os_spin_lock_magic_t old_irql;
 
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "read");
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "read");
 
-	e = (divas_um_idi_entity_t*)entity;
-  if (!e || (!(a = e->adapter)) ||
-      (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
-      (e->status & DIVA_UM_IDI_REMOVED) ||
-      (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "read");
-	  DBG_ERR(("E(%08x) read failed - adapter removed", e))
-    return (-1);
-  }
+	e = (divas_um_idi_entity_t *) entity;
+	if (!e || (!(a = e->adapter)) ||
+	    (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
+	    (e->status & DIVA_UM_IDI_REMOVED) ||
+	    (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
+		DBG_ERR(("E(%08x) read failed - adapter removed", e))
+		return (-1);
+	}
 
 	DBG_TRC(("A(%d) E(%08x) read(%d)", a->adapter_nr, e, max_length));
 
 	/*
-		Try to read return code first
-		*/
-	data	= diva_data_q_get_segment4read	(&e->rc);
-	q			=	&e->rc;
+	   Try to read return code first
+	 */
+	data = diva_data_q_get_segment4read(&e->rc);
+	q = &e->rc;
 
 	/*
-		No return codes available, read indications now
-		*/
+	   No return codes available, read indications now
+	 */
 	if (!data) {
 		if (!(e->status & DIVA_UM_IDI_RC_PENDING)) {
-			DBG_TRC (("A(%d) E(%08x) read data", a->adapter_nr, e));
-			data	= diva_data_q_get_segment4read	(&e->data);
-			q			=	&e->data;
+			DBG_TRC(("A(%d) E(%08x) read data", a->adapter_nr, e));
+			data = diva_data_q_get_segment4read(&e->data);
+			q = &e->data;
 		}
 	} else {
 		e->status &= ~DIVA_UM_IDI_RC_PENDING;
-		DBG_TRC (("A(%d) E(%08x) read rc", a->adapter_nr, e));
+		DBG_TRC(("A(%d) E(%08x) read rc", a->adapter_nr, e));
 	}
-		
+
 	if (data) {
-		if ((length = diva_data_q_get_segment_length (q)) > max_length) {
+		if ((length = diva_data_q_get_segment_length(q)) >
+		    max_length) {
 			/*
-				Not enough space to read message
-				*/
-			DBG_ERR (("A: A(%d) E(%08x) read small buffer", a->adapter_nr, e, ret));
-      diva_os_leave_spin_lock (&adapter_lock, &old_irql, "read");
+			   Not enough space to read message
+			 */
+			DBG_ERR(("A: A(%d) E(%08x) read small buffer",
+				 a->adapter_nr, e, ret));
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql,
+						"read");
 			return (-2);
 		}
 		/*
-			Copy it to user, this function does access ONLY locked an verified
-			memory, also we can access it witch spin lock held
-			*/
-	
+		   Copy it to user, this function does access ONLY locked an verified
+		   memory, also we can access it witch spin lock held
+		 */
+
 		if ((ret = (*cp_fn) (os_handle, dst, data, length)) >= 0) {
 			/*
-				Acknowledge only if read was successfull
-				*/
-			diva_data_q_ack_segment4read	(q);
+			   Acknowledge only if read was successfull
+			 */
+			diva_data_q_ack_segment4read(q);
 		}
 	}
 
 
-  DBG_TRC (("A(%d) E(%08x) read=%d", a->adapter_nr, e, ret));
+	DBG_TRC(("A(%d) E(%08x) read=%d", a->adapter_nr, e, ret));
 
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "read");
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
 
 	return (ret);
 }
 
 
-int diva_um_idi_write (void* entity,
-                       void* os_handle,
-                       const void* src,
-                       int length,
-                       divas_um_idi_copy_from_user_fn_t cp_fn) {
-	divas_um_idi_entity_t* e;
-	diva_um_idi_adapter_t* a;
-	diva_um_idi_req_hdr_t* req;
-	void* data;
+int diva_um_idi_write(void *entity,
+		      void *os_handle,
+		      const void *src,
+		      int length, divas_um_idi_copy_from_user_fn_t cp_fn)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	diva_um_idi_req_hdr_t *req;
+	void *data;
 	int ret = 0;
-  diva_os_spin_lock_magic_t old_irql;
+	diva_os_spin_lock_magic_t old_irql;
+
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "write");
+
+	e = (divas_um_idi_entity_t *) entity;
+	if (!e || (!(a = e->adapter)) ||
+	    (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
+	    (e->status & DIVA_UM_IDI_REMOVED) ||
+	    (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+		DBG_ERR(("E(%08x) write failed - adapter removed", e))
+		return (-1);
+	}
 
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "write");
+	DBG_TRC(("A(%d) E(%08x) write(%d)", a->adapter_nr, e, length));
 
-  e = (divas_um_idi_entity_t*)entity;
-  if (!e || (!(a = e->adapter)) ||
-      (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
-      (e->status & DIVA_UM_IDI_REMOVED) ||
-      (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-    DBG_ERR(("E(%08x) write failed - adapter removed", e))
-    return (-1);
-  }
-
-  DBG_TRC(("A(%d) E(%08x) write(%d)", a->adapter_nr, e, length));
-
-  if ((length < sizeof (*req)) || (length > sizeof (e->buffer))) {
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-    return (-2);
-  }
-
-  if (e->status & DIVA_UM_IDI_RC_PENDING) {
-    DBG_ERR(("A: A(%d) E(%08x) rc pending", a->adapter_nr, e));
-              diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-    return (-1); /* should wait for RC code first */
-  }
+	if ((length < sizeof(*req)) || (length > sizeof(e->buffer))) {
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+		return (-2);
+	}
+
+	if (e->status & DIVA_UM_IDI_RC_PENDING) {
+		DBG_ERR(("A: A(%d) E(%08x) rc pending", a->adapter_nr, e));
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+		return (-1);	/* should wait for RC code first */
+	}
 
 	/*
-			Copy function does access only locked verified memory,
-			also it can be called with spin lock held
-		*/
-	if ((ret = (*cp_fn)(os_handle, e->buffer, src, length)) < 0) {
-		DBG_TRC(("A: A(%d) E(%08x) write error=%d", a->adapter_nr, e, ret));
-                diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
+	   Copy function does access only locked verified memory,
+	   also it can be called with spin lock held
+	 */
+	if ((ret = (*cp_fn) (os_handle, e->buffer, src, length)) < 0) {
+		DBG_TRC(("A: A(%d) E(%08x) write error=%d", a->adapter_nr,
+			 e, ret));
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
 		return (ret);
 	}
 
-	req = (diva_um_idi_req_hdr_t*)&e->buffer[0];
+	req = (diva_um_idi_req_hdr_t *) & e->buffer[0];
 
 	switch (req->type) {
-		case DIVA_UM_IDI_GET_FEATURES: {
+	case DIVA_UM_IDI_GET_FEATURES:{
 			DBG_LOG(("A(%d) get_features", a->adapter_nr));
-			if (!(data = diva_data_q_get_segment4write	(&e->data))) {
-				DBG_ERR(("A(%d) get_features, no free buffer", a->adapter_nr));
-                                diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
+			if (!(data =
+			     diva_data_q_get_segment4write(&e->data))) {
+				DBG_ERR(("A(%d) get_features, no free buffer",
+					 a->adapter_nr));
+				diva_os_leave_spin_lock(&adapter_lock,
+							&old_irql,
+							"write");
 				return (0);
 			}
-			diva_user_mode_idi_adapter_features (a,
-												&(((diva_um_idi_ind_hdr_t*)data)->hdr.features));
-			((diva_um_idi_ind_hdr_t*)data)->type = DIVA_UM_IDI_IND_FEATURES;
-			((diva_um_idi_ind_hdr_t*)data)->data_length = 0;
-			diva_data_q_ack_segment4write	(&e->data, sizeof(diva_um_idi_ind_hdr_t));
-
-      diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-
-			diva_os_wakeup_read (e->os_context);
-		} break;
-
-		case DIVA_UM_IDI_REQ:
-		case DIVA_UM_IDI_REQ_MAN:
-		case DIVA_UM_IDI_REQ_SIG:
-		case DIVA_UM_IDI_REQ_NET:
-			DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", \
-							a->adapter_nr, req->Req, req->ReqCh,
-							req->type & DIVA_UM_IDI_REQ_TYPE_MASK));
-			switch (process_idi_request (e, req)) {
-				case -1:
-          diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-					return (-1);
-				case -2:
-          diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-					diva_os_wakeup_read (e->os_context);
-					break;
-				default:
-          diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-					break;
-			}
+			diva_user_mode_idi_adapter_features(a, &(((diva_um_idi_ind_hdr_t
+								*) data)->hdr.features));
+			((diva_um_idi_ind_hdr_t *) data)->type =
+			    DIVA_UM_IDI_IND_FEATURES;
+			((diva_um_idi_ind_hdr_t *) data)->data_length = 0;
+			diva_data_q_ack_segment4write(&e->data,
+						      sizeof(diva_um_idi_ind_hdr_t));
+
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+
+			diva_os_wakeup_read(e->os_context);
+		}
+		break;
+
+	case DIVA_UM_IDI_REQ:
+	case DIVA_UM_IDI_REQ_MAN:
+	case DIVA_UM_IDI_REQ_SIG:
+	case DIVA_UM_IDI_REQ_NET:
+		DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", a->adapter_nr,
+			 req->Req, req->ReqCh,
+			 req->type & DIVA_UM_IDI_REQ_TYPE_MASK));
+		switch (process_idi_request(e, req)) {
+		case -1:
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+			return (-1);
+		case -2:
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+			diva_os_wakeup_read(e->os_context);
 			break;
-
 		default:
-      diva_os_leave_spin_lock (&adapter_lock, &old_irql, "write");
-			return (-1);
+			diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+			break;
+		}
+		break;
+
+	default:
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
+		return (-1);
 	}
 
 	DBG_TRC(("A(%d) E(%08x) write=%d", a->adapter_nr, e, ret));
@@ -471,76 +500,84 @@
 /* --------------------------------------------------------------------------
 			CALLBACK FROM XDI
 	 -------------------------------------------------------------------------- */
-static void diva_um_idi_xdi_callback (ENTITY* entity) {
-	divas_um_idi_entity_t* e = DIVAS_CONTAINING_RECORD(entity,
-                                   divas_um_idi_entity_t, e); 
-  diva_os_spin_lock_magic_t old_irql;
+static void diva_um_idi_xdi_callback(ENTITY * entity)
+{
+	divas_um_idi_entity_t *e = DIVAS_CONTAINING_RECORD(entity,
+							   divas_um_idi_entity_t,
+							   e);
+	diva_os_spin_lock_magic_t old_irql;
 	int call_wakeup = 0;
 
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "xdi_callback");
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
 
 	if (e->e.complete == 255) {
 		if (!(e->status & DIVA_UM_IDI_REMOVE_PENDING)) {
-      diva_um_idi_stop_wdog (e);
-    }
-		if ((call_wakeup = process_idi_rc (e, e->e.Rc))) {
+			diva_um_idi_stop_wdog(e);
+		}
+		if ((call_wakeup = process_idi_rc(e, e->e.Rc))) {
 			if (e->rc_count) {
 				e->rc_count--;
 			}
 		}
 		e->e.Rc = 0;
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "xdi_callback");
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
 
 		if (call_wakeup) {
-			diva_os_wakeup_read (e->os_context);
-			diva_os_wakeup_close (e->os_context);
+			diva_os_wakeup_read(e->os_context);
+			diva_os_wakeup_close(e->os_context);
 		}
 	} else {
 		if (e->status & DIVA_UM_IDI_REMOVE_PENDING) {
 			e->e.RNum = 0;
-			e->e.RNR =  2;
+			e->e.RNR = 2;
 		} else {
-			call_wakeup = process_idi_ind (e, e->e.Ind);
+			call_wakeup = process_idi_ind(e, e->e.Ind);
 		}
 		e->e.Ind = 0;
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "xdi_callback");
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
 		if (call_wakeup) {
-			diva_os_wakeup_read (e->os_context);
+			diva_os_wakeup_read(e->os_context);
 		}
 	}
 }
 
-static int process_idi_request (divas_um_idi_entity_t* e,
-                                const diva_um_idi_req_hdr_t* req) {
+static int process_idi_request(divas_um_idi_entity_t * e,
+			       const diva_um_idi_req_hdr_t * req)
+{
 	int assign = 0;
-	byte Req = (byte)req->Req;
+	byte Req = (byte) req->Req;
 	dword type = req->type & DIVA_UM_IDI_REQ_TYPE_MASK;
 
-	if (!e->e.Id || !e->e.callback) { /* not assigned */
+	if (!e->e.Id || !e->e.callback) {	/* not assigned */
 		if (Req != ASSIGN) {
-			DBG_ERR(("A: A(%d) E(%08x) not assigned", e->adapter->adapter_nr, e));
-			return (-1); /* NOT ASSIGNED */
+			DBG_ERR(("A: A(%d) E(%08x) not assigned",
+				 e->adapter->adapter_nr, e));
+			return (-1);	/* NOT ASSIGNED */
 		} else {
 			switch (type) {
-				case DIVA_UM_IDI_REQ_TYPE_MAN:
-					e->e.Id = MAN_ID;
-					DBG_TRC(("A(%d) E(%08x) assign MAN", e->adapter->adapter_nr, e));
-					break;
-
-				case DIVA_UM_IDI_REQ_TYPE_SIG:
-					e->e.Id = DSIG_ID;
-					DBG_TRC(("A(%d) E(%08x) assign SIG", e->adapter->adapter_nr, e));
-					break;
-
-				case DIVA_UM_IDI_REQ_TYPE_NET:
-					e->e.Id = NL_ID;
-					DBG_TRC(("A(%d) E(%08x) assign NET", e->adapter->adapter_nr, e));
-					break;
-
-				default:
-					DBG_ERR (("A: A(%d) E(%08x) unknown type=%08x", \
-										e->adapter->adapter_nr, e, type));
-					return (-1);
+			case DIVA_UM_IDI_REQ_TYPE_MAN:
+				e->e.Id = MAN_ID;
+				DBG_TRC(("A(%d) E(%08x) assign MAN",
+					 e->adapter->adapter_nr, e));
+				break;
+
+			case DIVA_UM_IDI_REQ_TYPE_SIG:
+				e->e.Id = DSIG_ID;
+				DBG_TRC(("A(%d) E(%08x) assign SIG",
+					 e->adapter->adapter_nr, e));
+				break;
+
+			case DIVA_UM_IDI_REQ_TYPE_NET:
+				e->e.Id = NL_ID;
+				DBG_TRC(("A(%d) E(%08x) assign NET",
+					 e->adapter->adapter_nr, e));
+				break;
+
+			default:
+				DBG_ERR(("A: A(%d) E(%08x) unknown type=%08x",
+					 e->adapter->adapter_nr, e,
+					 type));
+				return (-1);
 			}
 		}
 		e->e.XNum = 1;
@@ -550,43 +587,43 @@
 		e->e.R = &e->RData;
 		assign = 1;
 	}
-	e->status			 |= DIVA_UM_IDI_RC_PENDING;
-	e->e.Req				= Req;
-	e->e.ReqCh			= (byte)req->ReqCh;
-	e->e.X->PLength = (word)req->data_length;
-	e->e.X->P			  = (byte*)&req[1]; /* Our buffer is safe */
-
-	DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))", \
-					e->adapter->adapter_nr, e, \
-					e->e.Id, e->e.Req, e->e.ReqCh, e->e.X->PLength));
+	e->status |= DIVA_UM_IDI_RC_PENDING;
+	e->e.Req = Req;
+	e->e.ReqCh = (byte) req->ReqCh;
+	e->e.X->PLength = (word) req->data_length;
+	e->e.X->P = (byte *) & req[1];	/* Our buffer is safe */
+
+	DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
+		 e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
+		 e->e.ReqCh, e->e.X->PLength));
 
 	e->rc_count++;
 
-  if (e->adapter && e->adapter->d.request) {
-    diva_um_idi_start_wdog (e);
-    (*(e->adapter->d.request))(&e->e);
-  }
+	if (e->adapter && e->adapter->d.request) {
+		diva_um_idi_start_wdog(e);
+		(*(e->adapter->d.request)) (&e->e);
+	}
 
 	if (assign) {
 		if (e->e.Rc == OUT_OF_RESOURCES) {
 			/*
-				XDI has no entities more, call was not forwarded to the card,
-				no callback will be scheduled
-				*/
+			   XDI has no entities more, call was not forwarded to the card,
+			   no callback will be scheduled
+			 */
 			DBG_ERR(("A: A(%d) E(%08x) XDI out of entities",
-							e->adapter->adapter_nr, e));
+				 e->adapter->adapter_nr, e));
 
-			e->e.Id		 = 0;
+			e->e.Id = 0;
 			e->e.ReqCh = 0;
-			e->e.RcCh	 = 0;
-			e->e.Ind	 = 0;
+			e->e.RcCh = 0;
+			e->e.Ind = 0;
 			e->e.IndCh = 0;
-			e->e.XNum	 = 0;
-			e->e.RNum	 = 0;
+			e->e.XNum = 0;
+			e->e.RNum = 0;
 			e->e.callback = 0;
-			e->e.X		 = 0;
-			e->e.R		 = 0;
-			write_return_code (e, ASSIGN_RC | OUT_OF_RESOURCES);
+			e->e.X = 0;
+			e->e.R = 0;
+			write_return_code(e, ASSIGN_RC | OUT_OF_RESOURCES);
 			return (-2);
 		} else {
 			e->status |= DIVA_UM_IDI_ASSIGN_PENDING;
@@ -596,15 +633,16 @@
 	return (0);
 }
 
-static int process_idi_rc (divas_um_idi_entity_t* e, byte rc) {
-	DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)", \
-					e->adapter->adapter_nr, e, \
-					e->e.Id, rc, e->e.RcCh));
+static int process_idi_rc(divas_um_idi_entity_t * e, byte rc)
+{
+	DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)",
+		 e->adapter->adapter_nr, e, e->e.Id, rc, e->e.RcCh));
 
 	if (e->status & DIVA_UM_IDI_ASSIGN_PENDING) {
 		e->status &= ~DIVA_UM_IDI_ASSIGN_PENDING;
 		if (rc != ASSIGN_OK) {
-			DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed", e->adapter->adapter_nr, e));
+			DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed",
+				 e->adapter->adapter_nr, e));
 			e->e.callback = 0;
 			e->e.Id = 0;
 			e->e.Req = 0;
@@ -613,18 +651,18 @@
 			e->e.RcCh = 0;
 			e->e.Ind = 0;
 			e->e.IndCh = 0;
-			e->e.X		 = 0;
-			e->e.R		 = 0;
-			e->e.XNum	 = 0;
-			e->e.RNum	 = 0;
+			e->e.X = 0;
+			e->e.R = 0;
+			e->e.XNum = 0;
+			e->e.RNum = 0;
 		}
 	}
 	if ((e->e.Req == REMOVE) && e->e.Id && (rc == 0xff)) {
-		DBG_ERR(("A: A(%d) E(%08x)  discard OK in REMOVE",  \
-						e->adapter->adapter_nr, e));
-		return (0); /* let us do it in the driver */
+		DBG_ERR(("A: A(%d) E(%08x)  discard OK in REMOVE",
+			 e->adapter->adapter_nr, e));
+		return (0);	/* let us do it in the driver */
 	}
-	if ((e->e.Req == REMOVE) && (!e->e.Id)) { /* REMOVE COMPLETE */
+	if ((e->e.Req == REMOVE) && (!e->e.Id)) {	/* REMOVE COMPLETE */
 		e->e.callback = 0;
 		e->e.Id = 0;
 		e->e.Req = 0;
@@ -633,59 +671,64 @@
 		e->e.RcCh = 0;
 		e->e.Ind = 0;
 		e->e.IndCh = 0;
-		e->e.X		 = 0;
-		e->e.R		 = 0;
-		e->e.XNum	 = 0;
-		e->e.RNum	 = 0;
+		e->e.X = 0;
+		e->e.R = 0;
+		e->e.XNum = 0;
+		e->e.RNum = 0;
 		e->rc_count = 0;
 	}
-	if ((e->e.Req == REMOVE) && (rc != 0xff)) { /* REMOVE FAILED */
-		DBG_ERR(("A: A(%d) E(%08x)  REMOVE FAILED",  \
-						e->adapter->adapter_nr, e));
+	if ((e->e.Req == REMOVE) && (rc != 0xff)) {	/* REMOVE FAILED */
+		DBG_ERR(("A: A(%d) E(%08x)  REMOVE FAILED",
+			 e->adapter->adapter_nr, e));
 	}
-	write_return_code (e, rc);
+	write_return_code(e, rc);
 
 	return (1);
 }
 
-static int process_idi_ind (divas_um_idi_entity_t* e, byte ind) {
+static int process_idi_ind(divas_um_idi_entity_t * e, byte ind)
+{
 	int do_wakeup = 0;
 
 	if (e->e.complete != 0x02) {
-		diva_um_idi_ind_hdr_t* pind =
-					(diva_um_idi_ind_hdr_t*)diva_data_q_get_segment4write (&e->data);
+		diva_um_idi_ind_hdr_t *pind =
+		    (diva_um_idi_ind_hdr_t *)
+		    diva_data_q_get_segment4write(&e->data);
 		if (pind) {
-			e->e.RNum       = 1;
-			e->e.R->P			  = (byte*)&pind[1];
-			e->e.R->PLength = (word)(diva_data_q_get_max_length	(&e->data) -\
-												sizeof(*pind));
-			DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]", \
-							e->adapter->adapter_nr, e, \
-							e->e.Id, ind, e->e.IndCh, e->e.RLength, e->e.R->PLength));
+			e->e.RNum = 1;
+			e->e.R->P = (byte *) & pind[1];
+			e->e.R->PLength =
+			    (word) (diva_data_q_get_max_length(&e->data) -
+				    sizeof(*pind));
+			DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]",
+				 e->adapter->adapter_nr, e, e->e.Id, ind,
+				 e->e.IndCh, e->e.RLength,
+				 e->e.R->PLength));
 
 		} else {
-			DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR", \
-								e->adapter->adapter_nr, e, \
-								e->e.Id, ind, e->e.IndCh));
-			e->e.RNum	= 0;
-			e->e.RNR	= 1;
+			DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR",
+				 e->adapter->adapter_nr, e, e->e.Id, ind,
+				 e->e.IndCh));
+			e->e.RNum = 0;
+			e->e.RNR = 1;
 			do_wakeup = 1;
 		}
 	} else {
-		diva_um_idi_ind_hdr_t* pind =\
-										(diva_um_idi_ind_hdr_t*)(e->e.R->P);
+		diva_um_idi_ind_hdr_t *pind =
+		    (diva_um_idi_ind_hdr_t *) (e->e.R->P);
 
-		DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]", \
-							e->adapter->adapter_nr, e, \
-							e->e.Id, ind, e->e.IndCh, e->e.R->PLength));
+		DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]",
+			 e->adapter->adapter_nr, e, e->e.Id, ind,
+			 e->e.IndCh, e->e.R->PLength));
 
 		pind--;
-		pind->type					= DIVA_UM_IDI_IND;
-		pind->hdr.ind.Ind		= ind;
+		pind->type = DIVA_UM_IDI_IND;
+		pind->hdr.ind.Ind = ind;
 		pind->hdr.ind.IndCh = e->e.IndCh;
-		pind->data_length   = e->e.R->PLength;
-		diva_data_q_ack_segment4write	(&e->data,
-																	 (int)(sizeof(*pind)+e->e.R->PLength));
+		pind->data_length = e->e.R->PLength;
+		diva_data_q_ack_segment4write(&e->data,
+					      (int) (sizeof(*pind) +
+						     e->e.R->PLength));
 		do_wakeup = 1;
 	}
 
@@ -699,21 +742,25 @@
 /* --------------------------------------------------------------------------
 		Write return code to the return code queue of entity
 	 -------------------------------------------------------------------------- */
-static int	write_return_code (divas_um_idi_entity_t* e, byte rc) {
-	diva_um_idi_ind_hdr_t* prc;
+static int write_return_code(divas_um_idi_entity_t * e, byte rc)
+{
+	diva_um_idi_ind_hdr_t *prc;
 
-	if (!(prc = (diva_um_idi_ind_hdr_t*)diva_data_q_get_segment4write	(&e->rc))) {
-		DBG_ERR (("A: A(%d) E(%08x) rc(%02x) lost", e->adapter->adapter_nr, e, rc));
+	if (!(prc =
+	     (diva_um_idi_ind_hdr_t *) diva_data_q_get_segment4write(&e->rc)))
+	{
+		DBG_ERR(("A: A(%d) E(%08x) rc(%02x) lost",
+			 e->adapter->adapter_nr, e, rc));
 		e->status &= ~DIVA_UM_IDI_RC_PENDING;
 		return (-1);
 	}
 
-	prc->type				 = DIVA_UM_IDI_IND_RC;
-	prc->hdr.rc.Rc	 = rc;
+	prc->type = DIVA_UM_IDI_IND_RC;
+	prc->hdr.rc.Rc = rc;
 	prc->hdr.rc.RcCh = e->e.RcCh;
 	prc->data_length = 0;
-	diva_data_q_ack_segment4write	(&e->rc, sizeof(*prc));
-	
+	diva_data_q_ack_segment4write(&e->rc, sizeof(*prc));
+
 	return (0);
 }
 
@@ -721,31 +768,32 @@
 		Return amount of entries that can be bead from this entity or
 		-1 if adapter was removed
 	 -------------------------------------------------------------------------- */
-int diva_user_mode_idi_ind_ready (void* entity, void* os_handle) {
-	divas_um_idi_entity_t* e;
-	diva_um_idi_adapter_t* a;
-        diva_os_spin_lock_magic_t old_irql;
+int diva_user_mode_idi_ind_ready(void *entity, void *os_handle)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	diva_os_spin_lock_magic_t old_irql;
 	int ret;
 
-        if (!entity)
-          return(-1);
-        diva_os_enter_spin_lock (&adapter_lock, &old_irql, "ind_ready");
-	e = (divas_um_idi_entity_t*)entity;
+	if (!entity)
+		return (-1);
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "ind_ready");
+	e = (divas_um_idi_entity_t *) entity;
 	a = e->adapter;
 
 	if ((!a) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
 		/*
-			Adapter was unloaded
-			*/
-                diva_os_leave_spin_lock (&adapter_lock, &old_irql, "ind_ready");
-		return (-1); /* adapter was removed */
+		   Adapter was unloaded
+		 */
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
+		return (-1);	/* adapter was removed */
 	}
 	if (e->status & DIVA_UM_IDI_REMOVED) {
 		/*
-			entity was removed as result of adapter removal
-			user should assign this entity again
-			*/
-                diva_os_leave_spin_lock (&adapter_lock, &old_irql, "ind_ready");
+		   entity was removed as result of adapter removal
+		   user should assign this entity again
+		 */
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
 		return (-1);
 	}
 
@@ -755,91 +803,95 @@
 		ret = 0;
 	}
 
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "ind_ready");
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
 
 	return (ret);
 }
 
-void* diva_um_id_get_os_context (void* entity) {
-	return (((divas_um_idi_entity_t*)entity)->os_context);
+void *diva_um_id_get_os_context(void *entity)
+{
+	return (((divas_um_idi_entity_t *) entity)->os_context);
 }
 
-int divas_um_idi_entity_assigned (void* entity) {
-	divas_um_idi_entity_t* e;
-	diva_um_idi_adapter_t* a;
+int divas_um_idi_entity_assigned(void *entity)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
 	int ret;
-  diva_os_spin_lock_magic_t old_irql;
+	diva_os_spin_lock_magic_t old_irql;
 
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "assigned?");
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "assigned?");
 
 
-	e = (divas_um_idi_entity_t*)entity;
-  if (!e || (!(a = e->adapter)) ||
-      (e->status & DIVA_UM_IDI_REMOVED) ||
-      (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "assigned?");
-    return (0);
-  }
+	e = (divas_um_idi_entity_t *) entity;
+	if (!e || (!(a = e->adapter)) ||
+	    (e->status & DIVA_UM_IDI_REMOVED) ||
+	    (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
+		return (0);
+	}
 
 	e->status |= DIVA_UM_IDI_REMOVE_PENDING;
 
-  ret = (e->e.Id || e->rc_count || (e->status & DIVA_UM_IDI_ASSIGN_PENDING));
+	ret = (e->e.Id || e->rc_count
+	       || (e->status & DIVA_UM_IDI_ASSIGN_PENDING));
 
-	DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e->e.Id, e->rc_count, e->status))
+	DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e->e.Id, e->rc_count,
+		 e->status))
 
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "assigned?");
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
 
-  return (ret);
+	return (ret);
 }
 
-int divas_um_idi_entity_start_remove (void* entity) {
-	divas_um_idi_entity_t* e;
-	diva_um_idi_adapter_t* a;
-  diva_os_spin_lock_magic_t old_irql;
-
-  diva_os_enter_spin_lock (&adapter_lock, &old_irql, "start_remove");
-
-  e = (divas_um_idi_entity_t*)entity;
-  if (!e || (!(a = e->adapter)) ||
-      (e->status & DIVA_UM_IDI_REMOVED) ||
-      (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "start_remove");
-    return (0);
-  }
-
-  if (e->rc_count) {
-    /*
-       Entity BUSY
-      */
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "start_remove");
-    return (1);
-  }
-
-  if (!e->e.Id) {
-    /*
-       Remove request was already pending, and arrived now
-       */
-    diva_os_leave_spin_lock (&adapter_lock, &old_irql, "start_remove");
-    return (0); /* REMOVE was pending */
-  }
-
-  /*
-    Now send remove request
-    */
-  e->e.Req	 = REMOVE;
-  e->e.ReqCh = 0;
-
-  e->rc_count++;
-
-  DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))", \
-           e->adapter->adapter_nr, e, \
-           e->e.Id, e->e.Req, e->e.ReqCh, e->e.X->PLength));
+int divas_um_idi_entity_start_remove(void *entity)
+{
+	divas_um_idi_entity_t *e;
+	diva_um_idi_adapter_t *a;
+	diva_os_spin_lock_magic_t old_irql;
+
+	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "start_remove");
 
-  if (a->d.request)
-    (*(a->d.request))(&e->e);
+	e = (divas_um_idi_entity_t *) entity;
+	if (!e || (!(a = e->adapter)) ||
+	    (e->status & DIVA_UM_IDI_REMOVED) ||
+	    (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
+		return (0);
+	}
 
-  diva_os_leave_spin_lock (&adapter_lock, &old_irql, "start_remove");
+	if (e->rc_count) {
+		/*
+		   Entity BUSY
+		 */
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
+		return (1);
+	}
+
+	if (!e->e.Id) {
+		/*
+		   Remove request was already pending, and arrived now
+		 */
+		diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
+		return (0);	/* REMOVE was pending */
+	}
+
+	/*
+	   Now send remove request
+	 */
+	e->e.Req = REMOVE;
+	e->e.ReqCh = 0;
+
+	e->rc_count++;
+
+	DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
+		 e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
+		 e->e.ReqCh, e->e.X->PLength));
+
+	if (a->d.request)
+		(*(a->d.request)) (&e->e);
+
+	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
 
 	return (0);
 }
-
diff -Nru a/drivers/isdn/hardware/eicon/um_idi.h b/drivers/isdn/hardware/eicon/um_idi.h
--- a/drivers/isdn/hardware/eicon/um_idi.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/isdn/hardware/eicon/um_idi.h	Sun Nov 17 20:30:13 2002
@@ -7,40 +7,38 @@
 /*
   interface between UM IDI core and OS dependent part
   */
-int diva_user_mode_idi_init (void);
-void diva_user_mode_idi_finit (void);
-int diva_um_idi_nr_of_adapters (void);
-void* divas_um_idi_create_entity (dword adapter_nr, void* file);
-int divas_um_idi_delete_entity (int adapter_nr, void* entity);
+int diva_user_mode_idi_init(void);
+void diva_user_mode_idi_finit(void);
+int diva_um_idi_nr_of_adapters(void);
+void *divas_um_idi_create_entity(dword adapter_nr, void *file);
+int divas_um_idi_delete_entity(int adapter_nr, void *entity);
 
-typedef int (*divas_um_idi_copy_to_user_fn_t)(void* os_handle,
-                                              void* dst,
-                                              const void* src,
-                                              int length);
-typedef int (*divas_um_idi_copy_from_user_fn_t)(void* os_handle,
-                                                void* dst,
-                                                const void* src,
-                                                int length);
+typedef int (*divas_um_idi_copy_to_user_fn_t) (void *os_handle,
+					       void *dst,
+					       const void *src,
+					       int length);
+typedef int (*divas_um_idi_copy_from_user_fn_t) (void *os_handle,
+						 void *dst,
+						 const void *src,
+						 int length);
 
-int diva_um_idi_read (void* entity,
-                      void* os_handle,
-                      void* dst,
-                      int max_length,
-                      divas_um_idi_copy_to_user_fn_t cp_fn);
+int diva_um_idi_read(void *entity,
+		     void *os_handle,
+		     void *dst,
+		     int max_length, divas_um_idi_copy_to_user_fn_t cp_fn);
 
-int diva_um_idi_write (void* entity,
-                       void* os_handle,
-                       const void* src,
-                       int length,
-                       divas_um_idi_copy_from_user_fn_t cp_fn);
+int diva_um_idi_write(void *entity,
+		      void *os_handle,
+		      const void *src,
+		      int length, divas_um_idi_copy_from_user_fn_t cp_fn);
 
-int diva_user_mode_idi_ind_ready (void* entity, void* os_handle);
-void* diva_um_id_get_os_context (void* entity);
-int diva_os_get_context_size (void);
-int divas_um_idi_entity_assigned (void* entity);
-int divas_um_idi_entity_start_remove (void* entity);
+int diva_user_mode_idi_ind_ready(void *entity, void *os_handle);
+void *diva_um_id_get_os_context(void *entity);
+int diva_os_get_context_size(void);
+int divas_um_idi_entity_assigned(void *entity);
+int divas_um_idi_entity_start_remove(void *entity);
 
-void diva_um_idi_start_wdog (void* entity);
-void diva_um_idi_stop_wdog (void* entity);
+void diva_um_idi_start_wdog(void *entity);
+void diva_um_idi_stop_wdog(void *entity);
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/um_xdi.h b/drivers/isdn/hardware/eicon/um_xdi.h
--- a/drivers/isdn/hardware/eicon/um_xdi.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hardware/eicon/um_xdi.h	Sun Nov 17 20:30:15 2002
@@ -9,11 +9,11 @@
 */
 
 typedef struct _diva_um_idi_adapter_features {
-  dword type;
-  dword features;
-  dword channels;
-  dword serial_number;
-  char  name [128];
+	dword type;
+	dword features;
+	dword channels;
+	dword serial_number;
+	char name[128];
 } diva_um_idi_adapter_features_t;
 
 #define DIVA_UM_IDI_REQ_MASK			0x0000FFFF
@@ -30,29 +30,29 @@
   data_length  bytes will follow this structure
 */
 typedef struct _diva_um_idi_req_hdr {
-  dword type;
-  dword Req;
-  dword ReqCh;
-  dword data_length;
+	dword type;
+	dword Req;
+	dword ReqCh;
+	dword data_length;
 } diva_um_idi_req_hdr_t;
 
 typedef struct _diva_um_idi_ind_parameters {
-  dword Ind;
-  dword IndCh;
+	dword Ind;
+	dword IndCh;
 } diva_um_idi_ind_parameters_t;
 
 typedef struct _diva_um_idi_rc_parameters {
-  dword Rc;
-  dword RcCh;
+	dword Rc;
+	dword RcCh;
 } diva_um_idi_rc_parameters_t;
 
 typedef union _diva_um_idi_ind {
-  diva_um_idi_adapter_features_t  features;
-  diva_um_idi_ind_parameters_t    ind;
-  diva_um_idi_rc_parameters_t     rc;
+	diva_um_idi_adapter_features_t features;
+	diva_um_idi_ind_parameters_t ind;
+	diva_um_idi_rc_parameters_t rc;
 } diva_um_idi_ind_t;
 
-#define DIVA_UM_IDI_IND_FEATURES  1  /* features indication */
+#define DIVA_UM_IDI_IND_FEATURES  1	/* features indication */
 #define DIVA_UM_IDI_IND           2
 #define DIVA_UM_IDI_IND_RC        3
 /*
@@ -60,10 +60,9 @@
   this structure
 */
 typedef struct _diva_um_idi_ind_hdr {
-  dword type;
-  diva_um_idi_ind_t  hdr;
-  dword  data_length;
+	dword type;
+	diva_um_idi_ind_t hdr;
+	dword data_length;
 } diva_um_idi_ind_hdr_t;
 
 #endif
-
diff -Nru a/drivers/isdn/hardware/eicon/xdi_adapter.h b/drivers/isdn/hardware/eicon/xdi_adapter.h
--- a/drivers/isdn/hardware/eicon/xdi_adapter.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/hardware/eicon/xdi_adapter.h	Sun Nov 17 20:30:14 2002
@@ -1,4 +1,4 @@
-/* $Id: xdi_adapter.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: xdi_adapter.h,v 1.1.2.3 2001/02/16 08:40:36 armin Exp $ */
 
 #ifndef __DIVA_OS_XDI_ADAPTER_H__
 #define __DIVA_OS_XDI_ADAPTER_H__
@@ -7,15 +7,15 @@
 #define DIVAS_XDI_ADAPTER_BUS_ISA  1
 
 typedef struct _divas_pci_card_resources {
-	byte	bus;
-	byte	func;
-	void* hdev;
-
-	dword bar[8]; /* contains context of appropriate BAR Register */
-	void* addr[8]; /* same bar, but mapped into memory */
-	dword length[8]; /* bar length */
+	byte bus;
+	byte func;
+	void *hdev;
+
+	dword bar[8];		/* contains context of appropriate BAR Register */
+	void *addr[8];		/* same bar, but mapped into memory */
+	dword length[8];	/* bar length */
 
-	byte   irq;
+	byte irq;
 } divas_pci_card_resources_t;
 
 typedef union _divas_card_resources {
@@ -23,45 +23,47 @@
 } divas_card_resources_t;
 
 struct _diva_os_xdi_adapter;
-typedef int (*diva_init_card_proc_t)(struct _diva_os_xdi_adapter* a);
-typedef int (*diva_cmd_card_proc_t)(struct _diva_os_xdi_adapter* a,
-                                    diva_xdi_um_cfg_cmd_t* data, int length);
-typedef void (*diva_xdi_clear_interrupts_proc_t)(struct _diva_os_xdi_adapter*);
+typedef int (*diva_init_card_proc_t) (struct _diva_os_xdi_adapter * a);
+typedef int (*diva_cmd_card_proc_t) (struct _diva_os_xdi_adapter * a,
+				     diva_xdi_um_cfg_cmd_t * data,
+				     int length);
+typedef void (*diva_xdi_clear_interrupts_proc_t) (struct
+						  _diva_os_xdi_adapter *);
 
 #define DIVA_XDI_MBOX_BUSY			1
 #define DIVA_XDI_MBOX_WAIT_XLOG	2
 
 typedef struct _xdi_mbox_t {
-  dword  status;
-  diva_xdi_um_cfg_cmd_data_t cmd_data;
-  dword  data_length;
-  void  *data;
+	dword status;
+	diva_xdi_um_cfg_cmd_data_t cmd_data;
+	dword data_length;
+	void *data;
 } xdi_mbox_t;
 
 typedef struct _diva_os_idi_adapter_interface {
-	diva_init_card_proc_t	cleanup_adapter_proc;
-	diva_cmd_card_proc_t	cmd_proc;
+	diva_init_card_proc_t cleanup_adapter_proc;
+	diva_cmd_card_proc_t cmd_proc;
 } diva_os_idi_adapter_interface_t;
 
 typedef struct _diva_os_xdi_adapter {
-  diva_entity_link_t  link;
-  int  CardIndex;
-  int  CardOrdinal;
-  int  controller; /* number of this controller */
-  int  Bus; /* PCI, ISA, ... */
-  divas_card_resources_t  resources;
-  char  port_name[24];
-  ISDN_ADAPTER  xdi_adapter;
-  xdi_mbox_t  xdi_mbox;
-  diva_os_idi_adapter_interface_t  interface;
-  struct _diva_os_xdi_adapter*  slave_adapters[3];
-  void*  slave_list;
-  void*  proc_adapter_dir;  /* adapterX proc entry */
-  void*  proc_info;         /* info proc entry     */
-  void*  proc_grp_opt;      /* group_optimization  */
-  void*  proc_d_l1_down;    /* dynamic_l1_down     */
-  volatile diva_xdi_clear_interrupts_proc_t clear_interrupts_proc;
-  dword dsp_mask;
+	diva_entity_link_t link;
+	int CardIndex;
+	int CardOrdinal;
+	int controller;		/* number of this controller */
+	int Bus;		/* PCI, ISA, ... */
+	divas_card_resources_t resources;
+	char port_name[24];
+	ISDN_ADAPTER xdi_adapter;
+	xdi_mbox_t xdi_mbox;
+	diva_os_idi_adapter_interface_t interface;
+	struct _diva_os_xdi_adapter *slave_adapters[3];
+	void *slave_list;
+	void *proc_adapter_dir;	/* adapterX proc entry */
+	void *proc_info;	/* info proc entry     */
+	void *proc_grp_opt;	/* group_optimization  */
+	void *proc_d_l1_down;	/* dynamic_l1_down     */
+	volatile diva_xdi_clear_interrupts_proc_t clear_interrupts_proc;
+	dword dsp_mask;
 } diva_os_xdi_adapter_t;
 
 #endif
diff -Nru a/drivers/isdn/hardware/eicon/xdi_msg.h b/drivers/isdn/hardware/eicon/xdi_msg.h
--- a/drivers/isdn/hardware/eicon/xdi_msg.h	Sun Nov 17 20:30:04 2002
+++ b/drivers/isdn/hardware/eicon/xdi_msg.h	Sun Nov 17 20:30:04 2002
@@ -1,4 +1,4 @@
-/* $Id: xdi_msg.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
+/* $Id: xdi_msg.h,v 1.1.2.2 2001/02/16 08:40:36 armin Exp $ */
 
 #ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__
 #define __DIVA_XDI_UM_CFG_MESSAGE_H__
@@ -93,36 +93,35 @@
 } diva_xdi_um_cfg_cmd_data_start_t;
 
 typedef struct _diva_xdi_um_cfg_cmd_data_write_sdram {
-	dword	ram_number;
-	dword	offset;
-	dword	length;
+	dword ram_number;
+	dword offset;
+	dword length;
 } diva_xdi_um_cfg_cmd_data_write_sdram_t;
 
 typedef struct _diva_xdi_um_cfg_cmd_data_write_fpga {
-	dword	fpga_number;
-	dword	image_length;
+	dword fpga_number;
+	dword image_length;
 } diva_xdi_um_cfg_cmd_data_write_fpga_t;
 
 typedef struct _diva_xdi_um_cfg_cmd_data_read_sdram {
-	dword	ram_number;
-	dword	offset;
-	dword	length;
+	dword ram_number;
+	dword offset;
+	dword length;
 } diva_xdi_um_cfg_cmd_data_read_sdram_t;
 
 typedef union _diva_xdi_um_cfg_cmd_data {
-	diva_xdi_um_cfg_cmd_data_write_sdram_t	write_sdram;
-	diva_xdi_um_cfg_cmd_data_write_fpga_t	write_fpga;
-	diva_xdi_um_cfg_cmd_data_read_sdram_t	read_sdram;
-	diva_xdi_um_cfg_cmd_data_start_t	start;
-  diva_xdi_um_cfg_cmd_data_set_features_t features;
+	diva_xdi_um_cfg_cmd_data_write_sdram_t write_sdram;
+	diva_xdi_um_cfg_cmd_data_write_fpga_t write_fpga;
+	diva_xdi_um_cfg_cmd_data_read_sdram_t read_sdram;
+	diva_xdi_um_cfg_cmd_data_start_t start;
+	diva_xdi_um_cfg_cmd_data_set_features_t features;
 } diva_xdi_um_cfg_cmd_data_t;
 
 typedef struct _diva_xdi_um_cfg_cmd {
-  dword  adapter; /* Adapter number 1...N */
-  dword  command;
-  diva_xdi_um_cfg_cmd_data_t  command_data;
-  dword  data_length; /* Plain binary data will follow */
+	dword adapter;		/* Adapter number 1...N */
+	dword command;
+	diva_xdi_um_cfg_cmd_data_t command_data;
+	dword data_length;	/* Plain binary data will follow */
 } diva_xdi_um_cfg_cmd_t;
 
 #endif
-
diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
--- a/drivers/isdn/hisax/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/isdn/hisax/Kconfig	Sun Nov 17 20:30:15 2002
@@ -1,10 +1,9 @@
 
 menu "Passive cards"
-	depends on NET && ISDN_BOOL && ISDN!=n
+	depends on ISDN
 
 config ISDN_DRV_HISAX
 	tristate "HiSax SiemensChipSet driver support"
-	depends on ISDN
 	---help---
 	  This is a driver supporting the Siemens chipset on various
 	  ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, Teles
@@ -17,12 +16,12 @@
 	  also to the configuration option of the driver for your particular
 	  card, below.
 
+if ISDN_DRV_HISAX!=n
+
 comment "D-channel protocol features"
-	depends on ISDN_DRV_HISAX
 
 config HISAX_EURO
 	bool "HiSax Support for EURO/DSS1"
-	depends on ISDN_DRV_HISAX
 	help
 	  Say Y or N according to the D-channel protocol which your local
 	  telephone service company provides.
@@ -64,7 +63,6 @@
 
 config HISAX_1TR6
 	bool "HiSax Support for german 1TR6"
-	depends on ISDN_DRV_HISAX
 	help
 	  Say Y or N according to the D-channel protocol which your local
 	  telephone service company provides.
@@ -75,25 +73,22 @@
 
 config HISAX_NI1
 	bool "HiSax Support for US NI1"
-	depends on ISDN_DRV_HISAX
 	help
 	  Enable this if you like to use ISDN in US on a NI1 basic rate
 	  interface.
 
 config HISAX_MAX_CARDS
 	int "Maximum number of cards supported by HiSax"
-	depends on ISDN_DRV_HISAX
 	default "8"
 	help
 	  This option allows you to specify the maximum number of cards which
 	  the HiSax driver will be able to handle.  
 
 comment "HiSax supported cards"
-	depends on ISDN_DRV_HISAX
 
 config HISAX_16_0
 	bool "Teles 16.0/8.0"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
 	  and many compatibles.
@@ -104,7 +99,6 @@
 
 config HISAX_16_3
 	bool "Teles 16.3 or PNP or PCMCIA"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Teles ISDN-cards S0-16.3 the
 	  Teles/Creatix PnP and the Teles PCMCIA.
@@ -115,14 +109,12 @@
 
 config HISAX_TELESPCI
 	bool "Teles PCI"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Teles PCI.
 	  See <file:Documentation/isdn/README.HiSax> on how to configure it.
 
 config HISAX_S0BOX
 	bool "Teles S0Box"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Teles/Creatix parallel port
 	  S0BOX.  See <file:Documentation/isdn/README.HiSax> on how to
@@ -130,7 +122,7 @@
 
 config HISAX_AVM_A1
 	bool "AVM A1 (Fritz)"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the AVM A1 (aka "Fritz").
 
@@ -140,21 +132,18 @@
 
 config HISAX_FRITZPCI
 	bool "AVM PnP/PCI (Fritz!PnP/PCI)"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
 	  See <file:Documentation/isdn/README.HiSax> on how to configure it.
 
 config HISAX_AVM_A1_PCMCIA
 	bool "AVM A1 PCMCIA (Fritz)"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
 	  See <file:Documentation/isdn/README.HiSax> on how to configure it.
 
 config HISAX_ELSA
 	bool "Elsa cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Elsa Mircolink ISA cards, for the
 	  Elsa Quickstep series cards and Elsa PCMCIA.
@@ -165,7 +154,7 @@
 
 config HISAX_IX1MICROR2
 	bool "ITK ix1-micro Revision 2"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the ITK ix1-micro Revision 2 card.
 
@@ -175,7 +164,6 @@
 
 config HISAX_DIEHLDIVA
 	bool "Eicon.Diehl Diva cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Eicon.Diehl Diva none PRO
 	  versions passive ISDN cards.
@@ -186,7 +174,7 @@
 
 config HISAX_ASUSCOM
 	bool "ASUSCOM ISA cards"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the AsusCom and their OEM versions
 	  passive ISDN ISA cards.
@@ -197,7 +185,7 @@
 
 config HISAX_TELEINT
 	bool "TELEINT cards"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
 
@@ -207,7 +195,7 @@
 
 config HISAX_HFCS
 	bool "HFC-S based cards"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the HFC-S 2BDS0 based cards, like
 	  teles 16.3c.
@@ -218,7 +206,6 @@
 
 config HISAX_SEDLBAUER
 	bool "Sedlbauer cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Sedlbauer passive ISDN cards.
 
@@ -228,7 +215,7 @@
 
 config HISAX_SPORTSTER
 	bool "USR Sportster internal TA"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the USR Sportster internal TA card.
 
@@ -238,7 +225,7 @@
 
 config HISAX_MIC
 	bool "MIC card"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the ITH MIC card.
 
@@ -248,7 +235,6 @@
 
 config HISAX_NETJET
 	bool "NETjet card"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the NetJet from Traverse
 	  Technologies.
@@ -259,7 +245,6 @@
 
 config HISAX_NETJET_U
 	bool "NETspider U card"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Netspider U interface ISDN card
 	  from Traverse Technologies.
@@ -269,7 +254,6 @@
 
 config HISAX_NICCY
 	bool "Niccy PnP/PCI card"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI.
 
@@ -279,7 +263,7 @@
 
 config HISAX_ISURF
 	bool "Siemens I-Surf card"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the Siemens I-Talk/I-Surf card with
 	  ISAR chip.
@@ -289,7 +273,7 @@
 
 config HISAX_HSTSAPHIR
 	bool "HST Saphir card"
-	depends on ISDN_DRV_HISAX && ISA
+	depends on ISA
 	help
 	  This enables HiSax support for the HST Saphir card.
 
@@ -299,7 +283,6 @@
 
 config HISAX_BKM_A4T
 	bool "Telekom A4T card"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Telekom A4T card.
 
@@ -309,7 +292,6 @@
 
 config HISAX_SCT_QUADRO
 	bool "Scitel Quadro card"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Scitel Quadro card.
 
@@ -319,7 +301,6 @@
 
 config HISAX_GAZEL
 	bool "Gazel cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the Gazel cards.
 
@@ -329,7 +310,6 @@
 
 config HISAX_HFC_PCI
 	bool "HFC PCI-Bus cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
 
@@ -338,7 +318,6 @@
 
 config HISAX_W6692
 	bool "Winbond W6692 based cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for Winbond W6692 based PCI ISDN cards.
 
@@ -348,26 +327,32 @@
 
 config HISAX_HFC_SX
 	bool "HFC-S+, HFC-SP, HFC-PCMCIA cards"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA
 	  cards. This code is not finished yet.
 
 #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+
 config HISAX_ENTERNOW_PCI
 	bool "Formula-n enter:now PCI card (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && EXPERIMENTAL
+	depends on EXPERIMENTAL
+	help
+	  This enables HiSax support for the Formula-n enter:now PCI
+	  ISDN card.
 
 config HISAX_AMD7930
 	bool "Am7930 (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && EXPERIMENTAL && (SPARC32 || SPARC64)
+	depends on EXPERIMENTAL && (SPARC32 || SPARC64)
 	help
 	  This enables HiSax support for the AMD7930 chips on some SPARCs.
 	  This code is not finished yet.
 
+endif
+
+if ISDN_DRV_HISAX
+
 config HISAX_DEBUG
 	bool "HiSax debugging"
-	depends on ISDN_DRV_HISAX
 	help
 	  This enables debugging code in the new-style HiSax drivers, i.e.
 	  the ST5481 USB driver currently. 
@@ -375,51 +360,55 @@
 
 config HISAX_SEDLBAUER_CS
 	tristate "Sedlbauer PCMCIA cards"
-	depends on ISDN_DRV_HISAX && PCMCIA
+	depends on PCMCIA
 	help
 	  This enables the PCMCIA client driver for the Sedlbauer Speed Star
 	  and Speed Star II cards.
 
 config HISAX_ELSA_CS
 	tristate "ELSA PCMCIA MicroLink cards"
-	depends on ISDN_DRV_HISAX && PCMCIA
+	depends on PCMCIA
 	help
 	  This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink
 	  card.
 
 config HISAX_AVM_A1_CS
 	tristate "AVM A1 PCMCIA cards"
-	depends on ISDN_DRV_HISAX && PCMCIA
+	depends on PCMCIA
 	help
 	  This enables the PCMCIA client driver for the AVM A1 / Fritz!Card
 	  PCMCIA cards.
 
 config HISAX_ST5481
 	tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && USB && EXPERIMENTAL
+	depends on USB && EXPERIMENTAL
 	help
 	  This enables the driver for ST5481 based USB ISDN adapters,
 	  e.g. the BeWan Gazel 128 USB
 
 config HISAX_FRITZ_PCIPNP
 	tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
-	  This enables the driver for the AVM Fritz!Card PCI, Fritz!Card PCI v2 
-	  and Fritz!Card PnP.
+	  This enables the driver for the AVM Fritz!Card PCI,
+	  Fritz!Card PCI v2 and Fritz!Card PnP.
 	  (the latter also needs you to select "ISA Plug and Play support"
 	  from the menu "Plug and Play configuration")
 
 config HISAX_FRITZ_CLASSIC
 	tristate "AVM Fritz!Card classic support (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  This enables the driver for the AVM Fritz!Card classic, formerly
 	  known as AVM A1.
 
 config HISAX_HFCPCI
 	tristate "HFC PCI support (EXPERIMENTAL)"
-	depends on ISDN_DRV_HISAX && EXPERIMENTAL
+	depends on EXPERIMENTAL
+	help
+	  This enables the driver for CCD HFC PCI based cards.
+
+endif
 
 endmenu
 
diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
--- a/drivers/isdn/i4l/Kconfig	Sun Nov 17 20:30:12 2002
+++ b/drivers/isdn/i4l/Kconfig	Sun Nov 17 20:30:12 2002
@@ -1,9 +1,29 @@
 #
 # Old ISDN4Linux config
 #
+
+config ISDN_NET_SIMPLE
+	bool '  Support raw-IP and other simple protocols'
+	depends on INET
+	help
+	  This options enables 'raw IP over ISDN', 'ethernet over ISDN',
+	  'raw IP with UI header' and 'IP + type field' encapsulations.
+	  
+	  If you never heard of any of those, you probably want to say N.
+
+config ISDN_NET_CISCO
+	bool '  Support CISCO router protocols'
+	depends on INET
+	help
+	  This options enables 'CISCO HDLC' encapsulation with
+	  optional support for CISCO keep-alive frames.
+	  
+	  Unless you want to connect to a Cisco Router in HDLC mode,
+	  you probably want to say N.
+
 config ISDN_PPP
 	bool "Support synchronous PPP"
-	depends on ISDN && INET
+	depends on INET
 	help
 	  Over digital connections such as ISDN, there is no need to
 	  synchronize sender and recipient's clocks with start and stop bits
@@ -32,7 +52,7 @@
 
 config ISDN_PPP_BSDCOMP
 	tristate "Support BSD compression"
-	depends on ISDN_PPP && ISDN
+	depends on ISDN_PPP
 	help
 	  Support for the BSD-Compress compression method for PPP, which uses
 	  the LZW compression method to compress each PPP packet before it is
@@ -43,7 +63,6 @@
 
 config ISDN_AUDIO
 	bool "Support audio via ISDN"
-	depends on ISDN
 	help
 	  If you say Y here, the modem-emulator will support a subset of the
 	  EIA Class 8 Voice commands. Using a getty with voice-support
@@ -66,7 +85,7 @@
 
 config ISDN_X25
 	bool "X.25 PLP on top of ISDN"
-	depends on ISDN && X25
+	depends on X25
 	help
 	  This feature provides the X.25 protocol over ISDN connections.
 	  See <file:Documentation/isdn/README.x25> for more information
@@ -74,11 +93,10 @@
 
 
 menu "ISDN feature submodules"
-	depends on ISDN!=n
+	depends on ISDN
 
 config ISDN_DRV_LOOP
 	tristate "isdnloop support"
-	depends on ISDN
 	help
 	  This driver provides a virtual ISDN card. Its primary purpose is
 	  testing of linklevel features or configuration without getting
@@ -88,8 +106,7 @@
 
 config ISDN_DIVERSION
 	tristate "Support isdn diversion services"
-	depends on ISDN
-	---help---
+	help
 	  This option allows you to use some supplementary diversion
 	  services in conjunction with the HiSax driver on an EURO/DSS1
 	  line.
@@ -106,4 +123,3 @@
 	  Please read the file <file:Documentation/isdn/README.diversion>.
 
 endmenu
-
diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c
--- a/drivers/isdn/i4l/isdn_net_lib.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/isdn/i4l/isdn_net_lib.c	Sun Nov 17 20:30:02 2002
@@ -490,7 +490,7 @@
 	isdn_net_set_encap(mlp, -1);
 	isdn_net_rmallphone(idev);
 
-	if (idev->exclusive >= 0)
+	if (idev->exclusive)
 		isdn_slot_free(idev->exclusive);
 
 	list_del(&idev->slaves);
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/isdn/i4l/isdn_ppp.c	Sun Nov 17 20:30:14 2002
@@ -138,9 +138,9 @@
 	init_waitqueue_head(&ipppd->wq);
 	skb_queue_head_init(&ipppd->rq);
 
-	spin_lock_irqsave(&ipppds, flags);
+	spin_lock_irqsave(&ipppds_lock, flags);
 	list_add(&ipppd->ipppds, &ipppds);
-	spin_unlock_irqrestore(&ipppds, flags);
+	spin_unlock_irqrestore(&ipppds_lock, flags);
 	
 	ipppd_debug(ipppd, "minor %d", minor);
 
@@ -160,9 +160,9 @@
 	if (ipppd->state == IPPPD_ST_CONNECTED)
 		isdn_net_hangup(ipppd->idev);
 
-	spin_lock_irqsave(&ipppds, flags);
+	spin_lock_irqsave(&ipppds_lock, flags);
 	list_del(&ipppd->ipppds);
-	spin_unlock_irqrestore(&ipppds, flags);
+	spin_unlock_irqrestore(&ipppds_lock, flags);
 
 	ipppd_put(ipppd);
 
@@ -676,7 +676,7 @@
 		return -ENOMEM;
 
 	spin_lock_irqsave(&ipppds_lock, flags);
-	if (idev->pppbind < 0) {  /* device bound to ippp device ? */
+	if (idev->pppbind < 0) {  /* device not bound to ippp device ? */
 		struct list_head *l;
 		char exclusive[ISDN_MAX_CHANNELS];	/* exclusive flags */
 		memset(exclusive, 0, ISDN_MAX_CHANNELS);
@@ -695,8 +695,7 @@
 			if (ipppd->state != IPPPD_ST_OPEN)
 				continue;
 			if (!exclusive[ipppd->minor])
-				break;
-			goto found;
+				goto found;
 		}
 	} else {
 		list_for_each_entry(ipppd, &ipppds, ipppds) {
diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
--- a/drivers/macintosh/adb.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/macintosh/adb.c	Sun Nov 17 20:30:16 2002
@@ -837,11 +837,11 @@
 }
 
 static struct file_operations adb_fops = {
-	llseek:		no_llseek,
-	read:		adb_read,
-	write:		adb_write,
-	open:		adb_open,
-	release:	adb_release,
+	.llseek		= no_llseek,
+	.read		= adb_read,
+	.write		= adb_write,
+	.open		= adb_open,
+	.release	= adb_release,
 };
 
 static void
diff -Nru a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
--- a/drivers/macintosh/adbhid.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/macintosh/adbhid.c	Sun Nov 17 20:30:16 2002
@@ -55,7 +55,7 @@
 
 static int adb_message_handler(struct notifier_block *, unsigned long, void *);
 static struct notifier_block adbhid_adb_notifier = {
-	notifier_call:	adb_message_handler,
+	.notifier_call	= adb_message_handler,
 };
 
 unsigned char adb_to_linux_keycodes[128] = {
diff -Nru a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
--- a/drivers/macintosh/ans-lcd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/macintosh/ans-lcd.c	Sun Nov 17 20:30:15 2002
@@ -120,9 +120,9 @@
 }
 
 struct file_operations anslcd_fops = {
-	write:	anslcd_write,
-	ioctl:	anslcd_ioctl,
-	open:	anslcd_open,
+	.write	= anslcd_write,
+	.ioctl	= anslcd_ioctl,
+	.open	= anslcd_open,
 };
 
 static struct miscdevice anslcd_dev = {
diff -Nru a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
--- a/drivers/macintosh/apm_emu.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/macintosh/apm_emu.c	Sun Nov 17 20:30:15 2002
@@ -499,12 +499,12 @@
 }
 
 static struct file_operations apm_bios_fops = {
-	owner:		THIS_MODULE,
-	read:		do_read,
-	poll:		do_poll,
-	ioctl:		do_ioctl,
-	open:		do_open,
-	release:	do_release,
+	.owner		= THIS_MODULE,
+	.read		= do_read,
+	.poll		= do_poll,
+	.ioctl		= do_ioctl,
+	.open		= do_open,
+	.release	= do_release,
 };
 
 static struct miscdevice apm_device = {
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/macintosh/macserial.c	Sun Nov 17 20:30:15 2002
@@ -3032,12 +3032,12 @@
 }
 
 static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name		= "ttyS",
+	.write		= serial_console_write,
+	.device		= serial_console_device,
+	.setup		= serial_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
 };
 
 /*
diff -Nru a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
--- a/drivers/macintosh/mediabay.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/macintosh/mediabay.c	Sun Nov 17 20:30:12 2002
@@ -706,30 +706,30 @@
 /* Definitions of "ops" structures.
  */
 static struct mb_ops ohare_mb_ops __pmacdata = {
-	name:		"Ohare",
-	content:	ohare_mb_content,
-	power:		ohare_mb_power,
-	setup_bus:	ohare_mb_setup_bus,
-	un_reset:	ohare_mb_un_reset,
-	un_reset_ide:	ohare_mb_un_reset_ide,
+	.name		= "Ohare",
+	.content	= ohare_mb_content,
+	.power		= ohare_mb_power,
+	.setup_bus	= ohare_mb_setup_bus,
+	.un_reset	= ohare_mb_un_reset,
+	.un_reset_ide	= ohare_mb_un_reset_ide,
 };
 
 static struct mb_ops heathrow_mb_ops __pmacdata = {
-	name:		"Heathrow",
-	content:	heathrow_mb_content,
-	power:		heathrow_mb_power,
-	setup_bus:	heathrow_mb_setup_bus,
-	un_reset:	heathrow_mb_un_reset,
-	un_reset_ide:	heathrow_mb_un_reset_ide,
+	.name		= "Heathrow",
+	.content	= heathrow_mb_content,
+	.power		= heathrow_mb_power,
+	.setup_bus	= heathrow_mb_setup_bus,
+	.un_reset	= heathrow_mb_un_reset,
+	.un_reset_ide	= heathrow_mb_un_reset_ide,
 };
 
 static struct mb_ops keylargo_mb_ops __pmacdata = {
-	name:		"KeyLargo",
-	content:	keylargo_mb_content,
-	power:		keylargo_mb_power,
-	setup_bus:	keylargo_mb_setup_bus,
-	un_reset:	keylargo_mb_un_reset,
-	un_reset_ide:	keylargo_mb_un_reset_ide,
+	.name		= "KeyLargo",
+	.content	= keylargo_mb_content,
+	.power		= keylargo_mb_power,
+	.setup_bus	= keylargo_mb_setup_bus,
+	.un_reset	= keylargo_mb_un_reset,
+	.un_reset_ide	= keylargo_mb_un_reset_ide,
 };
 
 /*
diff -Nru a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
--- a/drivers/macintosh/nvram.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/macintosh/nvram.c	Sun Nov 17 20:30:03 2002
@@ -101,11 +101,11 @@
 }
 
 struct file_operations nvram_fops = {
-	owner:		THIS_MODULE,
-	llseek:		nvram_llseek,
-	read:		read_nvram,
-	write:		write_nvram,
-	ioctl:		nvram_ioctl,
+	.owner		= THIS_MODULE,
+	.llseek		= nvram_llseek,
+	.read		= read_nvram,
+	.write		= write_nvram,
+	.ioctl		= nvram_ioctl,
 };
 
 static struct miscdevice nvram_dev = {
diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
--- a/drivers/macintosh/via-pmu.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/macintosh/via-pmu.c	Sun Nov 17 20:30:15 2002
@@ -2688,12 +2688,12 @@
 }
 
 static struct file_operations pmu_device_fops = {
-	read:		pmu_read,
-	write:		pmu_write,
-	poll:		pmu_fpoll,
-	ioctl:		pmu_ioctl,
-	open:		pmu_open,
-	release:	pmu_release,
+	.read		= pmu_read,
+	.write		= pmu_write,
+	.poll		= pmu_fpoll,
+	.ioctl		= pmu_ioctl,
+	.open		= pmu_open,
+	.release	= pmu_release,
 };
 
 static struct miscdevice pmu_device = {
diff -Nru a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
--- a/drivers/macintosh/via-pmu68k.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/macintosh/via-pmu68k.c	Sun Nov 17 20:30:03 2002
@@ -1040,10 +1040,10 @@
 }
 
 static struct file_operations pmu_device_fops = {
-	read:		pmu_read,
-	write:		pmu_write,
-	ioctl:		pmu_ioctl,
-	open:		pmu_open,
+	.read		= pmu_read,
+	.write		= pmu_write,
+	.ioctl		= pmu_ioctl,
+	.open		= pmu_open,
 };
 
 static struct miscdevice pmu_device = {
diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
--- a/drivers/md/dm-ioctl.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/md/dm-ioctl.c	Sun Nov 17 20:30:12 2002
@@ -176,10 +176,10 @@
  */
 static int register_with_devfs(struct hash_cell *hc)
 {
-	kdev_t dev = dm_kdev(hc->md);
+	struct gendisk *disk = dm_disk(hc->md);
 	hc->devfs_entry =
 	    devfs_register(_dev_dir, hc->name, DEVFS_FL_CURRENT_OWNER,
-			   major(dev), minor(dev),
+			   disk->major, disk->first_minor,
 			   S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
 			   &dm_blk_dops, NULL);
 
@@ -448,17 +448,18 @@
 {
 	struct dm_table *table;
 	struct block_device *bdev;
+	struct gendisk *disk = dm_disk(md);
 
 	param->flags = DM_EXISTS_FLAG;
 	if (dm_suspended(md))
 		param->flags |= DM_SUSPEND_FLAG;
 
-	param->dev = kdev_t_to_nr(dm_kdev(md));
+	param->dev = MKDEV(disk->major, disk->first_minor);
 	bdev = bdget(param->dev);
 	if (!bdev)
 		return -ENXIO;
 
-	if (bdev_read_only(bdev))
+	if (disk->policy)
 		param->flags |= DM_READONLY_FLAG;
 
 	param->open_count = bdev->bd_openers;
@@ -585,7 +586,7 @@
 	}
 	dm_table_put(t);	/* md will have grabbed its own reference */
 
-	set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG));
+	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG));
 	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
 	dm_put(md);
 
@@ -871,7 +872,7 @@
 		return r;
 	}
 
-	set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG));
+	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG));
 	dm_put(md);
 
 	r = info(param, user);
@@ -1077,7 +1078,6 @@
 int __init dm_interface_init(void)
 {
 	int r;
-	char rname[64];
 
 	r = dm_hash_init();
 	if (r)
@@ -1090,25 +1090,12 @@
 		return r;
 	}
 
-	r = devfs_generate_path(_dm_misc.devfs_handle, rname + 3,
-				sizeof rname - 3);
-	if (r == -ENOSYS)
-		return 0;	/* devfs not present */
-
-	if (r < 0) {
-		DMERR("devfs_generate_path failed for control device");
-		goto failed;
-	}
-
-	strncpy(rname + r, "../", 3);
-	r = devfs_mk_symlink(NULL, DM_DIR "/control",
-			     DEVFS_FL_DEFAULT, rname + r, &_ctl_handle, NULL);
+	r = devfs_mk_symlink(NULL, DM_DIR "/control", DEVFS_FL_DEFAULT,
+			"../misc/" DM_NAME, &_ctl_handle, NULL);
 	if (r) {
 		DMERR("devfs_mk_symlink failed for control device");
 		goto failed;
 	}
-	devfs_auto_unregister(_dm_misc.devfs_handle, _ctl_handle);
-
 	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
 	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
 	       DM_DRIVER_EMAIL);
@@ -1123,6 +1110,8 @@
 void dm_interface_exit(void)
 {
 	dm_hash_exit();
+
+	devfs_remove(DM_DIR "/control");
 
 	if (misc_deregister(&_dm_misc) < 0)
 		DMERR("misc_deregister failed for control device");
diff -Nru a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
--- a/drivers/md/dm-linear.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/md/dm-linear.c	Sun Nov 17 20:30:14 2002
@@ -87,7 +87,7 @@
 
 	case STATUSTYPE_TABLE:
 		snprintf(result, maxlen, "%s " SECTOR_FORMAT,
-			 kdevname(to_kdev_t(lc->dev->bdev->bd_dev)), lc->start);
+			 bdevname(lc->dev->bdev), lc->start);
 		break;
 	}
 	return 0;
diff -Nru a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
--- a/drivers/md/dm-stripe.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/md/dm-stripe.c	Sun Nov 17 20:30:14 2002
@@ -221,7 +221,7 @@
 			offset +=
 			    snprintf(result + offset, maxlen - offset,
 				     " %s " SECTOR_FORMAT,
-		       kdevname(to_kdev_t(sc->stripe[i].dev->bdev->bd_dev)),
+		       bdevname(sc->stripe[i].dev->bdev),
 				     sc->stripe[i].physical_start);
 		}
 		break;
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/md/dm.c	Sun Nov 17 20:30:15 2002
@@ -749,15 +749,9 @@
 	return 0;
 }
 
-kdev_t dm_kdev(struct mapped_device *md)
+struct gendisk *dm_disk(struct mapped_device *md)
 {
-	kdev_t dev;
-
-	down_read(&md->lock);
-	dev = md->kdev;
-	up_read(&md->lock);
-
-	return dev;
+	return md->disk;
 }
 
 struct dm_table *dm_get_table(struct mapped_device *md)
diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h
--- a/drivers/md/dm.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/md/dm.h	Sun Nov 17 20:30:14 2002
@@ -77,7 +77,7 @@
 /*
  * Info functions.
  */
-kdev_t dm_kdev(struct mapped_device *md);
+struct gendisk *dm_disk(struct mapped_device *md);
 int dm_suspended(struct mapped_device *md);
 
 /*-----------------------------------------------------------------
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/md/md.c	Sun Nov 17 20:30:12 2002
@@ -1008,7 +1008,7 @@
 
 	mddev->sb_dirty = 0;
 repeat:
-	mddev->utime = CURRENT_TIME;
+	mddev->utime = get_seconds();
 	mddev->events ++;
 
 	if (!mddev->events) {
@@ -2107,7 +2107,7 @@
 	mddev->major_version = MD_MAJOR_VERSION;
 	mddev->minor_version = MD_MINOR_VERSION;
 	mddev->patch_version = MD_PATCHLEVEL_VERSION;
-	mddev->ctime         = CURRENT_TIME;
+	mddev->ctime         = get_seconds();
 
 	mddev->level         = info->level;
 	mddev->size          = info->size;
@@ -3133,20 +3133,6 @@
 #ifndef MODULE
 
 /*
- * When md (and any require personalities) are compiled into the kernel
- * (not a module), arrays can be assembles are boot time using with AUTODETECT
- * where specially marked partitions are registered with md_autodetect_dev(),
- * and with MD_BOOT where devices to be collected are given on the boot line
- * with md=.....
- * The code for that is here.
- */
-
-struct {
-	int set;
-	int noautodetect;
-} raid_setup_args __initdata;
-
-/*
  * Searches all registered partitions for autorun RAID arrays
  * at boot time.
  */
@@ -3187,262 +3173,9 @@
 	autorun_devices();
 }
 
-static struct {
-	char device_set [MAX_MD_DEVS];
-	int pers[MAX_MD_DEVS];
-	int chunk[MAX_MD_DEVS];
-	char *device_names[MAX_MD_DEVS];
-} md_setup_args __initdata;
-
-/*
- * Parse the command-line parameters given our kernel, but do not
- * actually try to invoke the MD device now; that is handled by
- * md_setup_drive after the low-level disk drivers have initialised.
- *
- * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which
- *             assigns the task of parsing integer arguments to the
- *             invoked program now).  Added ability to initialise all
- *             the MD devices (by specifying multiple "md=" lines)
- *             instead of just one.  -- KTK
- * 18May2000: Added support for persistent-superblock arrays:
- *             md=n,0,factor,fault,device-list   uses RAID0 for device n
- *             md=n,-1,factor,fault,device-list  uses LINEAR for device n
- *             md=n,device-list      reads a RAID superblock from the devices
- *             elements in device-list are read by name_to_kdev_t so can be
- *             a hex number or something like /dev/hda1 /dev/sdb
- * 2001-06-03: Dave Cinege <dcinege@psychosis.com>
- *		Shifted name_to_kdev_t() and related operations to md_set_drive()
- *		for later execution. Rewrote section to make devfs compatible.
- */
-static int __init md_setup(char *str)
-{
-	int minor, level, factor, fault, pers;
-	char *pername = "";
-	char *str1 = str;
-
-	if (get_option(&str, &minor) != 2) {	/* MD Number */
-		printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
-		return 0;
-	}
-	if (minor >= MAX_MD_DEVS) {
-		printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor);
-		return 0;
-	} else if (md_setup_args.device_names[minor]) {
-		printk(KERN_WARNING "md: md=%d, Specified more than once. "
-		       "Replacing previous definition.\n", minor);
-	}
-	switch (get_option(&str, &level)) {	/* RAID Personality */
-	case 2: /* could be 0 or -1.. */
-		if (level == 0 || level == LEVEL_LINEAR) {
-			if (get_option(&str, &factor) != 2 ||	/* Chunk Size */
-					get_option(&str, &fault) != 2) {
-				printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
-				return 0;
-			}
-			md_setup_args.pers[minor] = level;
-			md_setup_args.chunk[minor] = 1 << (factor+12);
-			switch(level) {
-			case LEVEL_LINEAR:
-				pers = LINEAR;
-				pername = "linear";
-				break;
-			case 0:
-				pers = RAID0;
-				pername = "raid0";
-				break;
-			default:
-				printk(KERN_WARNING
-				       "md: The kernel has not been configured for raid%d support!\n",
-				       level);
-				return 0;
-			}
-			md_setup_args.pers[minor] = pers;
-			break;
-		}
-		/* FALL THROUGH */
-	case 1: /* the first device is numeric */
-		str = str1;
-		/* FALL THROUGH */
-	case 0:
-		md_setup_args.pers[minor] = 0;
-		pername="super-block";
-	}
-
-	printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
-		minor, pername, str);
-	md_setup_args.device_names[minor] = str;
-
-	return 1;
-}
-
-extern dev_t name_to_dev_t(char *line) __init;
-void __init md_setup_drive(void)
-{
-	int minor, i;
-	dev_t dev;
-	mddev_t*mddev;
-	dev_t devices[MD_SB_DISKS+1];
-
-	for (minor = 0; minor < MAX_MD_DEVS; minor++) {
-		int err = 0;
-		char *devname;
-		mdu_disk_info_t dinfo;
-
-		if (!(devname = md_setup_args.device_names[minor]))
-			continue;
-
-		for (i = 0; i < MD_SB_DISKS && devname != 0; i++) {
-
-			char *p;
-			void *handle;
-
-			p = strchr(devname, ',');
-			if (p)
-				*p++ = 0;
-
-			dev = name_to_dev_t(devname);
-			handle = devfs_get_handle(NULL, devname,
-						MAJOR(dev), MINOR(dev),
-						DEVFS_SPECIAL_BLK, 1);
-			if (handle != 0) {
-				unsigned major, minor;
-				devfs_get_maj_min(handle, &major, &minor);
-				dev = MKDEV(major, minor);
-				devfs_put(handle);
-			}
-			if (!dev) {
-				printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
-				break;
-			}
-
-			devices[i] = dev;
-			md_setup_args.device_set[minor] = 1;
-
-			devname = p;
-		}
-		devices[i] = 0;
-
-		if (!md_setup_args.device_set[minor])
-			continue;
-
-		printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
-
-		mddev = mddev_find(minor);
-		if (!mddev) {
-			printk(KERN_ERR "md: kmalloc failed - cannot start array %d\n", minor);
-			continue;
-		}
-		if (mddev_lock(mddev)) {
-			printk(KERN_WARNING
-			       "md: Ignoring md=%d, cannot lock!\n",
-			       minor);
-			mddev_put(mddev);
-			continue;
-		}
-
-		if (mddev->raid_disks || !list_empty(&mddev->disks)) {
-			printk(KERN_WARNING
-			       "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
-			       minor);
-			mddev_unlock(mddev);
-			mddev_put(mddev);
-			continue;
-		}
-		if (md_setup_args.pers[minor]) {
-			/* non-persistent */
-			mdu_array_info_t ainfo;
-			ainfo.level = pers_to_level(md_setup_args.pers[minor]);
-			ainfo.size = 0;
-			ainfo.nr_disks =0;
-			ainfo.raid_disks =0;
-			ainfo.md_minor =minor;
-			ainfo.not_persistent = 1;
-
-			ainfo.state = (1 << MD_SB_CLEAN);
-			ainfo.layout = 0;
-			ainfo.chunk_size = md_setup_args.chunk[minor];
-			err = set_array_info(mddev, &ainfo);
-			for (i = 0; !err && i <= MD_SB_DISKS; i++) {
-				dev = devices[i];
-				if (!dev)
-					break;
-				dinfo.number = i;
-				dinfo.raid_disk = i;
-				dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
-				dinfo.major = MAJOR(dev);
-				dinfo.minor = MINOR(dev);
-				mddev->raid_disks++;
-				err = add_new_disk (mddev, &dinfo);
-			}
-		} else {
-			/* persistent */
-			for (i = 0; i <= MD_SB_DISKS; i++) {
-				dev = devices[i];
-				if (!dev)
-					break;
-				dinfo.major = MAJOR(dev);
-				dinfo.minor = MINOR(dev);
-				add_new_disk (mddev, &dinfo);
-			}
-		}
-		if (!err)
-			err = do_md_run(mddev);
-		if (err) {
-			mddev->sb_dirty = 0;
-			do_md_stop(mddev, 0);
-			printk(KERN_WARNING "md: starting md%d failed\n", minor);
-		}
-		mddev_unlock(mddev);
-		mddev_put(mddev);
-	}
-}
-
-static int __init raid_setup(char *str)
-{
-	int len, pos;
-
-	len = strlen(str) + 1;
-	pos = 0;
-
-	while (pos < len) {
-		char *comma = strchr(str+pos, ',');
-		int wlen;
-		if (comma)
-			wlen = (comma-str)-pos;
-		else	wlen = (len-1)-pos;
-
-		if (!strncmp(str, "noautodetect", wlen))
-			raid_setup_args.noautodetect = 1;
-		pos += wlen+1;
-	}
-	raid_setup_args.set = 1;
-	return 1;
-}
-
-static int __init md_run_setup(void)
-{
-	if (raid_setup_args.noautodetect)
-		printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
-	else
-		autostart_arrays();
-	md_setup_drive();
-	return 0;
-}
-
-__setup("raid=", raid_setup);
-__setup("md=", md_setup);
-
-__initcall(md_init);
-__initcall(md_run_setup);
-
-#else /* It is a MODULE */
-
-int init_module(void)
-{
-	return md_init();
-}
+#endif
 
-void cleanup_module(void)
+static __exit void md_exit(void)
 {
 	int i;
 	blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS);
@@ -3466,7 +3199,9 @@
 		mddev_put(mddev);
 	}
 }
-#endif
+
+module_init(md_init)
+module_exit(md_exit)
 
 EXPORT_SYMBOL(md_size);
 EXPORT_SYMBOL(register_md_personality);
diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
--- a/drivers/media/dvb/dvb-core/dvbdev.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/media/dvb/dvb-core/dvbdev.c	Sun Nov 17 20:30:04 2002
@@ -350,7 +350,7 @@
 
 int dvb_register_adapter(dvb_adapter_t **padap, char *name)
 {
-	char dirname[10];
+	char dirname[16];
 	dvb_adapter_t *adap;
 	int num;
 
@@ -374,8 +374,8 @@
 
 	printk ("%s: registering new adapter (%s).\n", __FUNCTION__, name);
 	
-	sprintf(dirname, "adapter%d", num);
-	adap->devfs_handle = devfs_mk_dir(dvb_devfs_handle, dirname, NULL);
+	sprintf(dirname, "dvb/adapter%d", num);
+	adap->devfs_handle = devfs_mk_dir(NULL, dirname, NULL);
 	adap->num = num;
 
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
diff -Nru a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
--- a/drivers/media/radio/miropcm20-rds.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/media/radio/miropcm20-rds.c	Sun Nov 17 20:30:03 2002
@@ -23,16 +23,16 @@
 
 static int rds_f_open(struct inode *in, struct file *fi)
 {
-	if(rds_users)
+	if (rds_users)
 		return -EBUSY;
 
+	rds_users++;
 	if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
+		rds_users--;
 		printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
 		return -ENOMEM;
 	}
 
-	rds_users++;
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -41,7 +41,6 @@
 	kfree(text_buffer);
 
 	rds_users--;
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -106,6 +105,7 @@
 }
 
 static struct file_operations rds_f_ops = {
+	owner:	THIS_MODULE,
 	read:    rds_f_read,
 	open:    rds_f_open,
 	release: rds_f_release
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/media/video/bttv-driver.c	Sun Nov 17 20:30:15 2002
@@ -3225,6 +3225,7 @@
         INIT_LIST_HEAD(&btv->capture);
         INIT_LIST_HEAD(&btv->vcapture);
 
+	init_timer(&btv->timeout);
 	btv->timeout.function = bttv_irq_timeout;
 	btv->timeout.data     = (unsigned long)btv;
 	
diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
--- a/drivers/message/fusion/mptscsih.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/message/fusion/mptscsih.h	Sun Nov 17 20:30:16 2002
@@ -230,8 +230,8 @@
 extern	int		 x_scsi_old_abort(Scsi_Cmnd *);
 extern	int		 x_scsi_old_reset(Scsi_Cmnd *, unsigned int);
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
-extern	int		 x_scsi_bios_param(Disk *, struct block_device *, int *);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
+extern	int		 x_scsi_bios_param(Scsi_Device *, struct block_device *, sector_t, int[]);
 #else
 extern	int		 x_scsi_bios_param(Disk *, kdev_t, int *);
 #endif
diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
--- a/drivers/mtd/devices/blkmtd.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/mtd/devices/blkmtd.c	Sun Nov 17 20:30:02 2002
@@ -1127,7 +1127,7 @@
     return 1;
   }
   /* get the block device */
-  bdev = bdget(kdev_t_to_nr(mk_kdev(maj, min)));
+  bdev = bdget(rdev);
   err = blkdev_get(bdev, mode, 0, BDEV_RAW);
   if (err)
     return 1;
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/net/3c59x.c	Sun Nov 17 20:30:02 2002
@@ -1300,8 +1300,6 @@
 			else
 				phyx = phy;
 			mii_status = mdio_read(dev, phyx, 1);
-			printk("phy=%d, phyx=%d, mii_status=0x%04x\n",
-				phy, phyx, mii_status);
 			if (mii_status  &&  mii_status != 0xffff) {
 				vp->phys[phy_idx++] = phyx;
 				if (print_info) {
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/net/eepro100.c	Sun Nov 17 20:30:14 2002
@@ -734,7 +734,7 @@
 	if (eeprom[3] & 0x0100)
 		product = "OEM i82557/i82558 10/100 Ethernet";
 	else
-		product = pdev->name;
+		product = pdev->dev.name;
 
 	printk(KERN_INFO "%s: %s, ", dev->name, product);
 
diff -Nru a/drivers/net/irda/old_belkin.c b/drivers/net/irda/old_belkin.c
--- a/drivers/net/irda/old_belkin.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/net/irda/old_belkin.c	Sun Nov 17 20:30:15 2002
@@ -33,6 +33,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/net.h>
 #include <linux/irda.h>
 
 #include <net/irda/irda.h>
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/net/rrunner.c	Sun Nov 17 20:30:12 2002
@@ -1,7 +1,7 @@
 /*
  * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board.
  *
- * Copyright (C) 1998-2000 by Jes Sorensen, <Jes.Sorensen@cern.ch>.
+ * Copyright (C) 1998-2002 by Jes Sorensen, <jes@wildopensource.com>.
  *
  * Thanks to Essential Communication for providing us with hardware
  * and very comprehensive documentation without which I would not have
@@ -19,9 +19,10 @@
  *
  * Softnet support and various other patches from Val Henson of
  * ODS/Essential.
+ *
+ * PCI DMA mapping code partly based on work by Francois Romieu.
  */
 
-#error Please convert me to Documentation/DMA-mapping.txt
 
 #define DEBUG 1
 #define RX_DMA_SKBUFF 1
@@ -50,45 +51,20 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
-#if (LINUX_VERSION_CODE >= 0x02031b)
-#define NEW_NETINIT
-#endif
-
-#if (LINUX_VERSION_CODE < 0x02032b)
-/*
- * SoftNet changes
- */
-#define dev_kfree_skb_irq(a)	dev_kfree_skb(a)
-#define netif_wake_queue(dev)	clear_bit(0, &dev->tbusy)
-#define netif_stop_queue(dev)	set_bit(0, &dev->tbusy)
-
-static inline void netif_start_queue(struct net_device *dev)
-{
-	dev->tbusy = 0;
-	dev->start = 1;
-}
-
-#define rr_mark_net_bh(foo) mark_bh(foo)
-#define rr_if_busy(dev)     dev->tbusy
-#define rr_if_running(dev)  dev->start /* Currently unused. */
-#define rr_if_down(dev)     do { dev->start = 0; } while (0)
-#else
-#define NET_BH              0
-#define rr_mark_net_bh(foo) do { } while(0)
 #define rr_if_busy(dev)     netif_queue_stopped(dev)
 #define rr_if_running(dev)  netif_running(dev)
-#define rr_if_down(dev)     do { } while(0)
-#endif
 
 #include "rrunner.h"
 
 #define RUN_AT(x) (jiffies + (x))
 
 
+MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
+MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
+MODULE_LICENSE("GPL");
+
+static char version[] __initdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
+
 /*
  * Implementation notes:
  *
@@ -104,11 +80,6 @@
  * stack will need to know about I/O vectors or something similar.
  */
 
-static char version[] __initdata = "rrunner.c: v0.22 03/01/2000  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
-
-static struct net_device *root_dev;
-
-
 /*
  * These are checked at init time to see if they are at least 256KB
  * and increased to 256KB if they are not. This is done to avoid ending
@@ -117,200 +88,185 @@
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
-static int probed __initdata = 0;
-
-#if LINUX_VERSION_CODE >= 0x20400
-static struct pci_device_id rrunner_pci_tbl[] __initdata = {
-	{ PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, PCI_ANY_ID, PCI_ANY_ID, },
-	{ }			/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, rrunner_pci_tbl);
-#endif /* LINUX_VERSION_CODE >= 0x20400 */
-
-#ifdef NEW_NETINIT
-int __init rr_hippi_probe (void)
-#else
-int __init rr_hippi_probe (struct net_device *dev)
-#endif
+static int __devinit rr_init_one(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
 {
-#ifdef NEW_NETINIT
 	struct net_device *dev;
-#endif
-	int boards_found = 0;
-	int version_disp;	/* was version info already displayed? */
-	struct pci_dev *pdev = NULL;
-	struct pci_dev *opdev = NULL;
+	static int version_disp;
 	u8 pci_latency;
 	struct rr_private *rrpriv;
+	void *tmpptr;
+	dma_addr_t ring_dma;
+	int ret;
 
-	if (probed)
-		return -ENODEV;
-	probed++;
-
-	version_disp = 0;
-
-	while((pdev = pci_find_device(PCI_VENDOR_ID_ESSENTIAL,
-				      PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
-				      pdev)))
-	{
-		if (pci_enable_device(pdev))
-			continue;
+	dev = init_hippi_dev(NULL, sizeof(struct rr_private));
+	if (!dev) {
+		ret = -ENOMEM;
+		goto out2;
+	}
 
-		if (pdev == opdev)
-			return 0;
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		ret = -ENODEV;
+		goto out2;
+	}
 
-		/*
-		 * So we found our HIPPI ... time to tell the system.
-		 */
+	if (!dev->priv)
+		dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
 
-		dev = init_hippi_dev(NULL, sizeof(struct rr_private));
+	if (!dev->priv) {
+		ret = -ENOMEM;
+		goto out2;
+	}
 
-		if (!dev)
-			break;
+	rrpriv = (struct rr_private *)dev->priv;
+	memset(rrpriv, 0, sizeof(*rrpriv));
 
-		if (!dev->priv)
-			dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
+	SET_MODULE_OWNER(dev);
 
-		if (!dev->priv)
-			return -ENOMEM;
+	if (pci_request_regions(pdev, "rrunner")) {
+		ret = -EIO;
+		goto out;
+	}
 
-		rrpriv = (struct rr_private *)dev->priv;
-		memset(rrpriv, 0, sizeof(*rrpriv));
+	pci_set_drvdata(pdev, dev);
 
-#ifdef CONFIG_SMP
-		spin_lock_init(&rrpriv->lock);
-#endif
-		sprintf(rrpriv->name, "RoadRunner serial HIPPI");
+	rrpriv->pci_dev = pdev;
 
-		dev->irq = pdev->irq;
-		SET_MODULE_OWNER(dev);
-		dev->open = &rr_open;
-		dev->hard_start_xmit = &rr_start_xmit;
-		dev->stop = &rr_close;
-		dev->get_stats = &rr_get_stats;
-		dev->do_ioctl = &rr_ioctl;
+	spin_lock_init(&rrpriv->lock);
+	sprintf(rrpriv->name, "RoadRunner serial HIPPI");
 
-#if (LINUX_VERSION_CODE < 0x02030d)
-		dev->base_addr = pdev->base_address[0];
-#else
-		dev->base_addr = pdev->resource[0].start;
-#endif
+	dev->irq = pdev->irq;
+	dev->open = &rr_open;
+	dev->hard_start_xmit = &rr_start_xmit;
+	dev->stop = &rr_close;
+	dev->get_stats = &rr_get_stats;
+	dev->do_ioctl = &rr_ioctl;
 
-		/* display version info if adapter is found */
-		if (!version_disp)
-		{
-			/* set display flag to TRUE so that */
-			/* we only display this string ONCE */
-			version_disp = 1;
-			printk(version);
-		}
-
-		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
-		if (pci_latency <= 0x58){
-			pci_latency = 0x58;
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
-					      pci_latency);
-		}
-
-		pci_set_master(pdev);
-
-		printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
-		       "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
-		       dev->base_addr, dev->irq, pci_latency);
+	dev->base_addr = pci_resource_start(pdev, 0);
 
-		/*
-		 * Remap the regs into kernel space.
-		 */
+	/* display version info if adapter is found */
+	if (!version_disp) {
+		/* set display flag to TRUE so that */
+		/* we only display this string ONCE */
+		version_disp = 1;
+		printk(version);
+	}
 
-		rrpriv->regs = (struct rr_regs *)
-			ioremap(dev->base_addr, 0x1000);
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+	if (pci_latency <= 0x58){
+		pci_latency = 0x58;
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency);
+	}
 
-		if (!rrpriv->regs){
-			printk(KERN_ERR "%s:  Unable to map I/O register, "
-			       "RoadRunner %i will be disabled.\n",
-			       dev->name, boards_found);
-			break;
-		}
+	pci_set_master(pdev);
 
-		/*
-		 * Don't access any registes before this point!
-		 */
-#ifdef __BIG_ENDIAN
-		writel(readl(&regs->HostCtrl) | NO_SWAP, &regs->HostCtrl);
-#endif
-		/*
-		 * Need to add a case for little-endian 64-bit hosts here.
-		 */
+	printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
+	       "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
+	       dev->base_addr, dev->irq, pci_latency);
+
+	/*
+	 * Remap the regs into kernel space.
+	 */
 
-		rr_init(dev);
+	rrpriv->regs = (struct rr_regs *)ioremap(dev->base_addr, 0x1000);
 
-		boards_found++;
-		dev->base_addr = 0;
-		dev = NULL;
-		opdev = pdev;
+	if (!rrpriv->regs){
+		printk(KERN_ERR "%s:  Unable to map I/O register, "
+			"RoadRunner will be disabled.\n", dev->name);
+		ret = -EIO;
+		goto out;
 	}
 
-	/*
-	 * If we're at this point we're going through rr_hippi_probe()
-	 * for the first time.  Return success (0) if we've initialized
-	 * 1 or more boards. Otherwise, return failure (-ENODEV).
-	 */
+	tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	rrpriv->tx_ring = tmpptr;
+	rrpriv->tx_ring_dma = ring_dma;
 
-#ifdef MODULE
-	return boards_found;
-#else
-	if (boards_found > 0)
-		return 0;
-	else
-		return -ENODEV;
-#endif
-}
+	if (!tmpptr) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
+	tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	rrpriv->rx_ring = tmpptr;
+	rrpriv->rx_ring_dma = ring_dma;
 
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
-MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
-MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
-MODULE_LICENSE("GPL");
-#endif
+	if (!tmpptr) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
-int init_module(void)
-{
-	int cards;
+	tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma);
+	rrpriv->evt_ring = tmpptr;
+	rrpriv->evt_ring_dma = ring_dma;
 
-	root_dev = NULL;
+	if (!tmpptr) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
-#ifdef NEW_NETINIT
-	cards = rr_hippi_probe();
-#else
-	cards = rr_hippi_probe(NULL);
+	/*
+	 * Don't access any register before this point!
+	 */
+#ifdef __BIG_ENDIAN
+	writel(readl(&regs->HostCtrl) | NO_SWAP, &regs->HostCtrl);
 #endif
-	return cards ? 0 : -ENODEV;
+	/*
+	 * Need to add a case for little-endian 64-bit hosts here.
+	 */
+
+	rr_init(dev);
+
+	dev->base_addr = 0;
+	return 0;
+
+ out:
+	if (rrpriv->rx_ring)
+		pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring, 
+				    rrpriv->rx_ring_dma);
+	if (rrpriv->tx_ring)
+		pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring,
+				    rrpriv->tx_ring_dma);
+	if (rrpriv->regs)
+		iounmap(rrpriv->regs);	
+	if (pdev) {
+		pci_release_regions(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
+
+ out2:
+	if (dev) {
+		unregister_hipdev(dev);
+		kfree(dev);
+	}
+	return ret;
 }
 
-void cleanup_module(void)
+static void __devexit rr_remove_one (struct pci_dev *pdev)
 {
-	struct rr_private *rr;
-	struct net_device *next;
-
-	while (root_dev) {
-		next = ((struct rr_private *)root_dev->priv)->next;
-		rr = (struct rr_private *)root_dev->priv;
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rr_private *rr = (struct rr_private *)dev->priv;
 
+	if (dev) {
 		if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){
 			printk(KERN_ERR "%s: trying to unload running NIC\n",
-			       root_dev->name);
+			       dev->name);
 			writel(HALT_NIC, &rr->regs->HostCtrl);
 		}
 
+		pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring,
+				    rr->evt_ring_dma);
+		pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring,
+				    rr->rx_ring_dma);
+		pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring,
+				    rr->tx_ring_dma);
+		unregister_hipdev(dev);
 		iounmap(rr->regs);
-		unregister_hipdev(root_dev);
-		kfree(root_dev);
-
-		root_dev = next;
+		kfree(dev);
+		pci_release_regions(pdev);
+		pci_set_drvdata(pdev, NULL);
 	}
 }
-#endif
 
 
 /*
@@ -634,9 +590,6 @@
 		sysctl_wmem_max = 262144;
 	}
 
-	rrpriv->next = root_dev;
-	root_dev = dev;
-
 	return 0;
 }
 
@@ -668,14 +621,14 @@
 		goto error;
 	}
 
-	set_rxaddr(regs, rrpriv->rx_ctrl);
-	set_infoaddr(regs, rrpriv->info);
+	set_rxaddr(regs, rrpriv->rx_ctrl_dma);
+	set_infoaddr(regs, rrpriv->info_dma);
 
 	rrpriv->info->evt_ctrl.entry_size = sizeof(struct event);
 	rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES;
 	rrpriv->info->evt_ctrl.mode = 0;
 	rrpriv->info->evt_ctrl.pi = 0;
-	set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring);
+	set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring_dma);
 
 	rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd);
 	rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES;
@@ -695,7 +648,7 @@
 	rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES;
 	rrpriv->info->tx_ctrl.mode = 0;
 	rrpriv->info->tx_ctrl.pi = 0;
-	set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring);
+	set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring_dma);
 
 	/*
 	 * Set dirty_tx before we start receiving interrupts, otherwise
@@ -730,6 +683,7 @@
 
 	for (i = 0; i < RX_RING_ENTRIES; i++) {
 		struct sk_buff *skb;
+		dma_addr_t addr;
 
 		rrpriv->rx_ring[i].mode = 0;
 		skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
@@ -740,6 +694,8 @@
 			goto error;
 		}
 		rrpriv->rx_skbuff[i] = skb;
+	        addr = pci_map_single(rrpriv->pci_dev, skb->data,
+			dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
 		/*
 		 * Sanity test to see if we conflict with the DMA
 		 * limitations of the Roadrunner.
@@ -747,7 +703,7 @@
 		if ((((unsigned long)skb->data) & 0xfff) > ~65320)
 			printk("skb alloc error\n");
 
-		set_rraddr(&rrpriv->rx_ring[i].addr, skb->data);
+		set_rraddr(&rrpriv->rx_ring[i].addr, addr);
 		rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN;
 	}
 
@@ -756,7 +712,7 @@
 	rrpriv->rx_ctrl[4].mode = 8;
 	rrpriv->rx_ctrl[4].pi = 0;
 	wmb();
-	set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring);
+	set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring_dma);
 
 	udelay(1000);
 
@@ -785,10 +741,17 @@
 	 * make sure we release everything we allocated before failing
 	 */
 	for (i = 0; i < RX_RING_ENTRIES; i++) {
-		if (rrpriv->rx_skbuff[i]) {
+		struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+		if (skb) {
+	        	pci_unmap_single(rrpriv->pci_dev, 
+					 rrpriv->rx_ring[i].addr.addrlo, 
+					 dev->mtu + HIPPI_HLEN,
+					 PCI_DMA_FROMDEVICE);
 			rrpriv->rx_ring[i].size = 0;
 			set_rraddr(&rrpriv->rx_ring[i].addr, 0);
-			dev_kfree_skb(rrpriv->rx_skbuff[i]);
+			dev_kfree_skb(skb);
+			rrpriv->rx_skbuff[i] = 0;
 		}
 	}
 	return ecode;
@@ -1009,12 +972,14 @@
 	struct rr_regs *regs = rrpriv->regs;
 
 	do {
+		struct rx_desc *desc;
 		u32 pkt_len;
-		pkt_len = rrpriv->rx_ring[index].size;
+
+		desc = &(rrpriv->rx_ring[index]);
+		pkt_len = desc->size;
 #if (DEBUG > 2)
 		printk("index %i, rxlimit %i\n", index, rxlimit);
-		printk("len %x, mode %x\n", pkt_len,
-		       rrpriv->rx_ring[index].mode);
+		printk("len %x, mode %x\n", pkt_len, desc->mode);
 #endif
 		if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){
 			rrpriv->stats.rx_dropped++;
@@ -1022,7 +987,12 @@
 		}
 
 		if (pkt_len > 0){
-			struct sk_buff *skb;
+			struct sk_buff *skb, *rx_skb;
+
+			rx_skb = rrpriv->rx_skbuff[index];
+
+	        	pci_dma_sync_single(rrpriv->pci_dev, desc->addr.addrlo,
+				pkt_len, PCI_DMA_FROMDEVICE);
 
 			if (pkt_len < PKT_COPY_THRESHOLD) {
 				skb = alloc_skb(pkt_len, GFP_ATOMIC);
@@ -1032,19 +1002,27 @@
 					goto defer;
 				}else
 					memcpy(skb_put(skb, pkt_len),
-					       rrpriv->rx_skbuff[index]->data,
-					       pkt_len);
+					       rx_skb->data, pkt_len);
 			}else{
 				struct sk_buff *newskb;
 
 				newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
-						   GFP_ATOMIC);
+					GFP_ATOMIC);
 				if (newskb){
-					skb = rrpriv->rx_skbuff[index];
+					dma_addr_t addr;
+
+	        			pci_unmap_single(rrpriv->pci_dev, 
+						desc->addr.addrlo, dev->mtu + 
+						HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+					skb = rx_skb;
 					skb_put(skb, pkt_len);
 					rrpriv->rx_skbuff[index] = newskb;
-					set_rraddr(&rrpriv->rx_ring[index].addr, newskb->data);
-				}else{
+	        			addr = pci_map_single(rrpriv->pci_dev, 
+						newskb->data, 
+						dev->mtu + HIPPI_HLEN, 
+						PCI_DMA_FROMDEVICE);
+					set_rraddr(&desc->addr, addr);
+				} else {
 					printk("%s: Out of memory, deferring "
 					       "packet\n", dev->name);
 					rrpriv->stats.rx_dropped++;
@@ -1061,8 +1039,8 @@
 			rrpriv->stats.rx_bytes += pkt_len;
 		}
 	defer:
-		rrpriv->rx_ring[index].mode = 0;
-		rrpriv->rx_ring[index].size = dev->mtu + HIPPI_HLEN;
+		desc->mode = 0;
+		desc->size = dev->mtu + HIPPI_HLEN;
 
 		if ((index & 7) == 7)
 			writel(index, &regs->IpRxPi);
@@ -1120,14 +1098,24 @@
 			 * of sync. error need to check entry in ring -kbf
 			 */
 			if(rrpriv->tx_skbuff[txcon]){
+				struct tx_desc *desc;
+				struct sk_buff *skb;
+
+				desc = &(rrpriv->tx_ring[txcon]);
+				skb = rrpriv->tx_skbuff[txcon];
+
 				rrpriv->stats.tx_packets++;
-				rrpriv->stats.tx_bytes +=rrpriv->tx_skbuff[txcon]->len;
-				dev_kfree_skb_irq(rrpriv->tx_skbuff[txcon]);
+				rrpriv->stats.tx_bytes += skb->len;
+
+				pci_unmap_single(rrpriv->pci_dev,
+						 desc->addr.addrlo, skb->len,
+						 PCI_DMA_TODEVICE);
+				dev_kfree_skb_irq(skb);
 
 				rrpriv->tx_skbuff[txcon] = NULL;
-				rrpriv->tx_ring[txcon].size = 0;
+				desc->size = 0;
 				set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
-				rrpriv->tx_ring[txcon].mode = 0;
+				desc->mode = 0;
 			}
 			txcon = (txcon + 1) % TX_RING_ENTRIES;
 		} while (txcsmr != txcon);
@@ -1139,7 +1127,6 @@
 		     != rrpriv->dirty_tx)){
 			rrpriv->tx_full = 0;
 			netif_wake_queue(dev);
-			rr_mark_net_bh(NET_BH);
 		}
 	}
 
@@ -1164,6 +1151,7 @@
 		memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));
 		memset(rrpriv->info, 0, sizeof(struct rr_info));
 		wmb();
+
 		for (i = 0; i < TX_RING_ENTRIES; i++) {
 			if (rrpriv->tx_skbuff[i]) {
 				rrpriv->tx_ring[i].size = 0;
@@ -1181,6 +1169,7 @@
 				rrpriv->rx_skbuff[i] = NULL;
 			}
 		}
+
 		if (rr_init1(dev)) {
 			spin_lock_irqsave(&rrpriv->lock, flags);
 			writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, 
@@ -1195,12 +1184,13 @@
 
 static int rr_open(struct net_device *dev)
 {
-	struct rr_private *rrpriv;
+	struct rr_private *rrpriv = (struct rr_private *)dev->priv;
+	struct pci_dev *pdev = rrpriv->pci_dev;
 	struct rr_regs *regs;
 	int ecode = 0;
 	unsigned long flags;
+	dma_addr_t dma_addr;
 
-	rrpriv = (struct rr_private *)dev->priv;
 	regs = rrpriv->regs;
 
 	if (rrpriv->fw_rev < 0x00020000) {
@@ -1210,24 +1200,29 @@
 		goto error;
 	}
 
-	rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), GFP_KERNEL);
+	rrpriv->rx_ctrl = pci_alloc_consistent(pdev,
+					       256 * sizeof(struct ring_ctrl),
+					       &dma_addr);
 	if (!rrpriv->rx_ctrl) {
 		ecode = -ENOMEM;
 		goto error;
 	}
+	rrpriv->rx_ctrl_dma = dma_addr;
+	memset(rrpriv->rx_ctrl, 0, 256*sizeof(struct ring_ctrl));
 
-	rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL);
-	if (!rrpriv->info){
-		rrpriv->rx_ctrl = NULL;
+	rrpriv->info = pci_alloc_consistent(pdev, sizeof(struct rr_info),
+					    &dma_addr);
+	if (!rrpriv->info) {
 		ecode = -ENOMEM;
 		goto error;
 	}
-	memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));
+	rrpriv->info_dma = dma_addr;
 	memset(rrpriv->info, 0, sizeof(struct rr_info));
 	wmb();
 
 	spin_lock_irqsave(&rrpriv->lock, flags);
 	writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
+	readl(&regs->HostCtrl);
 	spin_unlock_irqrestore(&rrpriv->lock, flags);
 
 	if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))
@@ -1251,6 +1246,7 @@
 
 	netif_start_queue(dev);
 
+	MOD_INC_USE_COUNT;
 	return ecode;
 
  error:
@@ -1268,12 +1264,54 @@
 	}
 
 	netif_stop_queue(dev);
-	rr_if_down(dev);
 	
 	return ecode;
 }
 
 
+static inline void rr_raz_tx(struct rr_private *rrpriv, 
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < TX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->tx_skbuff[i];
+
+		if (skb) {
+			struct tx_desc *desc = &(rrpriv->tx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
+				skb->len, PCI_DMA_TODEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->tx_skbuff[i] = NULL;
+		}
+	}
+}
+
+
+static inline void rr_raz_rx(struct rr_private *rrpriv, 
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < RX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+		if (skb) {
+			struct rx_desc *desc = &(rrpriv->rx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
+				dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->rx_skbuff[i] = NULL;
+		}
+	}
+}
+
 static void rr_dump(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
@@ -1313,11 +1351,10 @@
 	if (rrpriv->tx_skbuff[cons]){
 		len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len);
 		printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);
-		printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n",
+		printk("mode 0x%x, size 0x%x,\n phys %08x, skbuff-addr %08lx, truesize 0x%x\n",
 		       rrpriv->tx_ring[cons].mode,
 		       rrpriv->tx_ring[cons].size,
 		       rrpriv->tx_ring[cons].addr.addrlo,
-		       (unsigned long)bus_to_virt(rrpriv->tx_ring[cons].addr.addrlo),
 		       (unsigned long)rrpriv->tx_skbuff[cons]->data,
 		       (unsigned int)rrpriv->tx_skbuff[cons]->truesize);
 		for (i = 0; i < len; i++){
@@ -1342,20 +1379,20 @@
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
+	unsigned long flags;
 	u32 tmp;
 	short i;
 
 	netif_stop_queue(dev);
-	rr_if_down(dev);
-	
+
 	rrpriv = (struct rr_private *)dev->priv;
 	regs = rrpriv->regs;
 
 	/*
 	 * Lock to make sure we are not cleaning up while another CPU
-	 * handling interrupts.
+	 * is handling interrupts.
 	 */
-	spin_lock(&rrpriv->lock);
+	spin_lock_irqsave(&rrpriv->lock, flags);
 
 	tmp = readl(&regs->HostCtrl);
 	if (tmp & NIC_HALTED){
@@ -1364,12 +1401,12 @@
 	}else{
 		tmp |= HALT_NIC | RR_CLEAR_INT;
 		writel(tmp, &regs->HostCtrl);
-		wmb();
+		readl(&regs->HostCtrl);
 	}
 
 	rrpriv->fw_running = 0;
 
-	del_timer(&rrpriv->timer);
+	del_timer_sync(&rrpriv->timer);
 
 	writel(0, &regs->TxPi);
 	writel(0, &regs->IpRxPi);
@@ -1403,18 +1440,18 @@
 		}
 	}
 
-	if (rrpriv->rx_ctrl) {
-		kfree(rrpriv->rx_ctrl);
-		rrpriv->rx_ctrl = NULL;
-	}
-	if (rrpriv->info) {
-		kfree(rrpriv->info);
-		rrpriv->info = NULL;
-	}
+	pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl),
+			    rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
+	rrpriv->rx_ctrl = NULL;
+
+	pci_free_consistent(rrpriv->pci_dev, sizeof(struct rr_info),
+			    rrpriv->info, rrpriv->info_dma);
+	rrpriv->info = NULL;
 
 	free_irq(dev->irq, dev);
-	spin_unlock(&rrpriv->lock);
+	spin_unlock_irqrestore(&rrpriv->lock, flags);
 
+	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -1467,7 +1504,8 @@
 	index = txctrl->pi;
 
 	rrpriv->tx_skbuff[index] = skb;
-	set_rraddr(&rrpriv->tx_ring[index].addr, skb->data);
+	set_rraddr(&rrpriv->tx_ring[index].addr, pci_map_single(
+		rrpriv->pci_dev, skb->data, len + 8, PCI_DMA_TODEVICE));
 	rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */
 	rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END;
 	txctrl->pi = (index + 1) % TX_RING_ENTRIES;
@@ -1612,6 +1650,7 @@
 {
 	struct rr_private *rrpriv;
 	unsigned char *image, *oldimage;
+	unsigned long flags;
 	unsigned int i;
 	int error = -EOPNOTSUPP;
 
@@ -1629,25 +1668,27 @@
 			       "for EEPROM image\n", dev->name);
 			return -ENOMEM;
 		}
-		
-		spin_lock(&rrpriv->lock);
-		
+
+
 		if (rrpriv->fw_running){
 			printk("%s: Firmware already running\n", dev->name);
 			error = -EPERM;
-			goto out_spin;
+			goto gf_out;
 		}
 
+		spin_lock_irqsave(&rrpriv->lock, flags);
 		i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
 		if (i != EEPROM_BYTES){
-			printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name);
+			printk(KERN_ERR "%s: Error reading EEPROM\n",
+			       dev->name);
 			error = -EFAULT;
-			goto out_spin;
+			goto gf_out;
 		}
-		spin_unlock(&rrpriv->lock);
+		spin_unlock_irqrestore(&rrpriv->lock, flags);
 		error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
 		if (error)
 			error = -EFAULT;
+	gf_out:
 		kfree(image);
 		return error;
 		
@@ -1657,56 +1698,52 @@
 		}
 
 		image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-		if (!image){
-			printk(KERN_ERR "%s: Unable to allocate memory "
-			       "for EEPROM image\n", dev->name);
-			return -ENOMEM;
-		}
-
 		oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-		if (!oldimage){
-			kfree(image);
+		if (!image || !oldimage) {
 			printk(KERN_ERR "%s: Unable to allocate memory "
-			       "for old EEPROM image\n", dev->name);
-			return -ENOMEM;
+			       "for EEPROM image\n", dev->name);
+			error = -ENOMEM;
+			goto wf_out;
 		}
 
 		error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
 		if (error) {
-			kfree(image);
-			kfree(oldimage);
-			return -EFAULT;
+			error = -EFAULT;
+			goto wf_out;
 		}
 
-		spin_lock(&rrpriv->lock);
 		if (rrpriv->fw_running){
-			kfree(oldimage);
 			printk("%s: Firmware already running\n", dev->name);
 			error = -EPERM;
-			goto out_spin;
+			goto wf_out;
 		}
 
 		printk("%s: Updating EEPROM firmware\n", dev->name);
 
+		spin_lock_irqsave(&rrpriv->lock, flags);
 		error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
 		if (error)
 			printk(KERN_ERR "%s: Error writing EEPROM\n",
 			       dev->name);
 
 		i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
+		spin_unlock_irqrestore(&rrpriv->lock, flags);
+
 		if (i != EEPROM_BYTES)
 			printk(KERN_ERR "%s: Error reading back EEPROM "
 			       "image\n", dev->name);
 
-		spin_unlock(&rrpriv->lock);
 		error = memcmp(image, oldimage, EEPROM_BYTES);
 		if (error){
 			printk(KERN_ERR "%s: Error verifying EEPROM image\n",
 			       dev->name);
 			error = -EFAULT;
 		}
-		kfree(image);
-		kfree(oldimage);
+	wf_out:
+		if (oldimage)
+			kfree(oldimage);
+		if (image)
+			kfree(image);
 		return error;
 		
 	case SIOCRRID:
@@ -1714,13 +1751,34 @@
 	default:
 		return error;
 	}
+}
 
- out_spin:
-	kfree(image);
-	spin_unlock(&rrpriv->lock);
-	return error;
+static struct pci_device_id rr_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0,}
+};
+MODULE_DEVICE_TABLE(pci, rr_pci_tbl);
+
+static struct pci_driver rr_driver = {
+	name:		"rrunner",
+	id_table:	rr_pci_tbl,
+	probe:		rr_init_one,
+	remove:		rr_remove_one,
+};
+
+static int __init rr_init_module(void)
+{
+	return pci_module_init(&rr_driver);
+}
+
+static void __exit rr_cleanup_module(void)
+{
+	pci_unregister_driver(&rr_driver);
 }
 
+module_init(rr_init_module);
+module_exit(rr_cleanup_module);
 
 /*
  * Local variables:
diff -Nru a/drivers/net/rrunner.h b/drivers/net/rrunner.h
--- a/drivers/net/rrunner.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/net/rrunner.h	Sun Nov 17 20:30:14 2002
@@ -351,7 +351,7 @@
  */
 
 #define EVT_RING_ENTRIES	64
-#define EVT_RING_SIZE	(EVT_RING_ENTRIES * sizeof(struct event))
+#define EVT_RING_SIZE		(EVT_RING_ENTRIES * sizeof(struct event))
 
 struct event {
 #ifdef __LITTLE_ENDIAN
@@ -496,9 +496,9 @@
 } rraddr;
 
 
-static inline void set_rraddr(rraddr *ra, volatile void *addr)
+static inline void set_rraddr(rraddr *ra, dma_addr_t addr)
 {
-	unsigned long baddr = virt_to_bus((void *)addr);
+	unsigned long baddr = addr;
 #if (BITS_PER_LONG == 64)
 	ra->addrlo = baddr;
 #else
@@ -509,9 +509,9 @@
 }
 
 
-static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr)
+static inline void set_rxaddr(struct rr_regs *regs, volatile dma_addr_t addr)
 {
-	unsigned long baddr = virt_to_bus((void *)addr);
+	unsigned long baddr = addr;
 #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
 	writel(baddr & 0xffffffff, &regs->RxRingHi);
 	writel(baddr >> 32, &regs->RxRingLo);
@@ -526,9 +526,9 @@
 }
 
 
-static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr)
+static inline void set_infoaddr(struct rr_regs *regs, volatile dma_addr_t addr)
 {
-	unsigned long baddr = virt_to_bus((void *)addr);
+	unsigned long baddr = addr;
 #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
 	writel(baddr & 0xffffffff, &regs->InfoPtrHi);
 	writel(baddr >> 32, &regs->InfoPtrLo);
@@ -552,7 +552,7 @@
 #else
 #define TX_RING_ENTRIES	16
 #endif
-#define TX_RING_SIZE	(TX_RING_ENTRIES * sizeof(struct tx_desc))
+#define TX_TOTAL_SIZE	(TX_RING_ENTRIES * sizeof(struct tx_desc))
 
 struct tx_desc{
 	rraddr	addr;
@@ -574,7 +574,7 @@
 #else
 #define RX_RING_ENTRIES 16
 #endif
-#define RX_RING_SIZE	(RX_RING_ENTRIES * sizeof(struct rx_desc))
+#define RX_TOTAL_SIZE	(RX_RING_ENTRIES * sizeof(struct rx_desc))
 
 struct rx_desc{
 	rraddr	addr;
@@ -798,24 +798,30 @@
 
 struct rr_private
 {
-	struct rx_desc		rx_ring[RX_RING_ENTRIES];
-	struct tx_desc		tx_ring[TX_RING_ENTRIES];
-	struct event		evt_ring[EVT_RING_ENTRIES];
+	struct rx_desc		*rx_ring;
+	struct tx_desc		*tx_ring;
+	struct event		*evt_ring;
+	dma_addr_t 		tx_ring_dma;
+	dma_addr_t 		rx_ring_dma;
+	dma_addr_t 		evt_ring_dma;
+	/* Alignment ok ? */
 	struct sk_buff		*rx_skbuff[RX_RING_ENTRIES];
 	struct sk_buff		*tx_skbuff[TX_RING_ENTRIES];
 	struct rr_regs		*regs;		/* Register base */
 	struct ring_ctrl	*rx_ctrl;	/* Receive ring control */
 	struct rr_info		*info;		/* Shared info page */
-	struct net_device		*next;
+	dma_addr_t 		rx_ctrl_dma;
+	dma_addr_t 		info_dma;
 	spinlock_t		lock;
 	struct timer_list	timer;
 	u32			cur_rx, cur_cmd, cur_evt;
 	u32			dirty_rx, dirty_tx;
 	u32			tx_full;
 	u32			fw_rev;
-	short			fw_running;
+	volatile short		fw_running;
 	char			name[24];	/* The assigned name */
 	struct net_device_stats stats;
+	struct pci_dev		*pci_dev;
 };
 
 
@@ -837,5 +843,6 @@
 				   unsigned long length);
 static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset);
 static int rr_load_firmware(struct net_device *dev);
-
+static inline void rr_raz_tx(struct rr_private *, struct net_device *);
+static inline void rr_raz_rx(struct rr_private *, struct net_device *);
 #endif /* _RRUNNER_H_ */
diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
--- a/drivers/net/sk98lin/skge.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/net/sk98lin/skge.c	Sun Nov 17 20:30:03 2002
@@ -315,8 +315,6 @@
 
 /* function prototypes ******************************************************/
 static void	FreeResources(struct net_device *dev);
-int		init_module(void);
-void		cleanup_module(void);
 static int	SkGeBoardInit(struct net_device *dev, SK_AC *pAC);
 static SK_BOOL	BoardAllocMem(SK_AC *pAC);
 static void	BoardFreeMem(SK_AC *pAC);
diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/net/skfp/skfddi.c	Sun Nov 17 20:30:02 2002
@@ -197,8 +197,6 @@
 static int autoprobed;
 
 #ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
 static struct net_device *unlink_modules(struct net_device *p);
 static int loading_module = 1;
 #else
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/net/tg3.c	Sun Nov 17 20:30:14 2002
@@ -63,8 +63,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.1"
-#define DRV_MODULE_RELDATE	"Aug 30, 2002"
+#define DRV_MODULE_VERSION	"1.2"
+#define DRV_MODULE_RELDATE	"Nov 14, 2002"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -2377,13 +2377,28 @@
 	/* No BH disabling for tx_lock here.  We are running in BH disabled
 	 * context and TX reclaim runs via tp->poll inside of a software
 	 * interrupt.  Rejoice!
+	 *
+	 * Actually, things are not so simple.  If we are to take a hw
+	 * IRQ here, we can deadlock, consider:
+	 *
+	 *       CPU1		CPU2
+	 *   tg3_start_xmit
+	 *   take tp->tx_lock
+	 *			tg3_timer
+	 *			take tp->lock
+	 *   tg3_interrupt
+	 *   spin on tp->lock
+	 *			spin on tp->tx_lock
+	 *
+	 * So we really do need to disable interrupts when taking
+	 * tx_lock here.
 	 */
-	spin_lock(&tp->tx_lock);
+	spin_lock_irq(&tp->tx_lock);
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		netif_stop_queue(dev);
-		spin_unlock(&tp->tx_lock);
+		spin_unlock_irq(&tp->tx_lock);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
 		return 1;
@@ -2535,7 +2550,7 @@
 		netif_stop_queue(dev);
 
 out_unlock:
-	spin_unlock(&tp->tx_lock);
+	spin_unlock_irq(&tp->tx_lock);
 
 	dev->trans_start = jiffies;
 
@@ -2553,13 +2568,28 @@
 	/* No BH disabling for tx_lock here.  We are running in BH disabled
 	 * context and TX reclaim runs via tp->poll inside of a software
 	 * interrupt.  Rejoice!
+	 *
+	 * Actually, things are not so simple.  If we are to take a hw
+	 * IRQ here, we can deadlock, consider:
+	 *
+	 *       CPU1		CPU2
+	 *   tg3_start_xmit
+	 *   take tp->tx_lock
+	 *			tg3_timer
+	 *			take tp->lock
+	 *   tg3_interrupt
+	 *   spin on tp->lock
+	 *			spin on tp->tx_lock
+	 *
+	 * So we really do need to disable interrupts when taking
+	 * tx_lock here.
 	 */
-	spin_lock(&tp->tx_lock);
+	spin_lock_irq(&tp->tx_lock);
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		netif_stop_queue(dev);
-		spin_unlock(&tp->tx_lock);
+		spin_unlock_irq(&tp->tx_lock);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
 		return 1;
@@ -2665,7 +2695,7 @@
 	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
 		netif_stop_queue(dev);
 
-	spin_unlock(&tp->tx_lock);
+	spin_unlock_irq(&tp->tx_lock);
 
 	dev->trans_start = jiffies;
 
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	Sun Nov 17 20:30:04 2002
+++ b/drivers/net/tg3.h	Sun Nov 17 20:30:04 2002
@@ -1528,7 +1528,7 @@
 	u32				__cookie3;
 };
 
-#define TG3_HW_STATUS_SIZE		0x80
+#define TG3_HW_STATUS_SIZE		0x50
 struct tg3_hw_status {
 	u32				status;
 #define SD_STATUS_UPDATED		0x00000001
diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
--- a/drivers/net/tulip/de4x5.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/net/tulip/de4x5.c	Sun Nov 17 20:30:02 2002
@@ -1034,8 +1034,6 @@
 static int     compact_infoblock(struct net_device *dev, u_char count, u_char *p);
 
 #ifdef MODULE
-int  init_module(void);
-void cleanup_module(void);
 static struct net_device *unlink_modules(struct net_device *p);
 static struct net_device *insert_device(struct net_device *dev, u_long iobase,
 				     int (*init)(struct net_device *));
diff -Nru a/drivers/pci/names.c b/drivers/pci/names.c
--- a/drivers/pci/names.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/pci/names.c	Sun Nov 17 20:30:03 2002
@@ -56,7 +56,7 @@
 {
 	const struct pci_vendor_info *vendor_p = pci_vendor_list;
 	int i = VENDORS;
-	char *name = dev->name;
+	char *name = dev->dev.name;
 
 	do {
 		if (vendor_p->vendor == dev->vendor)
@@ -80,12 +80,15 @@
 		}
 
 		/* Ok, found the vendor, but unknown device */
-		sprintf(name, "PCI device %04x:%04x (%s)", dev->vendor, dev->device, vendor_p->name);
+		sprintf(name, "PCI device %04x:%04x (%." DEVICE_NAME_HALF "s)",
+				dev->vendor, dev->device, vendor_p->name);
 		return;
 
 		/* Full match */
 		match_device: {
-			char *n = name + sprintf(name, "%s %s", vendor_p->name, device_p->name);
+			char *n = name + sprintf(name, "%." DEVICE_NAME_HALF
+					"s %." DEVICE_NAME_HALF "s",
+					vendor_p->name, device_p->name);
 			int nr = device_p->seen + 1;
 			device_p->seen = nr;
 			if (nr > 1)
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/pci/probe.c	Sun Nov 17 20:30:15 2002
@@ -52,7 +52,7 @@
 	for(pos=0; pos<howmany; pos = next) {
 		next = pos+1;
 		res = &dev->resource[pos];
-		res->name = dev->name;
+		res->name = dev->dev.name;
 		reg = PCI_BASE_ADDRESS_0 + (pos << 2);
 		pci_read_config_dword(dev, reg, &l);
 		pci_write_config_dword(dev, reg, ~0);
@@ -112,7 +112,7 @@
 			sz = pci_size(sz, PCI_ROM_ADDRESS_MASK);
 			res->end = res->start + (unsigned long) sz;
 		}
-		res->name = dev->name;
+		res->name = dev->dev.name;
 	}
 }
 
@@ -129,7 +129,7 @@
 		return;
 
 	if (dev->transparent) {
-		printk("Transparent bridge - %s\n", dev->name);
+		printk("Transparent bridge - %s\n", dev->dev.name);
 		for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++)
 			child->resource[i] = child->parent->resource[i];
 		return;
@@ -355,7 +355,7 @@
 	u32 class;
 
 	sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	sprintf(dev->name, "PCI device %04x:%04x", dev->vendor, dev->device);
+	sprintf(dev->dev.name, "PCI device %04x:%04x", dev->vendor, dev->device);
 	INIT_LIST_HEAD(&dev->pools);
 	
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
@@ -447,7 +447,6 @@
 	pci_name_device(dev);
 
 	/* now put in global tree */
-	strcpy(dev->dev.name,dev->name);
 	strcpy(dev->dev.bus_id,dev->slot_name);
 
 	device_register(&dev->dev);
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pci/proc.c	Sun Nov 17 20:30:14 2002
@@ -511,7 +511,7 @@
 		seq_printf(m, "    %s", class);
 	else
 		seq_printf(m, "    Class %04x", class_rev >> 16);
-	seq_printf(m, ": %s (rev %d).\n", dev->name, class_rev & 0xff);
+	seq_printf(m, ": %s (rev %d).\n", dev->dev.name, class_rev & 0xff);
 
 	if (dev->irq)
 		seq_printf(m, "      IRQ %d.\n", dev->irq);
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/pci/quirks.c	Sun Nov 17 20:30:02 2002
@@ -203,7 +203,7 @@
 	if (region) {
 		struct resource *res = dev->resource + nr;
 
-		res->name = dev->name;
+		res->name = dev->dev.name;
 		res->start = region;
 		res->end = region + size - 1;
 		res->flags = IORESOURCE_IO;
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/pci/setup-bus.c	Sun Nov 17 20:30:15 2002
@@ -105,7 +105,7 @@
 	pcibios_fixup_pbus_ranges(bus, &ranges);
 
 	DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n",
-			bus->number, bridge->name));
+			bus->number, bridge->dev.name));
 
 	/* Set up the top and bottom of the PCI I/O segment for this bus. */
 	if (bus->resource[0]->flags & IORESOURCE_IO) {
diff -Nru a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
--- a/drivers/pci/setup-irq.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pci/setup-irq.c	Sun Nov 17 20:30:14 2002
@@ -53,7 +53,7 @@
 		irq = 0;
 	dev->irq = irq;
 
-	DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
+	DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n", dev->dev.name, dev->irq));
 
 	/* Always tell the device, so the driver knows what is
 	   the real IRQ to use; the device does not use it. */
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/pci/setup-res.c	Sun Nov 17 20:30:15 2002
@@ -46,11 +46,11 @@
 		if (err) {
 			printk(KERN_ERR "PCI: Address space collision on "
 			       "region %d of device %s [%lx:%lx]\n",
-			       resource, dev->name, res->start, res->end);
+			       resource, dev->dev.name, res->start, res->end);
 		}
 	} else {
 		printk(KERN_ERR "PCI: No parent found for region %d "
-		       "of device %s\n", resource, dev->name);
+		       "of device %s\n", resource, dev->dev.name);
 	}
 
 	return err;
@@ -155,7 +155,7 @@
 		if (!r_align) {
 			printk(KERN_WARNING "PCI: Ignore bogus resource %d "
 					    "[%lx:%lx] of %s\n",
-					    i, r->start, r->end, dev->name);
+					    i, r->start, r->end, dev->dev.name);
 			continue;
 		}
 		r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/pcmcia/cardbus.c	Sun Nov 17 20:30:12 2002
@@ -284,7 +284,6 @@
 
 		pci_setup_device(dev);
 
-		strcpy(dev->dev.name, dev->name);
 		strcpy(dev->dev.bus_id, dev->slot_name);
 
 		/* FIXME: Do we need to enable the expansion ROM? */
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/pcmcia/cs.c	Sun Nov 17 20:30:12 2002
@@ -40,7 +40,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
--- a/drivers/pcmcia/i82092.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/pcmcia/i82092.c	Sun Nov 17 20:30:16 2002
@@ -15,6 +15,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/pcmcia/i82365.c	Sun Nov 17 20:30:15 2002
@@ -47,6 +47,7 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -76,12 +77,12 @@
 #define DEBUG(n, args...) do { } while (0)
 #endif
 
-static void irq_count(int, void *, struct pt_regs *);
+static void i365_count_irq(int, void *, struct pt_regs *);
 static inline int _check_irq(int irq, int flags)
 {
-    if (request_irq(irq, irq_count, flags, "x", irq_count) != 0)
+    if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
 	return -1;
-    free_irq(irq, irq_count);
+    free_irq(irq, i365_count_irq);
     return 0;
 }
 
@@ -533,7 +534,7 @@
 static volatile u_int irq_hits;
 static u_short irq_sock;
 
-static void irq_count(int irq, void *dev, struct pt_regs *regs)
+static void i365_count_irq(int irq, void *dev, struct pt_regs *regs)
 {
     i365_get(irq_sock, I365_CSC);
     irq_hits++;
@@ -543,13 +544,13 @@
 static u_int __init test_irq(u_short sock, int irq)
 {
     DEBUG(2, "  testing ISA irq %d\n", irq);
-    if (request_irq(irq, irq_count, 0, "scan", irq_count) != 0)
+    if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
 	return 1;
     irq_hits = 0; irq_sock = sock;
     __set_current_state(TASK_UNINTERRUPTIBLE);
     schedule_timeout(HZ/100);
     if (irq_hits) {
-	free_irq(irq, irq_count);
+	free_irq(irq, i365_count_irq);
 	DEBUG(2, "    spurious hit!\n");
 	return 1;
     }
@@ -559,7 +560,7 @@
     i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
     udelay(1000);
 
-    free_irq(irq, irq_count);
+    free_irq(irq, i365_count_irq);
 
     /* mask all interrupts */
     i365_set(sock, I365_CSCINT, 0);
diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
--- a/drivers/pcmcia/rsrc_mgr.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pcmcia/rsrc_mgr.c	Sun Nov 17 20:30:14 2002
@@ -36,7 +36,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/types.h>
diff -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
--- a/drivers/pcmcia/yenta.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pcmcia/yenta.c	Sun Nov 17 20:30:14 2002
@@ -2,6 +2,11 @@
  * Regular lowlevel cardbus driver ("yenta")
  *
  * (C) Copyright 1999, 2000 Linus Torvalds
+ *
+ * Changelog:
+ * Aug 2002: Manfred Spraul <manfred@colorfullife.com>
+ * 	Dynamically adjust the size of the bridge resource
+ * 	
  */
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -585,7 +590,7 @@
 	/* It's OK to overwrite this now */
 	INIT_WORK(&socket->tq_task, yenta_bh, socket);
 
-	if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) {
+	if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
 		/* No IRQ or request_irq failed. Poll */
 		socket->cb_irq = 0; /* But zero is a valid IRQ number. */
 		socket->poll_timer.function = yenta_interrupt_wrapper;
@@ -702,12 +707,24 @@
 	return 0;
 }
 
+/*
+ * Use an adaptive allocation for the memory resource,
+ * sometimes the memory behind pci bridges is limited:
+ * 1/8 of the size of the io window of the parent.
+ * max 4 MB, min 16 kB.
+ */
+#define BRIDGE_MEM_MAX 4*1024*1024
+#define BRIDGE_MEM_MIN 16*1024
+
+#define BRIDGE_IO_MAX 256
+#define BRIDGE_IO_MIN 32
+
 static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
 {
 	struct pci_bus *bus;
 	struct resource *root, *res;
 	u32 start, end;
-	u32 align, size, min, max;
+	u32 align, size, min;
 	unsigned offset;
 	unsigned mask;
 
@@ -733,24 +750,51 @@
 	if (start && end > start) {
 		res->start = start;
 		res->end = end;
-		request_resource(root, res);
-		return;
+		if (request_resource(root, res) == 0)
+			return;
+		printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n",
+				socket->dev->slot_name, nr);
+		res->start = res->end = 0;
 	}
 
-	align = size = 4*1024*1024;
-	min = PCIBIOS_MIN_MEM; max = ~0U;
 	if (type & IORESOURCE_IO) {
 		align = 1024;
-		size = 256;
-		min = 0x4000;
-		max = 0xffff;
+		size = BRIDGE_IO_MAX;
+		min = BRIDGE_IO_MIN;
+		start = PCIBIOS_MIN_IO;
+		end = ~0U;
+	} else {
+		unsigned long avail = root->end - root->start;
+		int i;
+		size = BRIDGE_MEM_MAX;
+		if (size > avail/8) {
+			size=(avail+1)/8;
+			/* round size down to next power of 2 */
+			i = 0;
+			while ((size /= 2) != 0)
+				i++;
+			size = 1 << i;
+		}
+		if (size < BRIDGE_MEM_MIN)
+			size = BRIDGE_MEM_MIN;
+		min = BRIDGE_MEM_MIN;
+		align = size;
+		start = PCIBIOS_MIN_MEM;
+		end = ~0U;
 	}
-		
-	if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0)
-		return;
-
-	config_writel(socket, offset, res->start);
-	config_writel(socket, offset+4, res->end);
+	
+	do {
+		if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) {
+			config_writel(socket, offset, res->start);
+			config_writel(socket, offset+4, res->end);
+			return;
+		}
+		size = size/2;
+		align = size;
+	} while (size >= min);
+	printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
+			socket->dev->slot_name, type);
+	res->start = res->end = 0;
 }
 
 /*
@@ -765,6 +809,20 @@
 }
 
 /*
+ * Free the bridge mappings for the device..
+ */
+static void yenta_free_resources(pci_socket_t *socket)
+{
+	int i;
+	for (i=0;i<4;i++) {
+		struct resource *res;
+		res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
+		if (res->start != 0 && res->end != 0)
+			release_resource(res);
+		res->start = res->end = 0;
+	}
+}
+/*
  * Close it down - release our resources and go home..
  */
 static void yenta_close(pci_socket_t *sock)
@@ -780,6 +838,7 @@
 
 	if (sock->base)
 		iounmap(sock->base);
+	yenta_free_resources(sock);
 }
 
 #include "ti113x.h"
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pnp/isapnp/core.c	Sun Nov 17 20:30:14 2002
@@ -1152,7 +1152,7 @@
 				continue;
 			for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
 				struct pci_dev *dev = pci_dev_b(devlist);
-				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
+				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->dev.name[0]?card->name:"Unknown");
 			}
 		}
 	}
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/pnp/resource.c	Sun Nov 17 20:30:14 2002
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <asm/io.h>
diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/s390/block/dasd.c	Sun Nov 17 20:30:14 2002
@@ -244,6 +244,7 @@
 		kfree(device);
 		return (dasd_device_t *) gdp;
 	}
+	gdp->private_data = device;
 	device->gdp = gdp;
 
 	dasd_init_chunklist(&device->ccw_chunks, device->ccw_mem, PAGE_SIZE*2);
@@ -282,7 +283,7 @@
 static inline int
 dasd_state_new_to_known(dasd_device_t *device)
 {
-	char buffer[5];
+	char buffer[10];
 	dasd_devmap_t *devmap;
 	umode_t devfs_perm;
 	devfs_handle_t dir;
@@ -302,8 +303,8 @@
 		return rc;
 
 	/* Add a proc directory and the dasd device entry to devfs. */
-	sprintf(buffer, "%04x", device->devinfo.devno);
-	dir = devfs_mk_dir(dasd_devfs_handle, buffer, device);
+	sprintf(buffer, "dasd/%04x", device->devinfo.devno);
+	dir = devfs_mk_dir(NULL, buffer, NULL);
 	device->gdp->de = dir;
 	if (devmap->features & DASD_FEATURE_READONLY)
 		devfs_perm = S_IFBLK | S_IRUSR;
@@ -2098,7 +2099,7 @@
 			major(inp->i_rdev), minor(inp->i_rdev));
 		return -EPERM;
 	}
-	devmap = dasd_devmap_from_kdev(inp->i_rdev);
+	devmap = dasd_devmap_from_bdev(inp->i_bdev);
 	device = (devmap != NULL) ?
 		dasd_get_device(devmap) : ERR_PTR(-ENODEV);
 	if (IS_ERR(device)) {
@@ -2134,7 +2135,7 @@
 	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 
-	devmap = dasd_devmap_from_kdev(inp->i_rdev);
+	devmap = dasd_devmap_from_bdev(inp->i_bdev);
 	device = (devmap != NULL) ?
 		dasd_get_device(devmap) : ERR_PTR(-ENODEV);
 	if (IS_ERR(device)) {
diff -Nru a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
--- a/drivers/s390/block/dasd_devmap.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/s390/block/dasd_devmap.c	Sun Nov 17 20:30:14 2002
@@ -430,11 +430,12 @@
 }
 
 /*
- * Find the devmap for a device corresponding to a kdev.
+ * Find the devmap for a device corresponding to a block_device.
  */
 dasd_devmap_t *
-dasd_devmap_from_kdev(kdev_t kdev)
+dasd_devmap_from_bdev(struct block_device *bdev)
 {
+	kdev_t kdev = to_kdev_t(bdev->bd_dev);
 	int devindex;
 
 	/* Find the devindex for kdev. */
@@ -449,15 +450,6 @@
 }
 
 /*
- * Find the devmap for a device corresponding to a block_device.
- */
-dasd_devmap_t *
-dasd_devmap_from_bdev(struct block_device *bdev)
-{
-	return dasd_devmap_from_kdev(to_kdev_t(bdev->bd_dev));
-}
-
-/*
  * Find the device structure for device number devno. If it does not
  * exists yet, allocate it. Increase the reference counter in the device
  * structure and return a pointer to it.
@@ -535,6 +527,5 @@
 EXPORT_SYMBOL(dasd_devmap_from_devno);
 EXPORT_SYMBOL(dasd_devmap_from_devindex);
 EXPORT_SYMBOL(dasd_devmap_from_irq);
-EXPORT_SYMBOL(dasd_devmap_from_kdev);
 EXPORT_SYMBOL(dasd_get_device);
 EXPORT_SYMBOL(dasd_put_device);
diff -Nru a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
--- a/drivers/s390/block/dasd_int.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/s390/block/dasd_int.h	Sun Nov 17 20:30:15 2002
@@ -464,7 +464,6 @@
 dasd_devmap_t *dasd_devmap_from_devno(int);
 dasd_devmap_t *dasd_devmap_from_devindex(int);
 dasd_devmap_t *dasd_devmap_from_irq(int);
-dasd_devmap_t *dasd_devmap_from_kdev(kdev_t);
 dasd_devmap_t *dasd_devmap_from_bdev(struct block_device *bdev);
 dasd_device_t *dasd_get_device(dasd_devmap_t *);
 void dasd_put_device(dasd_devmap_t *);
diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
--- a/drivers/s390/block/dasd_ioctl.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/s390/block/dasd_ioctl.c	Sun Nov 17 20:30:14 2002
@@ -241,14 +241,13 @@
 	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 	format_data_t fdata;
-	int partn, rc;
+	int rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 	if (!args)
 		return -EINVAL;
 	/* fdata == NULL is no longer a valid arg to dasd_format ! */
-	partn = MINOR(bdev->bd_dev) & DASD_PARTN_MASK;
 	devmap = dasd_devmap_from_bdev(bdev);
 	device = (devmap != NULL) ?
 		dasd_get_device(devmap) : ERR_PTR(-ENODEV);
@@ -260,7 +259,7 @@
 		rc = -EROFS;
 	else if (copy_from_user(&fdata, (void *) args, sizeof (format_data_t)))
 		rc = -EFAULT;
-	else if (partn != 0) {
+	else if (bdev != bdev->bd_contains) {
 		DEV_MESSAGE(KERN_WARNING, device, "%s",
 			    "Cannot low-level format a partition");
 		rc = -EINVAL;
@@ -428,7 +427,7 @@
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
-	if (MINOR(bdev->bd_dev) & DASD_PARTN_MASK)
+	if (bdev != bdev->bd_contains)
 		// ro setting is not allowed for partitions
 		return -EINVAL;
 	if (get_user(intval, (int *) args))
diff -Nru a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
--- a/drivers/s390/block/dasd_proc.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/s390/block/dasd_proc.c	Sun Nov 17 20:30:04 2002
@@ -65,7 +65,6 @@
 			vfree (info->data);
 		kfree (info);
 	}
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -223,12 +222,10 @@
 	int size, len;
 	int devindex;
 
-	MOD_INC_USE_COUNT;
 	info = (tempinfo_t *) kmalloc(sizeof (tempinfo_t), GFP_KERNEL);
 	if (info == NULL) {
 		MESSAGE(KERN_WARNING, "%s",
 			"No memory available for data (tempinfo)");
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 
 	}
@@ -239,7 +236,6 @@
 		MESSAGE(KERN_WARNING, "%s",
 			"No memory available for data (info->data)");
 		kfree(info);
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	file->private_data = (void *) info;
@@ -266,6 +262,7 @@
 }
 
 static struct file_operations dasd_devices_file_ops = {
+	owner:THIS_MODULE,
 	read:dasd_generic_read,		/* read */
 	write:dasd_devices_write,	/* write */
 	open:dasd_devices_open,		/* open */
@@ -299,12 +296,10 @@
 	int shift;
 #endif
 
-	MOD_INC_USE_COUNT;
 	info = (tempinfo_t *) kmalloc(sizeof (tempinfo_t), GFP_KERNEL);
 	if (info == NULL) {
 		MESSAGE(KERN_WARNING, "%s",
 			"No memory available for data (tempinfo)");
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 
@@ -317,7 +312,6 @@
 			"No memory available for data (info->data)");
 		kfree(info);
 		file->private_data = NULL;
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 #ifdef CONFIG_DASD_PROFILE
@@ -422,6 +416,7 @@
 }
 
 static struct file_operations dasd_statistics_file_ops = {
+	owner:	THIS_MODULE,
 	read:	dasd_generic_read,	/* read */
 	write:	dasd_statistics_write,	/* write */
 	open:	dasd_statistics_open,	/* open */
diff -Nru a/drivers/s390/char/tape.c b/drivers/s390/char/tape.c
--- a/drivers/s390/char/tape.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/s390/char/tape.c	Sun Nov 17 20:30:14 2002
@@ -199,6 +199,7 @@
 
 static struct file_operations tape_proc_devices_file_ops =
 {
+	owner:THIS_MODULE,
 	read:tape_proc_devices_read,	/* read */
 	open:tape_proc_devices_open,	/* open */
 	release:tape_proc_devices_release,	/* close */
@@ -239,12 +240,9 @@
 	long lockflags,lockflags2;
 	tape_ccw_req_t *treq;
 
-	MOD_INC_USE_COUNT;
-
 	procinfo = kmalloc (sizeof(tape_procinfo_t),GFP_KERNEL);
 	if (!procinfo){
 		rc = -ENOMEM;
-		MOD_DEC_USE_COUNT;
 		goto out_no_lock;
 	}
 
@@ -349,7 +347,6 @@
 	tape_procinfo_t *p_info = (tape_procinfo_t *) file->private_data;
         vfree(p_info->data);
         kfree (p_info);
-        MOD_DEC_USE_COUNT;
 	return rc;
 }
 
diff -Nru a/drivers/s390/char/tapechar.c b/drivers/s390/char/tapechar.c
--- a/drivers/s390/char/tapechar.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/s390/char/tapechar.c	Sun Nov 17 20:30:13 2002
@@ -40,6 +40,7 @@
  */
 static struct file_operations tape_fops =
 {
+	owner:THIS_MODULE,
 	read:tapechar_read,
 	write:tapechar_write,
 	ioctl:tapechar_ioctl,
@@ -548,8 +549,6 @@
 	int  rc = 0;
 	long lockflags;
 
-	MOD_INC_USE_COUNT;
-
 	tape_sprintf_event (tape_dbf_area,6,"c:open: %x\n",td->first_minor); 
 
 	inode = filp->f_dentry->d_inode;
@@ -580,7 +579,6 @@
 	s390irq_spin_unlock_irqrestore(td->devinfo.irq,lockflags);
 error:
 	if(rc != 0){
-		MOD_DEC_USE_COUNT;
 		if (td!=NULL)
 			tape_put_device(td);
 	}
@@ -625,6 +623,5 @@
 	if ( td->discipline->owner )
 		__MOD_DEC_USE_COUNT(td->discipline->owner);
 	tape_put_device(td);
-	MOD_DEC_USE_COUNT;
 	return rc;
 }
diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c
--- a/drivers/s390/char/tubfs.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/s390/char/tubfs.c	Sun Nov 17 20:30:14 2002
@@ -42,8 +42,8 @@
 {
 	char name[16];
 
-	sprintf(name, "tub%.4x", tubp->devno);
-	devfs_register(fs3270_devfs_dir, name, DEVFS_FL_DEFAULT,
+	sprintf(name, "3270/tub%.4x", tubp->devno);
+	devfs_register(NULL, name, DEVFS_FL_DEFAULT,
 		       IBM_FS3270_MAJOR, tubp->minor,
 		       S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL);
 	sprintf(name, "tty%.4x", tubp->devno);
@@ -53,16 +53,8 @@
 
 void fs3270_devfs_unregister(tub_t *tubp)
 {
-	char name[16];
-
-	sprintf(name, "tub%.4x", tubp->devno);
-	devfs_find_and_unregister(fs3270_devfs_dir, name,
-				  IBM_FS3270_MAJOR, tubp->minor,
-				  DEVFS_SPECIAL_CHR, 0);
-	sprintf(name, "tty%.4x", tubp->devno);
-	devfs_find_and_unregister(fs3270_devfs_dir, name,
-				  IBM_TTY3270_MAJOR, tubp->minor,
-				  DEVFS_SPECIAL_CHR, 0);
+	devfs_remove("3270/tub%.4x", tubp->devno);
+	devfs_remove("3270/tty%.4x", tubp->devno);
 }
 #endif
 
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/scsi/53c700.c	Sun Nov 17 20:30:03 2002
@@ -896,7 +896,7 @@
 			NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
 			hostdata->tag_negotiated &= ~(1<<SCp->target);
 			SCp->device->tagged_supported = 0;
-			scsi_deactivate_tcq(SCp->device);
+			scsi_deactivate_tcq(SCp->device, host->cmd_per_lun);
 		} else {
 			printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n",
 			       host->host_no, pun, lun,
@@ -1813,8 +1813,6 @@
 		 * NOTE: There is a danger here: the mid layer supports
 		 * tag queuing per LUN.  We only support it per PUN because
 		 * of potential reselection issues */
-		printk(KERN_NOTICE "scsi%d: (%d:%d) beginning blk layer TCQ\n",
-		       SCp->device->host->host_no, SCp->target, SCp->lun);
 		scsi_activate_tcq(SCp->device, NCR_700_MAX_TAGS);
 	}
 
diff -Nru a/drivers/scsi/ChangeLog b/drivers/scsi/ChangeLog
--- a/drivers/scsi/ChangeLog	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2023 +0,0 @@
-Sat Jan 18 15:51:45 1997  Richard Henderson  <rth@tamu.edu>
-
-	* Don't play with usage_count directly, instead hand around
-	the module header and use the module macros.
-
-Fri May 17 00:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
-
-	* BusLogic Driver Version 2.0.3 Released.
-
-Tue Apr 16 21:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
-
-	* BusLogic Driver Version 1.3.2 Released.
-
-Sun Dec 31 23:26:00 1995  Leonard N. Zubkoff <lnz@dandelion.com>
-
-	* BusLogic Driver Version 1.3.1 Released.
-
-Fri Nov 10 15:29:49 1995  Leonard N. Zubkoff <lnz@dandelion.com>
-
-	* Released new BusLogic driver.
-
-Wed Aug  9 22:37:04 1995  Andries Brouwer  <aeb@cwi.nl>
-
-	As a preparation for new device code, separated the various
-	functions the request->dev field had into the device proper,
-	request->rq_dev and a status field request->rq_status.
-
-	The 2nd argument of bios_param is now a kdev_t.
-
-Wed Jul 19 10:43:15 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-        * scsi.c (scsi_proc_info): /proc/scsi/scsi now also lists all
-	attached devices.
-
-	* scsi_proc.c (proc_print_scsidevice): Added. Used by scsi.c and
-	eata_dma_proc.c to produce some device info for /proc/scsi.
-
-	* eata_dma.c (eata_queue)(eata_int_handler)(eata_scsi_done):
-	Changed handling of internal SCSI commands send to the HBA.
-
-
-Wed Jul 19 10:09:17 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.11 released.
-
-	* eata_dma.c (eata_queue)(eata_int_handler): Added code to do
-	command latency measurements if requested by root through
-	/proc/scsi interface.
-	Throughout Use HZ constant for time references.
-
-	* eata_pio.c: Use HZ constant for time references.
-
-	* aic7xxx.c, aic7xxx.h, aic7xxx_asm.c: Changed copyright from BSD
-	to GNU style.
-
-	* scsi.h: Added READ_12 command opcode constant
-
-Wed Jul 19 09:25:30 1995  Michael Neuffer <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.10 released.
-
-	* scsi_proc.c (dispatch_scsi_info): Removed unused variable.
-
-Wed Jul 19 09:25:30 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.9 released.
-
-	* scsi.c Blacklist concept expanded to 'support' more device
-	deficiencies. blacklist[] renamed to device_list[]
-	(scan_scsis): Code cleanup.
-
-	* scsi_debug.c (scsi_debug_proc_info): Added support to control
-	device lockup simulation via /proc/scsi interface.
-
-
-Wed Jul 19 09:22:34 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.7 released.
-
-	* scsi_proc.c: Fixed a number of bugs in directory handling
-
-Wed Jul 19 09:18:28 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.5 released.
-
-	* Native wide, multichannel and /proc/scsi support now in official
-	kernel distribution.
-
-        * scsi.c/h, hosts.c/h et al reindented to increase readability
-	(especially on 80 column wide terminals).
-
-	* scsi.c, scsi_proc.c, ../../fs/proc/inode.c: Added
-	/proc/scsi/scsi which allows root to scan for hotplugged devices.
-
-	* scsi.c (scsi_proc_info): Added, to support /proc/scsi/scsi.
-	(scan_scsis): Added some 'spaghetti' code to allow scanning for
-	single devices.
-	
-
-Thu Jun 20 15:20:27 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-        * proc.c: Renamed to scsi_proc.c
-
-Mon Jun 12 20:32:45 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* Linux 1.3.0 released.
-
-Mon May 15 19:33:14 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* scsi.c: Added native multichannel and wide scsi support.
-
-	* proc.c (dispatch_scsi_info) (build_proc_dir_hba_entries):
-	Updated /proc/scsi interface.
-
-Thu May  4 17:58:48 1995  Michael Neuffer  <neuffer@goofy.zdv.uni-mainz.de>
-
-	* sd.c (requeue_sd_request): Zero out the scatterlist only if
-	scsi_malloc returned memory for it.
-
-	* eata_dma.c (register_HBA) (eata_queue): Add support for
-	large scatter/gather tables and set use_clustering accordingly
-
-	* hosts.c: Make use_clustering changeable in the Scsi_Host structure.
-
-Wed Apr 12 15:25:52 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.2.5 released.
-
-	* buslogic.c: Update to version 1.15 (From Leonard N. Zubkoff).
-	Fixed interrupt routine to avoid races when handling multiple
-	complete commands per interrupt.  Seems to come up with faster
-	cards.
-
-	* eata_dma.c: Update to 2.3.5r. Modularize. Improved error handling
-        throughout and fixed bug interrupt routine which resulted in shifted
-        status bytes. Added blink LED state checks for ISA and EISA HBAs.
-        Memory management bug seems to have disappeared ==> increasing
-        C_P_L_CURRENT_MAX to 16 for now. Decreasing C_P_L_DIV to 3 for
-        performance reasons.
-
-	* scsi.c: If we get a FMK, EOM, or ILI when attempting to scan
-	the bus, assume that it was just noise on the bus, and ignore
-	the device.
-
-	* scsi.h: Update and add a bunch of missing commands which we
-	were never using.
-
-	* sd.c: Use restore_flags in do_sd_request - this may result in
-	latency conditions, but it gets rid of races and crashes.
-	Do not save flags again when searching for a second command to
-	queue.
-
-	* st.c: Use bytes, not STP->buffer->buffer_size when reading
-	from tape.
-
-
-Tue Apr  4 09:42:08 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.2.4 released.
-
-	* st.c: Fix typo - restoring wrong flags.
-
-Wed Mar 29 06:55:12 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.2.3 released.
-
-	* st.c: Perform some waiting operations with interrupts off.
-	Is this correct???
-
-Wed Mar 22 10:34:26 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.2.2 released.
-
-	* aha152x.c: Modularize.  Add support for PCMCIA.
-
-	* eata.c: Update to version 2.0.  Fixed bug preventing media
-	detection.  If scsi_register_host returns NULL, fail gracefully.
-
-	* scsi.c: Detect as NEC (for photo-cd purposes) for the 84
-	and 25 models as "NEC_OLDCDR".
-
-	* scsi.h: Add define for NEC_OLDCDR
-
-	* sr.c: Add handling for NEC_OLDCDR.  Treat as unknown.
-
-	* u14-34f.c: Update to version 2.0.  Fixed same bug as in
-	eata.c.
-
-
-Mon Mar  6 11:11:20 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.2.0 released.  Yeah!!!
-
-	* Minor spelling/punctuation changes throughout.  Nothing
-	substantive.
-
-Mon Feb 20 21:33:03 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.95 released.
-
-	* qlogic.c: Update to version 0.41.
-
-	* seagate.c: Change some message to be more descriptive about what
-	we detected.
-
-	* sr.c: spelling/whitespace changes.
-
-Mon Feb 20 21:33:03 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.94 released.
-
-Mon Feb 20 08:57:17 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.93 released.
-
-	* hosts.h: Change io_port to long int from short.
-
- 	* 53c7,8xx.c: crash on AEN fixed, SCSI reset is no longer a NOP,
- 	  NULL pointer panic on odd UDCs fixed, two bugs in diagnostic output
- 	  fixed, should initialize correctly if left running, now loadable,
-  	  new memory allocation, extraneous diagnostic output suppressed,
- 	  splx() replaced with save/restore flags. [ Drew ]
-
-	* hosts.c, hosts.h, scsi_ioctl.c, sd.c, sd_ioctl.c, sg.c, sr.c,
-	sr_ioctl.c: Add special junk at end that Emacs will use for
-	formatting the file.
-
-	* qlogic.c: Update to v0.40a.  Improve parity handling.
-
-	* scsi.c: Add Hitachi DK312C to blacklist.  Change "};" to "}" in
-	many places.  Use scsi_init_malloc to get command block - may
-	need this to be dma compatible for some host adapters.
-	Restore interrupts after unregistering a host.
-
-	* sd.c: Use sti instead of restore flags - causes latency problems.
-
-	* seagate.c: Use controller_type to determine string used when
-	registering irq.
-
-	* sr.c: More photo-cd hacks to make sure we get the xa stuff right.
-	* sr.h, sr.c: Change is_xa to xa_flags field.
-
-	* st.c: Disable retries for write operations.
-
-Wed Feb 15 10:52:56 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.92 released.
-
-	* eata.c: Update to 1.17.
-
-	* eata_dma.c: Update to 2.31a. Add more support for /proc/scsi.
-        Continuing modularization. Less crashes because of the bug in the
-        memory management ==> increase C_P_L_CURRENT_MAX to 10
-        and decrease C_P_L_DIV to 4.
-
-	* hosts.c: If we remove last host registered, reuse host number.
-	When freeing memory from host being deregistered, free extra_bytes
-	too.
-
-	* scsi.c (scan_scsis): memset(SDpnt, 0) and set SCmd.device to SDpnt.
-	Change memory allocation to work around bugs in __get_dma_pages.
-	Do not free host if usage count is not zero (for modules).
-
-	* sr_ioctl.c: Increase IOCTL_TIMEOUT to 3000.
-
-	* st.c: Allow for ST_EXTRA_DEVS in st data structures.
-
-	* u14-34f.c: Update to 1.17.
-
-Thu Feb  9 10:11:16 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.91 released.
-
-	* eata.c: Update to 1.16.  Use wish_block instead of host->block.
-
-	* hosts.c: Initialize wish_block to 0.
-
-	* hosts.h: Add wish_block.
-
-	* scsi.c: Use wish_block as indicator that the host should be added
-	to block list.
-
-	* sg.c: Add SG_EXTRA_DEVS to number of slots.
-
-	* u14-34f.c: Use wish_block.
-
-Tue Feb  7 11:46:04 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.90 released.
-
-	* eata.c: Change naming from eata_* to eata2x_*.  Now at vers 1.15.
-	Update interrupt handler to take pt_regs as arg.  Allow blocking
-	even if loaded as module.  Initialize target_time_out array.
-	Do not put sti(); in timing loop.
-
-	* hosts.c: Do not reuse host numbers.
-	Use scsi_make_blocked_list to generate blocking list.
-
-	* script_asm.pl:  Beats me.  Don't know perl.  Something to do with
-	phase index.
-
-	* scsi.c (scsi_make_blocked_list): New function - code copied from
-	hosts.c.
-
-	* scsi.c: Update code to disable photo CD for Toshiba cdroms.
-	Use just manufacturer name, not model number.
-
-	* sr.c: Fix setting density for Toshiba drives.
-
-	* u14-34f.c: Clear target_time_out array during reset.
-
-Wed Feb  1 09:20:45 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.89 released.
-
-	* Makefile, u14-34f.c: Modularize.
-
-	* Makefile, eata.c: Modularize.  Now version 1.14
-
-	* NCR5380.c: Update interrupt handler with new arglist.  Minor
-	cleanups.
-
-	* eata_dma.c: Begin to modularize.  Add hooks for /proc/scsi.
-	New version 2.3.0a. Add code in interrupt handler to allow
-        certain CDROM drivers to be detected which return a
-        CHECK_CONDITION during SCSI bus scan. Add opcode check to get
-        all DATA IN and DATA OUT phases right. Utilize HBA_interpret flag.
-	Improvements in HBA identification. Various other minor stuff.
-
-	* hosts.c: Initialize ->dma_channel and ->io_port when registering
-	a new host.
-
-	* qlogic.c: Modularize and add PCMCIA support.
-
-	* scsi.c: Add Hitachi to blacklist.
-
-	* scsi.c: Change default to no lun scan (too many problem devices).
-
-	* scsi.h: Define QUEUE_FULL condition.
-
-	* sd.c: Do not check for non-existent partition until after
-	new media check.
-
-	* sg.c: Undo previous change which was wrong.
-
-	* sr_ioctl.c: Increase IOCTL_TIMEOUT to 2000.
-
-	* st.c: Patches from Kai - improve filemark handling.
-
-Tue Jan 31 17:32:12 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.88 released.
-
-	* Throughout - spelling/grammar fixups.
-
-	* scsi.c: Make sure that all buffers are 16 byte aligned - some
-	drivers (buslogic) need this.
-
-	* scsi.c (scan_scsis): Remove message printed.
-
-	* scsi.c (scsi_init): Move message here.
-
-Mon Jan 30 06:40:25 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.87 released.
-
-	* sr.c: Photo-cd related changes. (Gerd Knorr??).
-
-	* st.c: Changes from Kai related to EOM detection.
-
-Mon Jan 23 23:53:10 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.86 released.
-
-	* 53c7,8xx.h: Change SG size to 127.
-
-	* eata_dma: Update to version 2.10i. Remove bug in the registration
-        of multiple HBAs and channels. Minor other improvements and stylistic
-        changes.
-
-	* scsi.c: Test for Toshiba XM-3401TA and exclude from detection
-	as toshiba drive - photo cd does not work with this drive.
-
-	* sr.c:  Update photocd code.
-
-Mon Jan 23 23:53:10 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.85 released.
-
-	* st.c, st_ioctl.c, sg.c, sd_ioctl.c, scsi_ioctl.c, hosts.c:
-	include linux/mm.h
-
-	* qlogic.c, buslogic.c, aha1542.c: Include linux/module.h.
-
-Sun Jan 22 22:08:46 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.84 released.
-
-	* Makefile: Support for loadable QLOGIC boards.
-
-	* aha152x.c: Update to version 1.8 from Juergen.
-
-	* eata_dma.c: Update from Michael Neuffer.
-        Remove hard limit of 2 commands per lun and make it better
-        configurable. Improvements in HBA identification.
-
-	* in2000.c: Fix biosparam to support large disks.
-
-	* qlogic.c: Minor changes (change sti -> restore_flags).
-
-Wed Jan 18 23:33:09 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.83 released.
-
-	* aha1542.c(aha1542_intr_handle): Use arguments handed down to find
-	which irq.
-
-	* buslogic.c: Likewise.
-
-	* eata_dma.c: Use min of 2 cmd_per_lun for OCS_enabled boards.
-
-	* scsi.c: Make RECOVERED_ERROR a SUGGEST_IS_OK.
-
-	* sd.c: Fail if we are opening a non-existent partition.
-
-	* sr.c: Bump SR_TIMEOUT to 15000.
-	Do not probe for media size at boot time(hard on changers).
-	Flag device as needing sector size instead.
-
-	* sr_ioctl.c: Remove CDROMMULTISESSION_SYS ioctl.
-
-	* ultrastor.c: Fix bug in call to ultrastor_interrupt (wrong #args).
-
-Mon Jan 16 07:18:23 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.82 released.
-
-	Throughout.
-	- Change all interrupt handlers to accept new calling convention.
-	In particular, we now receive the irq number as one of the arguments.
-
-	* More minor spelling corrections in some of the new files.
-
-	* aha1542.c, buslogic.c: Clean up interrupt handler a little now
-	that we receive the irq as an arg.
-
-	* aha274x.c: s/snarf_region/request_region/
-
-	* eata.c: Update to version 1.12.   Fix some comments and display a
-	message if we cannot reserve the port addresses.
-
-	* u14-34f.c: Update to version 1.13.   Fix some comments and display a
-	message if we cannot reserve the port addresses.
-
-	* eata_dma.c: Define get_board_data function (send INQUIRY command).
-	Use to improve detection of variants of different DPT boards.  Change
-	version subnumber to "0g".
-
-	* fdomain.c:  Update to version 5.26.  Improve detection of some boards
-	repackaged by IBM.
-
-	* scsi.c (scsi_register_host): Change "name" to const char *.
-
-	* sr.c: Fix problem in set mode command for Toshiba drives.
-
-	* sr.c: Fix typo from patch 81.
-
-Fri Jan 13 12:54:46 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.81 released.  Codefreeze for 1.2 release announced.
-
-	Big changes here.
-
-	* eata_dma.*: New files from Michael Neuffer.
-	(neuffer@goofy.zdv.uni-mainz.de).  Should support
-	all eata/dpt cards.
-
-	* hosts.c, Makefile: Add eata_dma.
-
-	* README.st: Document MTEOM.
-
-	Patches from me (ERY) to finish support for low-level loadable scsi.
-	It now works, and is actually useful.
-
-	* Throughout - add new argument to scsi_init_malloc that takes an
-	additional parameter.  This is used as a priority to kmalloc,
-	and you can specify the GFP_DMA flag if you need DMA-able memory.
-
-	* Makefile: For source files that are loadable, always add name
-	to SCSI_SRCS.  Fill in modules: target.
-
-	* hosts.c:  Change next_host to next_scsi_host, and make global.
-	Print hosts after we have identified all of them.  Use info()
-	function if present, otherwise use name field.
-
-	* hosts.h: Change attach function to return int, not void.
-	Define number of device slots to allow for loadable devices.
-	Define tags to tell scsi module code what type of module we
-	are loading.
-
-	* scsi.c: Fix scan_scsis so that it can be run by a user process.
-	Do not use waiting loops - use up and down mechanism as long
-	as current != task[0].
-
-	* scsi.c(scan_scsis): Do not use stack variables for I/O - this
-	could be > 16Mb if we are loading a module at runtime (i.e. use
-	scsi_init_malloc to get some memory we know will be safe).
-
-	* scsi.c: Change dma freelist to be a set of pages.  This allows
-	us to dynamically adjust the size of the list by adding more pages
-	to the pagelist.  Fix scsi_malloc and scsi_free accordingly.
-
-	* scsi_module.c: Fix include.
-
-	* sd.c: Declare detach function.  Increment/decrement module usage
-	count as required.  Fix init functions to allow loaded devices.
-	Revalidate all new disks so we get the partition tables.  Define
-	detach function.
-
-	* sr.c: Likewise.
-
-	* sg.c: Declare detach function.  Allow attachment of devices on
-	loaded drivers.
-
-	* st.c: Declare detach function.  Increment/decrement module usage
-	count as required.
-
-Tue Jan 10 10:09:58 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.79 released.
-
-	Patch from some undetermined individual who needs to get a life :-).
-
-	* sr.c: Attacked by spelling bee...
-
-	Patches from Gerd Knorr:
-
-	* sr.c: make printk messages for photoCD a little more informative.
-
-	* sr_ioctl.c: Fix CDROMMULTISESSION_SYS ioctl.
-
-Mon Jan  9 10:01:37 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.78 released.
-
-	* Makefile: Add empty modules: target.
-
-	* Wheee.  Now change register_iomem to request_region.
-
-	* in2000.c: Bugfix - apparently this is the fix that we have
-	all been waiting for.  It fixes a problem whereby the driver
-	is not stable under heavy load.  Race condition and all that.
-	Patch from Peter Lu.
-
-Wed Jan  4 21:17:40 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.77 released.
-
-	* 53c7,8xx.c: Fix from Linus - emulate splx.
-
-	Throughout:
-
-		Change "snarf_region" with "register_iomem".
-
-	* scsi_module.c: New file.  Contains support for low-level loadable
-	  scsi drivers. [ERY].
-
-	* sd.c: More s/int/long/ changes.
-
-	* seagate.c: Explicitly include linux/config.h
-
-	* sg.c: Increment/decrement module usage count on open/close.
-
-	* sg.c: Be a bit more careful about the user not supplying enough
-	  information for a valid command.  Pass correct size down to
-	  scsi_do_cmd.
-
-	* sr.c:  More changes for Photo-CD.  This apparently breaks NEC drives.
-
-	* sr_ioctl.c:  Support CDROMMULTISESSION ioctl.
-
-
-Sun Jan  1 19:55:21 1995  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.76 released.
-
-	* constants.c: Add type cast in switch statement.
-
-	* scsi.c (scsi_free): Change datatype of "offset" to long.
-	  (scsi_malloc): Change a few more variables to long.  Who
-	  did this and why was it important?  64 bit machines?
-
-
-	Lots of changes to use save_state/restore_state instead of cli/sti.
-	Files changed include:
-
-	* aha1542.c:
-	* aha1740.c:
-	* buslogic.c:
-	* in2000.c:
-	* scsi.c:
-	* scsi_debug.c:
-	* sd.c:
-	* sr.c:
-	* st.c:
-
-Wed Dec 28 16:38:29 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.75 released.
-
-	* buslogic.c: Spelling fix.
-
-	* scsi.c: Add HP C1790A and C2500A scanjet to blacklist.
-
-	* scsi.c: Spelling fixup.
-
-	* sd.c: Add support for sd_hardsizes (hard sector sizes).
-
-	* ultrastor.c: Use save_flags/restore_flags instead of cli/sti.
-
-Fri Dec 23 13:36:25 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.74 released.
-
-	* README.st: Update from Kai Makisara.
-
-	* eata.c: New version from Dario - version 1.11.
-	  use scsicam bios_param routine.  Add support for 2011
-	  and 2021 boards.
-
-	* hosts.c: Add support for blocking.  Linked list automatically
-	  generated when shpnt->block is set.
-
-	* scsi.c: Add sankyo & HP scanjet to blacklist.  Add support for
-	  kicking things loose when we deadlock.
-
-	* scsi.c: Recognize scanners and processors in scan_scsis.
-
-	* scsi_ioctl.h: Increase timeout to 9 seconds.
-
-	* st.c: New version from Kai - add better support for backspace.
-
-	* u14-34f.c: New version from Dario.  Supports blocking.
-
-Wed Dec 14 14:46:30 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.73 released.
-
-	* buslogic.c: Update from Dave Gentzel.  Version 1.14.
-	  Add module related stuff.   More fault tolerant if out of
-	  DMA memory.
-
-	* fdomain.c: New version from Rik Faith - version 5.22.  Add support
-	  for ISA-200S SCSI adapter.
-
-	* hosts.c: Spelling.
-
-	* qlogic.c: Update to version 0.38a.  Add more support for PCMCIA.
-
-	* scsi.c: Mask device type with 0x1f during scan_scsis.
-	  Add support for deadlocking, err, make that getting out of
-	  deadlock situations that are created when we allow the user
-	  to limit requests to one host adapter at a time.
-
-	* scsi.c: Bugfix - pass pid, not SCpnt as second arg to
-	  scsi_times_out.
-
-	* scsi.c: Restore interrupt state to previous value instead of using
-	  cli/sti pairs.
-
-	* scsi.c: Add a bunch of module stuff (all commented out for now).
-
-	* scsi.c: Clean up scsi_dump_status.
-
-Tue Dec  6 12:34:20 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.72 released.
-
-	* sg.c: Bugfix - always use sg_free, since we might have big buff.
-
-Fri Dec  2 11:24:53 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.71 released.
-
-	* sg.c: Clear buff field when not in use.  Only call scsi_free if
-	non-null.
-
-	* scsi.h: Call wake_up(&wait_for_request) when done with a
-	command.
-
-	* scsi.c (scsi_times_out): Pass pid down so that we can protect
-	against race conditions.
-
-	* scsi.c (scsi_abort): Zero timeout field if we get the
-	NOT_RUNNING message back from low-level driver.
-
-
-	* scsi.c (scsi_done): Restore cmd_len, use_sg here.
-
-	* scsi.c (request_sense): Not here.
-
-	* hosts.h: Add new forbidden_addr, forbidden_size fields.  Who
-	added these and why????
-
-	* hosts.c (scsi_mem_init): Mark pages as reserved if they fall in
-	the forbidden regions.  I am not sure - I think this is so that
-	we can deal with boards that do incomplete decoding of their
-	address lines for the bios chips, but I am not entirely sure.
-
-	* buslogic.c: Set forbidden_addr stuff if using a buggy board.
-
-	* aha1740.c: Test for NULL pointer in SCtmp.  This should not
-	occur, but a nice message is better than a kernel segfault.
-
-	* 53c7,8xx.c: Add new PCI chip ID for 815.
-
-Fri Dec  2 11:24:53 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.70 released.
-
-	* ChangeLog, st.c: Spelling.
-
-Tue Nov 29 18:48:42 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.69 released.
-
-	* u14-34f.h: Non-functional change.  [Dario].
-
-	* u14-34f.c: Use block field in Scsi_Host to prevent commands from
-	being queued to more than one host at the same time (used when
-	motherboard does not deal with multiple bus-masters very well).
-	Only when SINGLE_HOST_OPERATIONS is defined.
-	Use new cmd_per_lun field.  [Dario]
-
-	* eata.c: Likewise.
-
-	* st.c: More changes from Kai.  Add ready flag to indicate drive
-	status.
-
-	* README.st: Document this.
-
-	* sr.c: Bugfix (do not subtract CD_BLOCK_OFFSET) for photo-cd
-	code.
-
-	* sg.c: Bugfix - fix problem where opcode is not correctly set up.
-
-	* seagate.[c,h]: Use #defines to set driver name.
-
-	* scsi_ioctl.c: Zero buffer before executing command.
-
-	* scsi.c: Use new cmd_per_lun field in Scsi_Hosts as appropriate.
-	Add Sony CDU55S to blacklist.
-
-	* hosts.h: Add new cmd_per_lun field to Scsi_Hosts.
-
-	* hosts.c: Initialize cmd_per_lun in Scsi_Hosts from template.
-
-	* buslogic.c: Use cmd_per_lun field - initialize to different
-	values depending upon bus type (i.e. use 1 if ISA, so we do not
-	hog memory).  Use other patches which got lost from 1.1.68.
-
-	* aha1542.c: Spelling.
-
-Tue Nov 29 15:43:50 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.68 released.
-
-	Add support for 12 byte vendor specific commands in scsi-generics,
-	more (i.e. the last mandatory) low-level changes to support
-	loadable modules, plus a few other changes people have requested
-	lately.  Changes by me (ERY) unless otherwise noted.  Spelling
-	changes appear from some unknown corner of the universe.
-
-	* Throughout: Change COMMAND_SIZE() to use SCpnt->cmd_len.
-
-	* Throughout: Change info() low level function to take a Scsi_Host
-	pointer.  This way the info function can return specific
-	information about the host in question, if desired.
-
-	* All low-level drivers: Add NULL in initializer for the
-	usage_count field added to Scsi_Host_Template.
-
-	* aha152x.[c,h]: Remove redundant info() function.
-
-	* aha1542.[c,h]: Likewise.
-
-	* aha1740.[c,h]: Likewise.
-
-	* aha274x.[c,h]: Likewise.
-
-	* eata.[c,h]: Likewise.
-
-	* pas16.[c,h]: Likewise.
-
-	* scsi_debug.[c,h]: Likewise.
-
-	* t128.[c,h]: Likewise.
-
-	* u14-34f.[c,h]: Likewise.
-
-	* ultrastor.[c,h]: Likewise.
-
-	* wd7000.[c,h]: Likewise.
-
-	* aha1542.c: Add support for command line options with lilo to set
-	DMA parameters, I/O port.  From Matt Aarnio.
-
-	* buslogic.[c,h]: New version (1.13) from Dave Gentzel.
-
-	* hosts.h: Add new field to Scsi_Hosts "block" to allow blocking
-	all I/O to certain other cards.  Helps prevent problems with some
-	ISA motherboards.
-
-	* hosts.h: Add usage_count to Scsi_Host_Template.
-
-	* hosts.h: Add n_io_port to Scsi_Host (used when releasing module).
-
-	* hosts.c: Initialize block field.
-
-	* in2000.c: Remove "static" declarations from exported functions.
-
-	* in2000.h: Likewise.
-
-	* scsi.c: Correctly set cmd_len field as required.  Save and
-	change setting when doing a request_sense, restore when done.
-	Move abort timeout message.  Fix panic in request_queueable to
-	print correct function name.
-
-	* scsi.c: When incrementing usage count, walk block linked list
-	for host, and or in SCSI_HOST_BLOCK bit.  When decrementing usage
-	count to 0, clear this bit to allow usage to continue, wake up
-	processes waiting.
-
-
-	* scsi_ioctl.c: If we have an info() function, call it, otherwise
-	if we have a "name" field, use it, else do nothing.
-
-	* sd.c, sr.c: Clear cmd_len field prior to each command we
-	generate.
-
-	* sd.h: Add "has_part_table" bit to rscsi_disks.
-
-	* sg.[c,h]: Add support for vendor specific 12 byte commands (i.e.
-	override command length in COMMAND_SIZE).
-
-	* sr.c: Bugfix from Gerd in photocd code.
-
-	* sr.c: Bugfix in get_sectorsize - always use scsi_malloc buffer -
-	we cannot guarantee that the stack is < 16Mb.
-
-Tue Nov 22 15:40:46 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.67 released.
-
-	* sr.c: Change spelling of manufactor to manufacturer.
-
-	* scsi.h: Likewise.
-
-	* scsi.c: Likewise.
-
-	* qlogic.c: Spelling corrections.
-
-	* in2000.h: Spelling corrections.
-
-	* in2000.c: Update from Bill Earnest, change from
-	jshiffle@netcom.com.  Support new bios versions.
-
-	* README.qlogic: Spelling correction.
-
-Tue Nov 22 15:40:46 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.66 released.
-
-	* u14-34f.c: Spelling corrections.
-
-	* sr.[h,c]: Add support for multi-session CDs from Gerd Knorr.
-
-	* scsi.h: Add manufactor field for keeping track of device
-	manufacturer.
-
-	* scsi.c: More spelling corrections.
-
-	* qlogic.h, qlogic.c, README.qlogic: New driver from Tom Zerucha.
-
-	* in2000.c, in2000.h: New driver from Brad McLean/Bill Earnest.
-
-	* fdomain.c: Spelling correction.
-
-	* eata.c: Spelling correction.
-
-Fri Nov 18 15:22:44 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.65 released.
-
-	* eata.h: Update version string to 1.08.00.
-
-	* eata.c: Set sg_tablesize correctly for DPT PM2012 boards.
-
-	* aha274x.seq: Spell checking.
-
-	* README.st: Likewise.
-
-	* README.aha274x: Likewise.
-
-	* ChangeLog: Likewise.
-
-Tue Nov 15 15:35:08 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.64 released.
-
-	* u14-34f.h: Update version number to 1.10.01.
-
-	* u14-34f.c: Use Scsi_Host can_queue variable instead of one from template.
-
-	* eata.[c,h]: New driver for DPT boards from Dario Ballabio.
-
-	* buslogic.c: Use can_queue field.
-
-Wed Nov 30 12:09:09 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.63 released.
-
-	* sd.c: Give I/O error if we attempt 512 byte I/O to a disk with
-	1024 byte sectors.
-
-	* scsicam.c: Make sure we do read from whole disk (mask off
-	partition).
-
-	* scsi.c: Use can_queue in Scsi_Host structure.
-	Fix panic message about invalid host.
-
-	* hosts.c: Initialize can_queue from template.
-
-	* hosts.h: Add can_queue to Scsi_Host structure.
-
-	* aha1740.c: Print out warning about NULL ecbptr.
-
-Fri Nov  4 12:40:30 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.62 released.
-
-	* fdomain.c: Update to version 5.20. (From Rik Faith).  Support
-	BIOS version 3.5.
-
-	* st.h: Add ST_EOD symbol.
-
-	* st.c: Patches from Kai Makisara - support additional densities,
-	add support for MTFSS, MTBSS, MTWSM commands.
-
-	* README.st: Update to document new commands.
-
-	* scsi.c: Add Mediavision CDR-H93MV to blacklist.
-
-Sat Oct 29 20:57:36 1994  Eric Youngdale  (eric@andante.aib.com)
-
-	* Linux 1.1.60 released.
-
-	* u14-34f.[c,h]: New driver from Dario Ballabio.
-
-	* aic7770.c, aha274x_seq.h, aha274x.seq, aha274x.h, aha274x.c,
-	README.aha274x: New files, new driver from John Aycock.
-
-
-Tue Oct 11 08:47:39 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.54 released.
-
-	* Add third PCI chip id.  [Drew]
-
-	* buslogic.c: Set BUSLOGIC_CMDLUN back to 1 [Eric].
-
-	* ultrastor.c: Fix asm directives for new GCC.
-
-	* sr.c, sd.c: Use new end_scsi_request function.
-
-	* scsi.h(end_scsi_request): Return pointer to block if still
-	active, else return NULL if inactive.  Fixes race condition.
-
-Sun Oct  9 20:23:14 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.53 released.
-
-	* scsi.c: Do not allocate dma bounce buffers if we have exactly
-	16Mb.
-
-Fri Sep  9 05:35:30 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.51 released.
-
-	* aha152x.c: Add support for disabling the parity check.  Update
-	to version 1.4. [Juergen].
-
-	* seagate.c: Tweak debugging message.
-
-Wed Aug 31 10:15:55 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.50 released.
-
-	* aha152x.c: Add eb800 for Vtech Platinum SMP boards. [Juergen].
-
-	* scsi.c: Add Quantum PD1225S to blacklist.
-
-Fri Aug 26 09:38:45 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.49 released.
-
-	* sd.c: Fix bug when we were deleting the wrong entry if we
-	get an unsupported sector size device.
-
-	* sr.c: Another spelling patch.
-
-Thu Aug 25 09:15:27 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.48 released.
-
-	* Throughout: Use new semantics for request_dma, as appropriate.
-
-	* sr.c: Print correct device number.
-
-Sun Aug 21 17:49:23 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.47 released.
-
-	* NCR5380.c: Add support for LIMIT_TRANSFERSIZE.
-
-	* constants.h: Add prototype for print_Scsi_Cmnd.
-
-	* pas16.c: Some more minor tweaks.  Test for Mediavision board.
-	Allow for disks > 1Gb.  [Drew??]
-
-	* sr.c: Set SCpnt->transfersize.
-
-Tue Aug 16 17:29:35 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.46 released.
-
-	* Throughout: More spelling fixups.
-
-	* buslogic.c: Add a few more fixups from Dave.  Disk translation
-	mainly.
-
-	* pas16.c: Add a few patches (Drew?).
-
-
-Thu Aug 11 20:45:15 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.44 released.
-
-	* hosts.c: Add type casts for scsi_init_malloc.
-
-	* scsicam.c: Add type cast.
-
-Wed Aug 10 19:23:01 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.43 released.
-
-	* Throughout: Spelling cleanups. [??]
-
-	* aha152x.c, NCR53*.c, fdomain.c, g_NCR5380.c, pas16.c, seagate.c,
-	 t128.c: Use request_irq, not irqaction. [??]
-
-	* aha1542.c: Move test for shost before we start to use shost.
-
-	* aha1542.c, aha1740.c, ultrastor.c, wd7000.c: Use new
-	calling sequence for request_irq.
-
-	* buslogic.c: Update from Dave Gentzel.
-
-Tue Aug  9 09:32:59 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.42 released.
-
-	* NCR5380.c: Change NCR5380_print_status to static.
-
-	* seagate.c: A few more bugfixes.  Only Drew knows what they are
-	for.
-
-	* ultrastor.c: Tweak some __asm__ directives so that it works
-	with newer compilers. [??]
-
-Sat Aug  6 21:29:36 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.40 released.
-
-	* NCR5380.c: Return SCSI_RESET_WAKEUP from reset function.
-
-	* aha1542.c: Reset mailbox status after a bus device reset.
-
-	* constants.c: Fix typo (;;).
-
-	* g_NCR5380.c:
-	* pas16.c:  Correct usage of NCR5380_init.
-
-	* scsi.c: Remove redundant (and unused variables).
-
-	* sd.c: Use memset to clear all of rscsi_disks before we use it.
-
-	* sg.c: Ditto, except for scsi_generics.
-
-	* sr.c: Ditto, except for scsi_CDs.
-
-	* st.c: Initialize STp->device.
-
-	* seagate.c: Fix bug. [Drew]
-
-Thu Aug  4 08:47:27 1994  Eric Youngdale  (eric@andante)
-
-	* Linux 1.1.39 released.
-
-	* Makefile: Fix typo in NCR53C7xx.
-
-	* st.c: Print correct number for device.
-
-Tue Aug  2 11:29:14 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.38 released.
-
-	Lots of changes in 1.1.38.  All from Drew unless otherwise noted.
-
-	* 53c7,8xx.c: New file from Drew.  PCI driver.
-
-	* 53c7,8xx.h: Likewise.
-
-	* 53c7,8xx.scr: Likewise.
-
-	* 53c8xx_d.h, 53c8xx_u.h, script_asm.pl: Likewise.
-
-	* scsicam.c: New file from Drew.  Read block 0 on the disk and
-	read the partition table.  Attempt to deduce the geometry from
-	the partition table if possible.  Only used by 53c[7,8]xx right
-	now, but could be used by any device for which we have no way
-	of identifying the geometry.
-
-	* sd.c: Use device letters instead of sd%d in a lot of messages.
-
-	* seagate.c: Fix bug that resulted in lockups with some devices.
-
-	* sr.c (sr_open): Return -EROFS, not -EACCES if we attempt to open
-	device for write.
-
-	* hosts.c, Makefile: Update for new driver.
-
-	* NCR5380.c, NCR5380.h, g_NCR5380.h: Update from Drew to support
-	53C400 chip.
-
-	* constants.c: Define CONST_CMND and CONST_MSG.  Other minor
-	cleanups along the way.  Improve handling of CONST_MSG.
-
-	* fdomain.c, fdomain.h: New version from Rik Faith.  Update to
-	5.18.  Should now support TMC-3260 PCI card with 18C30 chip.
-
-	* pas16.c: Update with new irq initialization.
-
-	* t128.c: Update with minor cleanups.
-
-	* scsi.c (scsi_pid): New variable - gives each command a unique
-	id. Add Quantum LPS5235S to blacklist.  Change in_scan to
-	in_scan_scsis and make global.
-
-	* scsi.h: Add some defines for extended message handling,
-	INITIATE/RELEASE_RECOVERY.  Add a few new fields to support sync
-	transfers.
-
-	* scsi_ioctl.h: Add ioctl to request synchronous transfers.
-
-
-Tue Jul 26 21:36:58 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.37 released.
-
-	* aha1542.c: Always call aha1542_mbenable, use new udelay
-	mechanism so we do not wait a long time if the board does not
-	implement this command.
-
-	* g_NCR5380.c: Remove #include <linux/config.h> and #if
-	defined(CONFIG_SCSI_*).
-
-	* seagate.c: Likewise.
-
-	Next round of changes to support loadable modules.  Getting closer
-	now, still not possible to do anything remotely usable.
-
-	hosts.c: Create a linked list of detected high level devices.
-	(scsi_register_device): New function to insert into this list.
-	(scsi_init): Call scsi_register_device for each of the known high
-	level drivers.
-
-	hosts.h: Add prototype for linked list header.  Add structure
-	definition for device template structure which defines the linked
-	list.
-
-	scsi.c: (scan_scsis): Use linked list instead of knowledge about
-	existing high level device drivers.
-	(scsi_dev_init): Use init functions for drivers on linked list
-	instead of explicit list to initialize and attach devices to high
-	level drivers.
-
-	scsi.h: Add new field "attached" to scsi_device - count of number
-	of high level devices attached.
-
-	sd.c, sr.c, sg.c, st.c: Adjust init/attach functions to use new
-	scheme.
-
-Sat Jul 23 13:03:17 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.35 released.
-
-	* ultrastor.c: Change constraint on asm() operand so that it works
-	with gcc 2.6.0.
-
-Thu Jul 21 10:37:39 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.33 released.
-
-	* sr.c(sr_open): Do not allow opens with write access.
-
-Mon Jul 18 09:51:22 1994 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.31 released.
-
-	* sd.c: Increase SD_TIMEOUT from 300 to 600.
-
-	* sr.c: Remove stray task_struct* variable that was no longer
-	used.
-
-	* sr_ioctl.c: Fix typo in up() call.
-
-Sun Jul 17 16:25:29 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.30 released.
-
-	* scsi.c (scan_scsis): Fix detection of some Toshiba CDROM drives
-	that report themselves as disk drives.
-
-	* (Throughout): Use request.sem instead of request.waiting.
-	Should fix swap problem with fdomain.
-
-Thu Jul 14 10:51:42 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.29 released.
-
-	* scsi.c (scan_scsis): Add new devices to end of linked list, not
-	to the beginning.
-
-	* scsi.h (SCSI_SLEEP): Remove brain dead hack to try to save
-	the task state before sleeping.
-
-Sat Jul  9 15:01:03 1994  Eric Youngdale  (eric@esp22)
-
-	More changes to eventually support loadable modules.  Mainly
-	we want to use linked lists instead of arrays because it is easier
-	to dynamically add and remove things this way.
-
-	Quite a bit more work is needed before loadable modules are
-	possible (and usable) with scsi, but this is most of the grunge
-	work.
-
-	* Linux 1.1.28 released.
-
-	* scsi.c, scsi.h (allocate_device, request_queueable): Change
-	argument from index into scsi_devices to a pointer to the
-	Scsi_Device struct.
-
-	* Throughout: Change all calls to allocate_device,
-	request_queueable to use new calling sequence.
-
-	* Throughout: Use SCpnt->device instead of
-	scsi_devices[SCpnt->index].  Ugh - the pointer was there all along
-	- much cleaner this way.
-
-	* scsi.c (scsi_init_malloc, scsi_free_malloc): New functions -
-	allow us to pretend that we have a working malloc when we
-	initialize.  Use this instead of passing memory_start, memory_end
-	around all over the place.
-
-	* scsi.h, st.c, sr.c, sd.c, sg.c: Change *_init1 functions to use
-	scsi_init_malloc, remove all arguments, no return value.
-
-	* scsi.h: Remove index field from Scsi_Device and Scsi_Cmnd
-	structs.
-
-	* scsi.c (scsi_dev_init): Set up for scsi_init_malloc.
-	(scan_scsis): Get SDpnt from scsi_init_malloc, and refresh
-	when we discover a device.  Free pointer before returning.
-	Change scsi_devices into a linked list.
-
-	* scsi.c (scan_scsis): Change to only scan one host.
-	(scsi_dev_init): Loop over all detected hosts, and scan them.
-
-	* hosts.c  (scsi_init_free): Change so that  number of extra bytes
-	is stored in struct, and we do not have to pass it each time.
-
-	* hosts.h: Change Scsi_Host_Template struct to include "next" and
-	"release" functions.  Initialize to NULL in all low level
-	adapters.
-
-	* hosts.c: Rename scsi_hosts to builtin_scsi_hosts, create linked
-	list scsi_hosts, linked together with the new "next" field.
-
-Wed Jul  6 05:45:02 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.25 released.
-
-	* aha152x.c: Changes from Juergen - cleanups and updates.
-
-	* sd.c, sr.c: Use new check_media_change and revalidate
-	file_operations fields.
-
-	* st.c, st.h: Add changes from Kai Makisara, dated Jun 22.
-
-	* hosts.h: Change SG_ALL back to 0xff.  Apparently soft error
-	in /dev/brain resulted in having this bumped up.
-	Change first parameter in bios_param function to be Disk * instead
-	of index into rscsi_disks.
-
-	* sd_ioctl.c: Pass pointer to rscsi_disks element instead of index
-	to array.
-
-	* sd.h: Add struct name "scsi_disk" to typedef for Scsi_Disk.
-
-	* scsi.c: Remove redundant Maxtor XT8760S from blacklist.
-	In scsi_reset, add printk when DEBUG defined.
-
-	* All low level drivers: Modify definitions of bios_param in
-	appropriate way.
-
-Thu Jun 16 10:31:59 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.20 released.
-
-	* scsi_ioctl.c: Only pass down the actual number of characters
-	required to scsi_do_cmd, not the one rounded up to a even number
-	of sectors.
-
-	* ultrastor.c: Changes from Caleb Epstein for 24f cards.  Support
-	larger SG lists.
-
-	* ultrastor.c: Changes from me - use scsi_register to register
-	host.  Add some consistency checking,
-
-Wed Jun  1 21:12:13 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.19 released.
-
-	* scsi.h: Add new return code for reset() function:
-	SCSI_RESET_PUNT.
-
-	* scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for
-	now.
-
-	* aha1542.c: If the command responsible for the reset is not
-	pending, return SCSI_RESET_PUNT.
-
-	* aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return
-	SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE.
-
-Tue May 31 19:36:01 1994  Eric Youngdale  (eric@esp22)
-
-	* buslogic.c: Do not print out message about "must be Adaptec"
-	if we have detected a buslogic card.  Print out a warning message
-	if we are configuring for >16Mb, since the 445S at board level
-	D or earlier does not work right.  The "D" level board can be made
-	to work by flipping an undocumented switch, but this is too subtle.
-
-    Changes based upon patches in Yggdrasil distribution.
-
-	* sg.c, sg.h: Return sense data to user.
-
-	* aha1542.c, aha1740.c, buslogic.c: Do not panic if
-	sense buffer is wrong size.
-
-	* hosts.c: Test for ultrastor card before any of the others.
-
-	* scsi.c: Allow boot-time option for max_scsi_luns=? so that
-	buggy firmware has an easy work-around.
-
-Sun May 15 20:24:34 1994  Eric Youngdale  (eric@esp22)
-
-	* Linux 1.1.15 released.
-
-	Post-codefreeze thaw...
-
-	* buslogic.[c,h]: New driver from David Gentzel.
-
-	* hosts.h: Add use_clustering field to explicitly say whether
-	clustering should be used for devices attached to this host
-	adapter.  The buslogic board apparently supports large SG lists,
-	but it is apparently faster if sd.c condenses this into a smaller
-	list.
-
-	* sd.c: Use this field instead of heuristic.
-
-	* All host adapter include files: Add appropriate initializer for
-	use_clustering field.
-
-	* scsi.h: Add #defines for return codes for the abort and reset
-	functions.  There are now a specific set of return codes to fully
-	specify all of the possible things that the low-level adapter
-	could do.
-
-	* scsi.c: Act based upon return codes from abort/reset functions.
-
-	* All host adapter abort/reset functions: Return new return code.
-
-	* Add code in scsi.c to help debug timeouts.  Use #define
-	DEBUG_TIMEOUT to enable this.
-
-	* scsi.c: If the host->irq field is set, use
-	disable_irq/enable_irq before calling queuecommand if we
-	are not already in an interrupt.  Reduce races, and we
-	can be sloppier about cli/sti in the interrupt routines now
-	(reduce interrupt latency).
-
-	* constants.c: Fix some things to eliminate warnings.  Add some
-	sense descriptions that were omitted before.
-
-	* aha1542.c: Watch for SCRD from host adapter - if we see it, set
-	a flag.  Currently we only print out the number of pending
-	commands that might need to be restarted.
-
-	* aha1542.c (aha1542_abort): Look for lost interrupts, OGMB still
-	full, and attempt to recover.  Otherwise give up.
-
-	* aha1542.c (aha1542_reset): Try BUS DEVICE RESET, and then pass
-	DID_RESET back up to the upper level code for all commands running
-	on this target (even on different LUNs).
-
-Sat May  7 14:54:01 1994
-
-	* Linux 1.1.12 released.
-
-	* st.c, st.h: New version from Kai.  Supports boot time
-	specification of number of buffers.
-
-	* wd7000.[c,h]: Updated driver from John Boyd.  Now supports
-	more than one wd7000 board in machine at one time, among other things.
-
-Wed Apr 20 22:20:35 1994
-
-	* Linux 1.1.8 released.
-
-	* sd.c: Add a few type casts where scsi_malloc is called.
-
-Wed Apr 13 12:53:29 1994
-
-	* Linux 1.1.4 released.
-
-	* scsi.c: Clean up a few printks (use %p to print pointers).
-
-Wed Apr 13 11:33:02 1994
-
-	* Linux 1.1.3 released.
-
-	* fdomain.c: Update to version 5.16 (Handle different FIFO sizes
-	better).
-
-Fri Apr  8 08:57:19 1994
-
-	* Linux 1.1.2 released.
-
-	* Throughout: SCSI portion of cluster diffs added.
-
-Tue Apr  5 07:41:50 1994
-
-	* Linux 1.1 development tree initiated.
-
-	* The linux 1.0 development tree is now effectively frozen except
-	for obvious bugfixes.
-
-******************************************************************
-******************************************************************
-******************************************************************
-******************************************************************
-
-Sun Apr 17 00:17:39 1994
-
-	* Linux 1.0, patchlevel 9 released.
-
-	* fdomain.c: Update to version 5.16 (Handle different FIFO sizes
-	better).
-
-Thu Apr  7 08:36:20 1994
-
-	* Linux 1.0, patchlevel8 released.
-
-	* fdomain.c: Update to version 5.15 from 5.9.  Handles 3.4 bios.
-
-Sun Apr  3 14:43:03 1994
-
-	* Linux 1.0, patchlevel6 released.
-
-	* wd7000.c: Make stab at fixing race condition.
-
-Sat Mar 26 14:14:50 1994
-
-	* Linux 1.0, patchlevel5 released.
-
-	* aha152x.c, Makefile: Fix a few bugs (too much data message).
-	Add a few more bios signatures. (Patches from Juergen).
-
-	* aha1542.c: Fix race condition in aha1542_out.
-
-Mon Mar 21 16:36:20 1994
-
-	* Linux 1.0, patchlevel3 released.
-
-	* sd.c, st.c, sr.c, sg.c: Return -ENXIO, not -ENODEV if we attempt
-	to open a non-existent device.
-
-	* scsi.c: Add Chinon cdrom to blacklist.
-
-	* sr_ioctl.c: Check return status of verify_area.
-
-Sat Mar  6 16:06:19 1994
-
-	* Linux 1.0 released (technically a pre-release).
-
-	* scsi.c: Add IMS CDD521, Maxtor XT-8760S to blacklist.
-
-Tue Feb 15 10:58:20 1994
-
-        * pl15e released.
-
-        * aha1542.c: For 1542C, allow dynamic device scan with >1Gb turned
-	off.
-
-	* constants.c: Fix typo in definition of CONSTANTS.
-
-        * pl15d released.
-
-Fri Feb 11 10:10:16 1994
-
-        * pl15c released.
-
-	* scsi.c: Add Maxtor XT-3280 and Rodime RO3000S to blacklist.
-
-	* scsi.c: Allow tagged queueing for scsi 3 devices as well.
-	Some really old devices report a version number of 0.  Disallow
-	LUN != 0 for these.
-
-Thu Feb 10 09:48:57 1994
-
-        * pl15b released.
-
-Sun Feb  6 12:19:46 1994
-
-        * pl15a released.
-
-Fri Feb  4 09:02:17 1994
-
-        * scsi.c: Add Teac cdrom to blacklist.
-
-Thu Feb  3 14:16:43 1994
-
-	* pl15 released.
-
-Tue Feb  1 15:47:43 1994
-
-	* pl14w released.
-
-	* wd7000.c (wd_bases): Fix typo in last change.
-
-Mon Jan 24 17:37:23 1994
-
-	* pl14u released.
-
-	* aha1542.c: Support 1542CF/extended bios.  Different from 1542C
-
-	* wd7000.c: Allow bios at 0xd8000 as well.
-
-	* ultrastor.c: Do not truncate cylinders to 1024.
-
-	* fdomain.c: Update to version 5.9 (add new bios signature).
-
-	* NCR5380.c: Update from Drew - should work a lot better now.
-
-Sat Jan  8 15:13:10 1994
-
-	* pl14o released.
-
-	* sr_ioctl.c: Zero reserved field before trying to set audio volume.
-
-Wed Jan  5 13:21:10 1994
-
-	* pl14m released.
-
-	* fdomain.c: Update to version 5.8.  No functional difference???
-
-Tue Jan  4 14:26:13 1994
-
-	* pl14l released.
-
-	* ultrastor.c: Remove outl, inl functions (now provided elsewhere).
-
-Mon Jan  3 12:27:25 1994
-
-	* pl14k released.
-
-	* aha152x.c: Remove insw and outsw functions.
-
-	* fdomain.c: Ditto.
-
-Wed Dec 29 09:47:20 1993
-
-	* pl14i released.
-
-	* scsi.c: Support RECOVERED_ERROR for tape drives.
-
-	* st.c: Update of tape driver from Kai.
-
-Tue Dec 21 09:18:30 1993
-
-	* pl14g released.
-
-	* aha1542.[c,h]: Support extended BIOS stuff.
-
-	* scsi.c: Clean up messages about disks, so they are displayed as
-	sda, sdb, etc instead of sd0, sd1, etc.
-
-	* sr.c:  Force reread of capacity if disk was changed.
-	Clear buffer before asking for capacity/sectorsize (some drives
-	do not report this properly).  Set needs_sector_size flag if
-	drive did not return sensible sector size.
-
-Mon Dec 13 12:13:47 1993
-
-	* aha152x.c: Update to version .101 from Juergen.
-
-Mon Nov 29 03:03:00 1993
-
-        * linux 0.99.14 released.
-
-	* All scsi stuff moved from kernel/blk_drv/scsi to drivers/scsi.
-
-	* Throughout: Grammatical corrections to various comments.
-
-	* Makefile: fix so that we do not need to compile things we are
-	not going to use.
-
-	* NCR5380.c, NCR5380.h, g_NCR5380.c, g_NCR5380.h, pas16.c,
-	pas16.h, t128.c, t128.h:  New files from Drew.
-
-	* aha152x.c, aha152x.h: New files from Juergen Fischer.
-
-	* aha1542.c: Support for more than one 1542 in the machine
-	at the same time.  Make functions static that do not need
-	visibility.
-
-	* aha1740.c: Set NEEDS_JUMPSTART flag in reset function, so we
-	know to restart the command.  Change prototype of aha1740_reset
-	to take a command pointer.
-
-	* constants.c: Clean up a few things.
-
-	* fdomain.c: Update to version 5.6.  Move snarf_region.  Allow
-	board to be set at different SCSI ids.  Remove support for
-	reselection (did not work well).  Set JUMPSTART flag in reset
-	code.
-
-	* hosts.c: Support new low-level adapters.  Allow for more than
-	one adapter of a given type.
-
-	* hosts.h: Allow for more than one adapter of a given type.
-
-	* scsi.c:  Add scsi_device_types array, if NEEDS_JUMPSTART is set
-	after a low-level reset, start the command again.  Sort blacklist,
-	and add Maxtor MXT-1240S, XT-4170S, NEC CDROM 84, Seagate ST157N.
-
-	* scsi.h: Add constants for tagged queueing.
-
-	* Throughout: Use constants from major.h instead of hardcoded
-	numbers for major numbers.
-
-	* scsi_ioctl.c: Fix bug in buffer length in ioctl_command.  Use
-	verify_area in GET_IDLUN ioctl.  Add new ioctls for
-	TAGGED_QUEUE_ENABLE, DISABLE.  Only allow IOCTL_SEND_COMMAND by
-	superuser.
-
-	* sd.c: Only pay attention to UNIT_ATTENTION for removable disks.
-	Fix bug where sometimes portions of blocks would get lost
-	resulting in processes hanging.  Add messages when we spin up a
-	disk, and fix a bug in the timing.  Increase read-ahead for disks
-	that are on a scatter-gather capable host adapter.
-
-	* seagate.c: Fix so that some parameters can be set from the lilo
-	prompt.  Supply jumpstart flag if we are resetting and need the
-	command restarted.   Fix so that we return 1 if we detect a card
-	so that multiple card detection works correctly.  Add yet another
-	signature for FD cards (950).  Add another signature for ST0x.
-
-	* sg.c, sg.h: New files from Lawrence Foard for generic scsi
-	access.
-
-	* sr.c:  Add type casts for (void*) so that we can do pointer
-	arithmetic.  Works with GCC without this, but it is not strictly
-	correct.  Same bugfix as was in sd.c.  Increase read-ahead a la
-	disk driver.
-
-	* sr_ioctl.c: Use scsi_malloc buffer instead of buffer from stack
-	since we cannot guarantee that the stack is < 16Mb.
-
-	ultrastor.c: Update to support 24f properly (JFC's driver).
-
-	wd7000.c: Supply jumpstart flag for reset.  Do not round up
-	number of cylinders in biosparam function.
-
-Sat Sep  4 20:49:56 1993
-
-    * 0.99pl13 released.
-
-    * Throughout:  Use check_region/snarf_region for all low-level
-    drivers.
-
-    * aha1542.c: Do hard reset instead of soft (some ethercard probes
-    screw us up).
-
-    * scsi.c: Add new flag ASKED_FOR_SENSE so that we can tell if we are
-    in a loop whereby the device returns null sense data.
-
-    * sd.c: Add code to spin up a drive if it is not already spinning.
-    Do this one at a time to make it easier on power supplies.
-
-    * sd_ioctl.c: Use sync_dev instead of fsync_dev in BLKFLSBUF ioctl.
-
-    * seagate.c: Switch around DATA/CONTROL lines.
-
-    * st.c: Change sense to unsigned.
-
-Thu Aug  5 11:59:18 1993
-
-    * 0.99pl12 released.
-
-    * constants.c, constants.h: New files with ascii descriptions of
-    various conditions.
-
-    * Makefile: Do not try to count the number of low-level drivers,
-    just generate the list of .o files.
-
-    * aha1542.c: Replace 16 with sizeof(SCpnt->sense_buffer).  Add tests
-    for addresses > 16Mb, panic if we find one.
-
-    * aha1740.c: Ditto with sizeof().
-
-    * fdomain.c: Update to version 3.18.  Add new signature, register IRQ
-    with irqaction.  Use ID 7 for new board.  Be more intelligent about
-    obtaining the h/s/c numbers for biosparam.
-
-    * hosts.c: Do not depend upon Makefile generated count of the number
-    of low-level host adapters.
-
-    * scsi.c: Use array for scsi_command_size instead of a function.  Add
-    Texel cdrom and Maxtor XT-4380S to blacklist.  Allow compile time
-    option for no-multi lun scan.  Add semaphore for possible problems
-    with handshaking, assume device is faulty until we know it not to be
-    the case.  Add DEBUG_INIT symbol to dump info as we scan for devices.
-    Zero sense buffer so we can tell if we need to request it.  When
-    examining sense information, request sense if buffer is all zero.
-    If RESET, request sense information to see what to do next.
-
-    * scsi_debug.c: Change some constants to use symbols like INT_MAX.
-
-    * scsi_ioctl.c (kernel_scsi_ioctl): New function -for making ioctl
-    calls from kernel space.
-
-    * sd.c: Increase timeout to 300.  Use functions in constants.h to
-    display info.  Use scsi_malloc buffer for READ_CAPACITY, since
-    we cannot guarantee that a stack based buffer is < 16Mb.
-
-    * sd_ioctl.c: Add BLKFLSBUF ioctl.
-
-    * seagate.c: Add new compile time options for ARBITRATE,
-    SLOW_HANDSHAKE, and SLOW_RATE.  Update assembly loops for transferring
-    data.  Use kernel_scsi_ioctl to request mode page with geometry.
-
-    * sr.c: Use functions in constants.c to display messages.
-
-    * st.c: Support for variable block size.
-
-    * ultrastor.c: Do not use cache for tape drives.  Set
-    unchecked_isa_dma flag, even though this may not be needed (gets set
-    later).
-
-Sat Jul 17 18:32:44 1993
-
-    * 0.99pl11 released.  C++ compilable.
-
-    * Throughout: Add type casts all over the place, and use "ip" instead
-    of "info" in the various biosparam functions.
-
-    * Makefile: Compile seagate.c with C++ compiler.
-
-    * aha1542.c: Always set ccb pointer as this gets trashed somehow on
-    some systems.  Add a few type casts.  Update biosparam function a little.
-
-    * aha1740.c: Add a few type casts.
-
-    * fdomain.c: Update to version 3.17 from 3.6.  Now works with
-    TMC-18C50.
-
-    * scsi.c: Minor changes here and there with datatypes.  Save use_sg
-    when requesting sense information so that this can properly be
-    restored if we retry the command.  Set aside dma buffers assuming each
-    block is 1 page, not 1Kb minix block.
-
-    * scsi_ioctl.c: Add a few type casts.  Other minor changes.
-
-    * sd.c:  Correctly  free all scsi_malloc'd memory if we run out of
-    dma_pool. Store blocksize information for each partition.
-
-    * seagate.c: Minor cleanups here and there.
-
-    * sr.c: Set up blocksize array for all discs.  Fix bug in freeing
-    buffers if we run out of dma pool.
-
-Thu Jun  2 17:58:11 1993
-
-    * 0.99pl10 released.
-
-    * aha1542.c: Support for BT 445S (VL-bus board with no dma channel).
-
-    * fdomain.c: Upgrade to version 3.6. Preliminary support for TNC-18C50.
-
-    * scsi.c: First attempt to fix problem with old_use_sg.  Change
-    NOT_READY to a SUGGEST_ABORT.  Fix timeout race where time might
-    get decremented past zero.
-
-    * sd.c: Add block_fsync function to dispatch table.
-
-    * sr.c: Increase timeout to 500 from 250.  Add entry for sync in
-    dispatch table (supply NULL).  If we do not have a sectorsize,
-    try to get it in the sd_open function.  Add new function just to
-    obtain sectorsize.
-
-    * sr.h: Add needs_sector_size semaphore.
-
-    * st.c: Add NULL for fsync in dispatch table.
-
-    * wd7000.c: Allow another condition for power on that are normal
-    and do not require a panic.
-
-Thu Apr 22 23:10:11 1993
-
-    * 0.99pl9 released.
-
-    * aha1542.c: Use (void) instead of () in setup_mailboxes.
-
-    * scsi.c: Initialize transfersize and underflow fields in SCmd to 0.
-    Do not panic for unsupported message bytes.
-
-    * scsi.h: Allocate 12 bytes instead of 10 for commands.  Add
-    transfersize and underflow fields.
-
-    * scsi_ioctl.c: Further bugfix to ioctl_probe.
-
-    * sd.c: Use long instead of int for last parameter in sd_ioctl.
-    Initialize transfersize and underflow fields.
-
-    * sd_ioctl.c: Ditto for sd_ioctl(,,,,);
-
-    * seagate.c: New version from Drew.  Includes new signatures for FD
-    cards.  Support for 0ws jumper. Correctly initialize
-    scsi_hosts[hostnum].this_id.  Improved handing of
-    disconnect/reconnect, and support command linking.  Use
-    transfersize and underflow fields.  Support scatter-gather.
-
-    * sr.c, sr_ioctl.c: Use long instead of int for last parameter in sr_ioctl.
-    Use buffer and buflength in do_ioctl.  Patches from Chris Newbold for
-    scsi-2 audio commands.
-
-    * ultrastor.c: Comment out in_byte (compiler warning).
-
-    * wd7000.c: Change () to (void) in wd7000_enable_dma.
-
-Wed Mar 31 16:36:25 1993
-
-    * 0.99pl8 released.
-
-    * aha1542.c: Handle mailboxes better for 1542C.
-        Do not truncate number of cylinders at 1024 for biosparam call.
-
-    * aha1740.c: Fix a few minor bugs for multiple devices.
-        Same as above for biosparam.
-
-    * scsi.c: Add lockable semaphore for removable devices that can have
-    media removal prevented.  Add another signature for flopticals.
-    (allocate_device): Fix race condition.  Allow more space in dma pool
-    for blocksizes of up to 4Kb.
-
-    * scsi.h: Define COMMAND_SIZE.  Define a SCSI specific version of
-    INIT_REQUEST that can run with interrupts off.
-
-    * scsi_ioctl.c: Make ioctl_probe function more idiot-proof.  If
-    a removable device says ILLEGAL REQUEST to a door-locking command,
-    clear lockable flag.  Add SCSI_IOCTL_GET_IDLUN ioctl.  Do not attempt
-    to lock door for devices that do not have lockable semaphore set.
-
-    * sd.c: Fix race condition for multiple disks.  Use INIT_SCSI_REQUEST
-    instead of INIT_REQUEST.  Allow sector sizes of 1024 and 256.  For
-    removable disks that are not ready, mark them as having a media change
-    (some drives do not report this later).
-
-    * seagate.c: Use volatile keyword for memory-mapped register pointers.
-
-    * sr.c: Fix race condition, a la sd.c.  Increase the number of retries
-    to 1.  Use INIT_SCSI_REQUEST.  Allow 512 byte sector sizes.  Do a
-    read_capacity when we init the device so we know the size and
-    sectorsize.
-
-    * st.c: If ioctl not found in st.c, try scsi_ioctl for others.
-
-    * ultrastor.c: Do not truncate number of cylinders at 1024 for
-    biosparam call.
-
-    * wd7000.c: Ditto.
-    Throughout: Use COMMAND_SIZE macro to determine length of scsi
-    command.
-
-
-
-Sat Mar 13 17:31:29 1993
-
-    * 0.99pl7 released.
-
-    Throughout: Improve punctuation in some messages, and use new
-    verify_area syntax.
-
-    * aha1542.c: Handle unexpected interrupts better.
-
-    * scsi.c: Ditto.  Handle reset conditions a bit better, asking for
-    sense information and retrying if required.
-
-    * scsi_ioctl.c: Allow for 12 byte scsi commands.
-
-    * ultrastor.c: Update to use scatter-gather.
-
-Sat Feb 20 17:57:15 1993
-
-    * 0.99pl6 released.
-
-    * fdomain.c: Update to version 3.5.  Handle spurious interrupts
-    better.
-
-    * sd.c: Use register_blkdev function.
-
-    * sr.c: Ditto.
-
-    * st.c: Use register_chrdev function.
-
-    * wd7000.c: Undo previous change.
-
-Sat Feb  6 11:20:43 1993
-
-    * 0.99pl5 released.
-
-    * scsi.c: Fix bug in testing for UNIT_ATTENTION.
-
-    * wd7000.c: Check at more addresses for bios.  Fix bug in biosparam
-    (heads & sectors turned around).
-
-Wed Jan 20 18:13:59 1993
-
-    * 0.99pl4 released.
-
-    * scsi.c: Ignore leading spaces when looking for blacklisted devices.
-
-    * seagate.c: Add a few new signatures for FD cards.  Another patch
-    with SCint to fix race condition.  Use recursion_depth to keep track
-    of how many times we have been recursively called, and do not start
-    another command unless we are on the outer level.  Fixes bug
-    with Syquest cartridge drives (used to crash kernel), because
-    they do not disconnect with large data transfers.
-
-Tue Jan 12 14:33:36 1993
-
-    * 0.99pl3 released.
-
-    * fdomain.c: Update to version 3.3 (a few new signatures).
-
-    * scsi.c: Add CDU-541, Denon DRD-25X to blacklist.
-    (allocate_request, request_queueable): Init request.waiting to NULL if
-    non-buffer type of request.
-
-    * seagate.c:  Allow controller to be overridden with CONTROLLER symbol.
-    Set SCint=NULL when we are done, to remove race condition.
-
-    * st.c: Changes from Kai.
-
-Wed Dec 30 20:03:47 1992
-
-    * 0.99pl2 released.
-
-    * scsi.c: Blacklist back in.  Remove Newbury drive as other bugfix
-    eliminates need for it here.
-
-    * sd.c: Return ENODEV instead of EACCES if no such device available.
-    (sd_init) Init blkdev_fops earlier so that sd_open is available sooner.
-
-    * sr.c: Same as above for sd.c.
-
-    * st.c: Return ENODEV instead of ENXIO if no device.  Init chrdev_fops
-    sooner, so that it is always there even if no tapes.
-
-    * seagate.c (controller_type): New variable to keep track of ST0x or
-    FD.  Modify signatures list to indicate controller type, and init
-    controller_type once we find a match.
-
-    * wd7000.c (wd7000_set_sync): Remove redundant function.
-
-Sun Dec 20 16:26:24 1992
-
-    * 0.99pl1 released.
-
-    * scsi_ioctl.c: Bugfix - check dev->index, not dev->id against
-    NR_SCSI_DEVICES.
-
-    * sr_ioctl.c: Verify that device exists before allowing an ioctl.
-
-    * st.c: Patches from Kai - change timeout values, improve end of tape
-    handling.
-
-Sun Dec 13 18:15:23 1992
-
-    * 0.99 kernel released.  Baseline for this ChangeLog.
diff -Nru a/drivers/scsi/ChangeLog.ips b/drivers/scsi/ChangeLog.ips
--- a/drivers/scsi/ChangeLog.ips	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,122 +0,0 @@
-IBM ServeRAID driver Change Log
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-        5.00.01  - Sarasota ( 5i ) adapters must always be scanned first  
-                 - Get rid on IOCTL_NEW_COMMAND code  
-                 - Add Extended DCDB Commands for Tape Support in 5I                  
-        
-        4.90.11  - Don't actually RESET unless it's physically required
-                 - Remove unused compile options
-        
-        4.90.08  - Data Corruption if First Scatter Gather Element is > 64K
-        
-        4.90.08  - Increase Delays in Flashing ( Trombone Only - 4H )        
-        
-        4.90.05  - Use New PCI Architecture to facilitate Hot Plug Development
-        
-        4.90.01  - Add ServeRAID Version Checking
-
-        4.80.26  - Clean up potential code problems ( Arjan's recommendations )
-        
-        4.80.21  - Change memcpy() to copy_to_user() in NVRAM Page 5 IOCTL path   
-        
-        4.80.20  - Set max_sectors in Scsi_Host structure ( if >= 2.4.7 kernel )
-                 - 5 second delay needed after resetting an i960 adapter
-        
-        4.80.14  - Take all semaphores off stack                    
-                 - Clean Up New_IOCTL path
-                   
-        4.80.04  - Eliminate calls to strtok() if 2.4.x or greater 
-                 - Adjustments to Device Queue Depth               
-
-        4.80.00  - Make ia64 Safe    
-        
-        4.72.01  - I/O Mapped Memory release ( so "insmod ips" does not Fail )    
-                 - Don't Issue Internal FFDC Command if there are Active Commands 
-                 - Close Window for getting too many IOCTL's active 
-                   
-        4.72.00  - Allow for a Scatter-Gather Element to exceed MAX_XFER Size     
-        
-        4.71.00  - Change all memory allocations to not use GFP_DMA flag 
-                 - Code Clean-Up for 2.4.x kernel      
-        
-        4.70.15  - Fix Breakup for very large ( non-SG ) requests
-        
-        4.70.13  - Don't release HA Lock in ips_next() until SC taken off queue  
-                 - Unregister SCSI device in ips_release()                        
-                 - Don't Send CDB's if we already know the device is not present  
-                 
-        4.70.12  - Corrective actions for bad controller ( during initialization )
-        
-        4.70.09  - Use a Common ( Large Buffer ) for Flashing from the JCRM CD    
-                 - Add IPSSEND Flash Support                                      
-                 - Set Sense Data for Unknown SCSI Command                        
-                 - Use Slot Number from NVRAM Page 5 
-                 - Restore caller's DCDB Structure
-                                       
-        4.20.14  - Update patch files for kernel 2.4.0-test5
-
-        4.20.13  - Fix some failure cases / reset code
-                 - Hook into the reboot_notifier to flush the controller
-                   cache
-
-        4.20.03 - Rename version to coincide with new release schedules
-                - Performance fixes
-                - Fix truncation of /proc files with cat
-                - Merge in changes through kernel 2.4.0test1ac21
-
-        4.10.13 - Fix for dynamic unload and proc file system
-
-        4.10.00 - Add support for ServeRAID 4M/4L
-
-        4.00.06 - Fix timeout with initial FFDC command
-
-        4.00.05 - Remove wish_block from init routine
-                - Use linux/spinlock.h instead of asm/spinlock.h for kernels
-                  2.3.18 and later
-                - Sync with other changes from the 2.3 kernels
-
-        4.00.04 - Rename structures/constants to be prefixed with IPS_
-
-        4.00.03 - Add alternative passthru interface
-                - Add ability to flash ServeRAID BIOS
-
-        4.00.02 - Fix problem with PT DCDB with no buffer
-
-        4.00.01 - Add support for First Failure Data Capture
-
-        4.00.00 - Add support for ServeRAID 4
-
-        3.60.02 - Make DCDB direction based on lookup table.
-                - Only allow one DCDB command to a SCSI ID at a time.
-
-        3.60.01 - Remove bogus error check in passthru routine.
-
-        3.60.00 - Bump max commands to 128 for use with ServeRAID
-                  firmware 3.60.
-                - Change version to 3.60 to coincide with ServeRAID release
-                  numbering.
-
-        1.00.00 - Initial Public Release
-                - Functionally equivalent to 0.99.05
-
-        0.99.05 - Fix an oops on certain passthru commands
-
-        0.99.04 - Fix race condition in the passthru mechanism
-                  -- this required the interface to the utilities to change
-                - Fix error recovery code
-
-        0.99.03 - Make interrupt routine handle all completed request on the
-                  adapter not just the first one
-                - Make sure passthru commands get woken up if we run out of
-                  SCBs
-                - Send all of the commands on the queue at once rather than
-                  one at a time since the card will support it.
-
-        0.99.02 - Added some additional debug statements to print out
-                  errors if an error occurs while trying to read/write
-                  to a logical drive (IPS_DEBUG).
-
-                - Fixed read/write errors when the adapter is using an
-                  8K stripe size.
-
diff -Nru a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx
--- a/drivers/scsi/ChangeLog.ncr53c8xx	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,495 +0,0 @@
-Sat May 12 12:00 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version ncr53c8xx-3.4.3b
-	- Ensure LEDC bit in GPCNTL is cleared when reading the NVRAM.
-	  Fix sent by Stig Telfer <stig@api-networks.com>.
-	- Define scsi_set_pci_device() as nil for kernel < 2.4.4.
-
-Mon Feb 12 22:30 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version ncr53c8xx-3.4.3
-	- Call pci_enable_device() as AC wants this to be done.
-	- Get both the BAR cookies actual and PCI BAR values.
-	  (see Changelog.sym53c8xx rev. 1.7.3 for details)
-	- Merge changes for linux-2.4 that declare the host template 
-	  in the driver object also when the driver is statically 
-	  linked with the kernel.
-
-Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version ncr53c8xx-3.4.2
-	- See Changelog.sym53c8xx, driver version 1.7.2.
-
-Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version ncr53c8xx-3.4.1
-	- Provide OpenFirmare path through the proc FS on PPC.
-	- Remove trailing argument #2 from a couple of #undefs.
-
-Sun Jul 09 16:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version ncr53c8xx-3.4.0
-	- Remove the PROFILE C and SCRIPTS code.
-	  This facility was not this useful and thus was not longer 
-	  desirable given the increasing complexity of the driver code.
-	- Merges from FreeBSD sym-1.6.2 driver:
-	  * Clarify memory barriers needed by the driver for architectures 
-	    that implement a weak memory ordering.
-	- General cleanup:
-	  Move definitions for barriers and IO/MMIO operations to the 
-	  sym53c8xx_defs.h header files. They are now shared by the 
-	  both drivers.
-	  Use SCSI_NCR_IOMAPPED instead of NCR_IOMAPPED.
-
-Thu May 11   12:30 2000 Pam Delaney (pam.delaney@lsil.com)
-	* revision 3.3b
- 
-Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2i
-	- Return value 1 (instead of 0) from the driver setup routine.
-	- Let the driver also attach controllers that have been set to 
-	  OFF in the NVRAM as it did prior to revision 3.2g.
-
-Sat Apr 1  12:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2h
-	- Fix a compilation problem on Alpha introduced in version 3.2g.
-          (`port' changed to `base_io').
-	- Move from `sym' to this driver a tiny change for __sparc__ that 
-	  applies to cache line size (? Probably from David S Miller).
-	- Make sure no data transfer will happen for Scsi_Cmnd requests 
-	  that supply SCSI_DATA_NONE direction (this avoids some BUG() 
-	  statement in the PCI code when a data buffer is also supplied).
-
-Thu Mar 16   9:30 2000 Pam Delaney (pam.delaney@lsil.com)
-	* revision 3.3b-3
- 	- Added exclusion for the 53C1010 and 53C1010_66 chips
-	  to the driver (change to sym53c8xx_comm.h).
-
-Mon March 6  23:15 2000 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2g
-	- Add the file sym53c8xx_comm.h that collects code that should 
-	  be shared by sym53c8xx and ncr53c8xx drivers. For now, it is  
-	  a header file that is only included by the ncr53c8xx driver, 
-	  but things will be cleaned up later. This code addresses 
-	  notably:
-	  * Chip detection and PCI related initialisations
-	  * NVRAM detection and reading
-	  * DMA mapping
-	  * Boot setup command
-	  * And some other ...
-	- Add support for the new dynamic dma mapping kernel interface.
-	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
-	- Get data transfer direction from the scsi command structure 
-	  (Scsi_Cmnd) when this information is available.
-
-Mon March 6  23:15 2000 Gerard Roudier (groudier@club-internet.fr)
-        * revision 3.2g
-        - Add the file sym53c8xx_comm.h that collects code that should
-          be shared by sym53c8xx and ncr53c8xx drivers. For now, it is
-          a header file that is only included by the ncr53c8xx driver,
-          but things will be cleaned up later. This code addresses
-          notably:
-          * Chip detection and PCI related initialisations
-          * NVRAM detection and reading
-          * DMA mapping
-          * Boot setup command
-          * And some other ...
-        - Add support for the new dynamic dma mapping kernel interface.
-          Requires Linux-2.3.47 (tested with pre-2.3.47-6).
-        - Get data transfer direction from the scsi command structure
-          (Scsi_Cmnd) when this information is available.
-
-Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
-	* revision pre-3.3b-1
-	- Merge parallel driver series 3.31 and 3.2e 
-
-Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
-	* revision 3.31
-	- Added support for mounting disks on wide-narrow-wide
-	  scsi configurations.  
-	- Built off of version 3.30
-
-Mon Jan 10 13:30 2000 Pam Delaney (pam.delaney@lsil.com)
-	* revision 3.30
-	- Added capability to use the integrity checking code
-	  in the kernel (optional).
-	- Disabled support for the 53C1010.
-	- Built off of version 3.2c
-
-Sat Jan 8  22:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2e
-	- Add year 2000 copyright.
-	- Display correctly bus signals when bus is detected wrong.
-	- Remove the dead code that broke driver 3.2d.
-
-Mon Dec 6  22:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2d
-	- Change messages written by the driver at initialisation and 
-	  through the /proc FS (rather cosmetic changes that consist in
-	  printing out the PCI bus number and device/function).
-	- Get rid of the old PCI bios interface, but preserve kernel 2.0 
-	  compatibility from a simple wrapper.
-	- Remove the compilation condition about having to acquire the 
-	  io_request_lock since it seems to be a definite feature now.:)
-	- proc_dir structure no longer needed for kernel >= 2.3.27.
-	- Change the driver detection code by the sym53c8xx one, modulo 
-	  some minor changes. The driver can now attach any number of 
-	  controllers (>40) and does no longer hoger stack space at 
-	  initialisation.
-	- Definitely disable overlapped PCI arbitration for all dual 
-	  function chips, since I cannot make sure for what chip revisions 
-	  it is actually safe.
-	- Add support for the SYM53C1510D.
-	- Update the poor Tekram sync factor table.
-	- Remove the compilation condition about having to acquire the 
-	  io_request_lock since it seems to be a definite feature now.:)
-	- proc_dir structure no longer needed for kernel >= 2.3.27.
-
-Sat Sep 11  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2c
-	- Handle correctly (hopefully) jiffies wrap-around.
-	- Restore the entry used to detect 875 until revision 0xff.
-	  (I removed it inadvertently, it seems :) )
-	- Replace __initfunc() which is deprecated stuff by __init which 
-	  is not yet so. ;-)
-	- Add support of some 'resource handling' for linux-2.3.13.
-	  Basically the BARs have been changed to something more complex 
-	  in the pci_dev structure.
-	- Remove some deprecated code.
-
-Sat May 10  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision pre-3.2b-1
-	- Support for the 53C895A by Pamela Delaney <pam.delaney@lsil.com>
-	  The 53C895A contains all of the features of the 896 but has only 
-	  one channel and has a 32 bit PCI bus. It does 64 bit PCI addressing 
-	  using dual cycle PCI data transfers.
-	- Miscellaneous minor fixes.
-	- Some additions to the README.ncr53c8xx file.
-
-Sun Apr 11  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2a
-	- Add 'hostid:#id' boot option. This option allows to change the 
-	  default SCSI id the driver uses for controllers.
-	- Remove nvram layouts and driver set-up structures from the C source,
-	  and use the one defined in sym53c8xx_defs.h file.
-	  (shared by both drivers).
-	- Set for now MAX LUNS to 16 (instead of 8).
-
-Thu Mar 11  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.2	  (8xx-896 driver bundle)
-	- Only define the host template in ncr53c8xx.h and include the 
-	  sym53c8xx_defs.h file.
-	- Declare static all symbols that do not need to be visible from 
-	  outside the driver code.
-	- Add 'excl' boot command option that allows to pass to the driver 
-	  io address of devices not to attach.
-	- Add info() function called from the host template to print 
-	  driver/host information.
-	- Minor documentation additions.
-
-Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1h
-	- Fix some oooold bug that hangs the bus if a device rejects a 
-	  negotiation. Btw, the corresponding stuff also needed some cleanup 
-	  and thus the change is a bit larger than it could have been.
-	- Still some typo that made compilation fail for 64 bit (trivial fix).
-
-Sun Feb  14:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1g
-	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
-	  Pointed out by Leonard Zubkoff.
-	- Allow to tune request_irq() flags from the boot command line using 
-	  ncr53c8xx=irqm:??, as follows:
-	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
-	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
-	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
-	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
-	  a 53C8XX adapter and a network board.
-	- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
-	  harmless.
-	- Negotiate SYNC data transfers with CCS devices.
-
-Sat Jan 16  17:30 1999 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1f
-	- Some PCI fix-ups not needed any more for PPC (from Cort).
-	- Cache line size set to 16 DWORDS for Sparc   (from DSM).
-	- Waiting list look-up didn't work for the first command of the list.
-	- Remove 2 useless lines of code.
-
-Sun Dec 13  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1e
-	- Same work-around as for the 53c876 rev <= 0x15 for 53c896 rev 1:
-	  Disable overlapped arbitration. This will not make difference 
-	  since the chip has on-chip RAM.
-
-Thu Nov 26  22:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1d
-	- The SISL RAID change requires now remap_pci_mem() stuff to be 
-	  compiled for __i386__ when normal IOs are used.
-	- Minor spelling fixes in doc files.
-
-Sat Nov 21  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1c
-	- Ignore chips that are driven by SISL RAID (DAC 960).
-	  Change sent by Leonard Zubkoff and slightly reworked.
-	- Still a buglet in the tags initial settings that needed to be fixed.
-	  It was not possible to disable TGQ at system startup for devices 
-	  that claim TGQ support. The driver used at least 2 for the queue 
-	  depth but did'nt keep track of user settings for tags depth lower 
-	  than 2.
-
-Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1b
-	- The driver was unhappy when configured with default_tags > MAX_TAGS
-	  Hopefully doubly-fixed.
-	- Update the Configure.help driver section that speaks of TAGS.
-
-Wed Oct 21 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.1a
-	- Changes from Eddie Dost for Sparc and Alpha:
-	  ioremap/iounmap support for Sparc.
-	  pcivtophys changed to bus_dvma_to_phys.
-	- Add the 53c876 description to the chip table. This is only useful 
-	  for printing the right name of the controller.
-	- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
-	- Add additionnal checking of INQUIRY data:
-	  Check INQUIRY data received length is at least 7. Byte 7 of 
-	  inquiry data contains device features bits and the driver might 
-	  be confused by garbage. Also check peripheral qualifier.
-	- Cleanup of the SCSI tasks management:
-	  Remove the special case for 32 tags. Now the driver only uses the 
-	  scheme that allows up to 64 tags per LUN.
-	  Merge some code from the 896 driver.
-	  Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could  
-	  use any tag number from 1 to 253 and some non conformant devices  
-	  might have problems with large tag numbers.
-	- 'no_sync' changed to 'no_disc' in the README file. This is an old 
-	  and trivial mistake that seems to demonstrate the README file is 
-	  not often read. :)
-
-Sun Oct  4 14:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0i
-	- Cosmetic changes for sparc (but not for the driver) that needs  
-	  __irq_itoa() to be used for printed IRQ value to be understandable.
-	- Some problems with the driver that didn't occur using driver 2.5f 
-	  were due to a SCSI selection problem triggered by a clearly 
-	  documented feature that in fact seems not to work: (53C8XX chips  
-	  are claimed by the manuals to be able to execute SCSI scripts just 
-	  after abitration while the SCSI core is performing SCSI selection).
-	  This optimization is broken and has been removed.
-	- Some broken scsi devices are confused when a negotiation is started 
-	  on a LUN that does not correspond to a real device. According to 
-	  SCSI specs, this is a device firmware bug. This has been worked 
-	  around by only starting negotiation if the LUN has previously be 
-	  used for at least 1 successful SCSI command.
-	- The 'last message sent' printed out on M_REJECT message reception 
-	  was read from the SFBR i/o register after the previous message had 
-	  been sent. 
-	  This was not correct and affects all previous driver versions and 
-	  the original FreeBSD one as well. The SCSI scripts has been fixed 
-	  so that it now provides the right information to the C code.
-
-Sat Jul 18 13:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0g
-	- Preliminary fixes for Big Endian (sent by Eddie C. Dost).
-	  Big Endian architectures should work again with the driver.
-	  Eddie's patch has been partially applied since current 2.1.109 
-	  does not have all the Sparc changes of the vger tree.
-	- Use of BITS_PER_LONG instead of (~0UL == 0xffffffffUL) has fixed
-	  the problem observed when the driver was compiled using EGCS or 
-	  PGCC.
-
-Mon Jul 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0f
-	- Some spelling fixes.
-	- linux/config.h misplaced in ncr53c8xx.h
-	- MODULE_PARM stuff added for linux 2.1.
-	- check INQUIRY response data format is exactly 2. 
-	- use BITS_PER_LONG if defined. 
-
-Sun Jun 28 12:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0e
-	- Some cleanup, spelling fixes, version checks, documentations 
-	  changes, etc ...
-
-Sat Jun 20 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0c
-	- Add a boot setup option that allows to set up device queue depths 
-	  at boot-up. This option is very useful since Linux does not 
-	  allow to change scsi device queue depth once the system has been 
-	  booted up.
-
-Sun Jun 15 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0a
-	- Support for up to 64 TAGS per LUN.
-	- Rewrite the TARGET vs LUN capabilities management.
-	  CmdQueue is now handled as a LUN capability as it shall be.
-	  This also fixes a bug triggered when disabling tagged command 
-	  queuing for a device that had this feature enabled.
-	- Remove the ncr_opennings() stuff that was useless under Linux 
-	  and hard to understand to me.
-	- Add "setverbose" procfs driver command. It allows to tune 
-	  verbose level after boot-up. Setting this level to zero, for 
-	  example avoid flooding the syslog file.
-	- Add KERN_XXX to some printk's.
-
-Tue Jun 10 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 3.0
-	- Linux config changes for 2.0.34:
-	  Remove NVRAM detection config option. This option is now enabled 
-	  by default but can be disabled by editing the driver header file.
-	  Add a PROFILE config option.
-	- Update Configure.help
-	- Add calls to new function mdelay() for milli-seconds delay if 
-	  kernel version >= 2.1.105.
-	- Replace all printf(s) by printk(s). After all, the ncr53c8xx is 
-	  a driver for Linux.
-	- Perform auto-sense on COMMAND TERMINATED. Not sure it is useful.
-	- Some other minor changes.
-
-Tue Jun 4 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6n
-	- Code cleanup and simplification:
-	  Remove kernel 1.2.X and 1.3.X support.
-	  Remove the _old_ target capabilities table.
-	  Remove the error recovery code that have'nt been really useful.
-	  Use a single alignment boundary (CACHE_LINE_SIZE) for data 
-	  structures.
-	- Several aggressive SCRIPTS optimizations and changes:
-	  Reselect SCRIPTS code rewritten.
-	  Support for selection/reselection without ATN.
-	  And some others.
-	- Miscallaneous changes in the C code:
-	  Count actual number of CCB queued to the controller (future use).
-	  Lots of other minor changes.
-
-Wed May 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6m
-	- Problem of missed SCSI bus reset with the 53C895 fixed by 
-	  Richard Waltham. The 53C895 needs about 650 us for the bus 
-	  mode to settle. Delays used while resetting the controller 
-	  and the bus have been adjusted. Thanks Richard!
-	- Some simplification for 64 bit arch done ccb address testing.
-	- Add a check of the MSG_OUT phase after Selection with ATN.
-	- The new tagged queue stuff seems ok, so some informationnal 
-	  message have been conditionned by verbose >= 3.
-	- Donnot reset if a SBMC interrupt reports the same bus mode.
-	- Print out the whole driver set-up. Some options were missing and 
-	  the print statement was misplaced for modules.
-	- Ignore a SCSI parity interrupt if the chip is not connected to 
-	  the SCSI bus.
-
-Sat May 1 16:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6l
-	- Add CCB done queue support for Alpha and perhaps some other 
-	  architectures.
-	- Add some barriers to enforce memory ordering for x86 and 
-	  Alpha architectures.
-	- Fix something that looks like an old bug in the nego SIR 
-	  interrupt code in case of negotiation failure.
-
-Sat Apr 25 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6k
-	- Remove all accesses to the on-chip RAM from the C code:
-	  Use SCRIPTS to load the on-chip RAM.
-	  Use SCRIPTS to repair the start queue on selection timeout.
-	  Use the copy of script in main memory to calculate the chip 
-	  context on phase mismatch.
-	- The above allows now to use the on-chip RAM without requiring 
-	  to get access to the on-chip RAM from the C code. This makes 
-	  on-chip RAM useable for linux-1.2.13 and for Linux-Alpha for 
-	  instance.
-	- Some simplifications and cleanups in the SCRIPTS and C code.
-	- Buglet fixed in parity error recovery SCRIPTS (never tested).
-	- Minor updates in README.ncr53c8xx.
-
-Wed Apr 15 21:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6j
-	- Incorporate changes from linux-2.1.95 ncr53c8xx driver version.
-	- Add SMP support for linux-2.1.95 and above.
-	- Fix a bug when QUEUE FULL is returned and no commands are 
-	  disconnected. This happens with Atlas I / L912 and may happen 
-	  with Atlas II / LXY4.
-	- Nail another one on CHECK condition when requeuing the command 
-	  for auto-sense.
-	- Call scsi_done() for all completed commands after interrupt 
-	  handling.
-	- Increase the done queue to 24 entries.
-
-Sat Apr 4 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6i
-	- CTEST0 is used by the 53C885 for Power Management and 
-	  priority setting between the 2 functions.
-	  Use SDID instead as actual target number. Just have had to 
-	  overwrite it with SSID on reselection.
-	- Split DATA_IN and DATA_OUT scripts into 2 sub-scripts.
-	  64 segments are moved from on-chip RAM scripts.
-	  If more segments, a script in main memory is used for the 
-	  additionnal segments.
-	- Since the SCRIPTS processor continues SCRIPTS execution after 
-	  having won arbitration, do some stuff prior to testing any SCSI 
-	  phase on reselection. This should have the vertue to process 
-	  scripts in parallel with the SCSI core performing selection.
-	- Increase the done queue to 12 entries.
-
-Sun Mar 29 12:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6h
-	- Some fixes.
-
-Tue Mar 26 23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6g
-	- New done queue. 8 entries by default (6 always useable).
-	  Can be increased if needed.
-	- Resources management using doubly linked queues.
-	- New auto-sense and QUEUE FULL handling that does not need to 
-	  stall the NCR queue any more.
-	- New CCB starvation avoiding algorithm.
-	- Prepare CCBs for SCSI commands that cannot be queued, instead of 
-	  inserting these commands into the waiting list. The waiting list 
-	  is now only used while resetting and when memory for CCBs is not 
-	  yet available?
-
-Sun Feb 8 22:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6f
-	- Some fixes in order to really support the 53C895, at least with 
-	  FAST-20 devices.
-	- Heavy changes in the target/lun resources management to allow 
-	  the scripts to jump directly to the CCB on reselection instead 
-	  of walking on the lun CCBs list. Up to 32 tags per lun are now 
-	  supported without script processor and PCI traffic overhead.
-
-Sun Jan 11 22:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* revision 2.6d
-	- new (different ?) implementation of the start queue:
-          Use a simple CALL to a launch script in the CCB.
-	- implement a minimal done queue (1 entry :-) ).
-          this avoid scanning all CCBs on INT FLY (Only scan all CCBs, on 
-          overflow). Hit ratio is better than 99.9 % on my system, so no 
-          need to have a larger done queue.
-	- generalization of the restart of CCB on special condition as 
-          Abort, QUEUE FULL, CHECK CONDITION.
-          This has been called 'silly scheduler'.
-	- make all the profiling code conditionned by a config option.
-	  This spare some PCI traffic and C code when this feature is not 
-          needed.
-	- handle more cleanly the situation where direction is unknown.
-	  The pointers patching is now performed by the SCRIPTS processor.
-	- remove some useless scripts instructions.
-
-	Ported from driver 2.5 series:
-        ------------------------------
-	- Use FAST-5 instead of SLOW for slow scsi devices according to 
-	  new SPI-2 draft.
-	- Make some changes in order to accomodate with 875 rev <= 3 
-	  device errata listing 397. Minor consequences are:
-	  . Leave use of PCI Write and Invalidate under user control.
-	    Now, by default the driver does not enable PCI MWI and option
-	    'specf:y' is required in order to enable this feature.
-	  . Memory Read Line is not enabled for 875 and 875-like chips.
-	  . Programmed burst length set to 64 DWORDS (instead of 128).
-	    (Note: SYMBIOS uses 32 DWORDS for the SDMS BIOS)
-	- Add 'buschk' boot option.
-	  This option enables checking of SCSI BUS data lines after SCSI 
-	  RESET (set by default). (Submitted by Richard Waltham).
-	- Update the README file.
-	- Dispatch CONDITION MET and RESERVATION CONFLICT scsi status 
-	  as OK driver status.
-	- Update the README file and the Symbios NVRAM format definition 
-	  with removable media flags values (available with SDMS 4.09).
-	- Several PCI configuration registers fix-ups for powerpc.
-	  (Patch sent by Cort).
diff -Nru a/drivers/scsi/ChangeLog.serverraid b/drivers/scsi/ChangeLog.serverraid
--- a/drivers/scsi/ChangeLog.serverraid	Sun Nov 17 20:30:02 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,103 +0,0 @@
-IBM ServeRAID driver Change Log
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-        4.80.20  - Set max_sectors in Scsi_Host structure ( if >= 2.4.7 kernel )
-                 - 5 second delay needed after resetting an i960 adapter
-        
-        4.80.14  - Take all semaphores off stack                    
-                   Clean Up New_IOCTL path
-                   
-        4.80.04  - Eliminate calls to strtok() if 2.4.x or greater 
-                 - Adjustments to Device Queue Depth               
-
-        4.80.00  - Make ia64 Safe    
-        
-        4.72.01  - I/O Mapped Memory release ( so "insmod ips" does not Fail )    
-                   Don't Issue Internal FFDC Command if there are Active Commands 
-                   Close Window for getting too many IOCTL's active 
-                   
-        4.72.00  - Allow for a Scatter-Gather Element to exceed MAX_XFER Size     
-        
-        4.71.00  - Change all memory allocations to not use GFP_DMA flag 
-                   Code Clean-Up for 2.4.x kernel      
-        
-        4.70.15  - Fix Breakup for very large ( non-SG ) requests
-        
-        4.70.13  - Don't release HA Lock in ips_next() until SC taken off queue  
-                 - Unregister SCSI device in ips_release()                        
-                 - Don't Send CDB's if we already know the device is not present  
-                 
-        4.70.12  - Corrective actions for bad controller ( during initialization )
-        
-        4.70.09  - Use a Common ( Large Buffer ) for Flashing from the JCRM CD    
-                 - Add IPSSEND Flash Support                                      
-                 - Set Sense Data for Unknown SCSI Command                        
-                 - Use Slot Number from NVRAM Page 5 
-                 - Restore caller's DCDB Structure
-                                       
-        4.20.14  - Update patch files for kernel 2.4.0-test5
-
-        4.20.13  - Fix some failure cases / reset code
-                 - Hook into the reboot_notifier to flush the controller
-                   cache
-
-        4.20.03 - Rename version to coincide with new release schedules
-                - Performance fixes
-                - Fix truncation of /proc files with cat
-                - Merge in changes through kernel 2.4.0test1ac21
-
-        4.10.13 - Fix for dynamic unload and proc file system
-
-        4.10.00 - Add support for ServeRAID 4M/4L
-
-        4.00.06 - Fix timeout with initial FFDC command
-
-        4.00.05 - Remove wish_block from init routine
-                - Use linux/spinlock.h instead of asm/spinlock.h for kernels
-                  2.3.18 and later
-                - Sync with other changes from the 2.3 kernels
-
-        4.00.04 - Rename structures/constants to be prefixed with IPS_
-
-        4.00.03 - Add alternative passthru interface
-                - Add ability to flash ServeRAID BIOS
-
-        4.00.02 - Fix problem with PT DCDB with no buffer
-
-        4.00.01 - Add support for First Failure Data Capture
-
-        4.00.00 - Add support for ServeRAID 4
-
-        3.60.02 - Make DCDB direction based on lookup table.
-                - Only allow one DCDB command to a SCSI ID at a time.
-
-        3.60.01 - Remove bogus error check in passthru routine.
-
-        3.60.00 - Bump max commands to 128 for use with ServeRAID
-                  firmware 3.60.
-                - Change version to 3.60 to coincide with ServeRAID release
-                  numbering.
-
-        1.00.00 - Initial Public Release
-                - Functionally equivalent to 0.99.05
-
-        0.99.05 - Fix an oops on certain passthru commands
-
-        0.99.04 - Fix race condition in the passthru mechanism
-                  -- this required the interface to the utilities to change
-                - Fix error recovery code
-
-        0.99.03 - Make interrupt routine handle all completed request on the
-                  adapter not just the first one
-                - Make sure passthru commands get woken up if we run out of
-                  SCBs
-                - Send all of the commands on the queue at once rather than
-                  one at a time since the card will support it.
-
-        0.99.02 - Added some additional debug statements to print out
-                  errors if an error occurs while trying to read/write
-                  to a logical drive (IPS_DEBUG).
-
-                - Fixed read/write errors when the adapter is using an
-                  8K stripe size.
-
diff -Nru a/drivers/scsi/ChangeLog.sym53c8xx b/drivers/scsi/ChangeLog.sym53c8xx
--- a/drivers/scsi/ChangeLog.sym53c8xx	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,593 +0,0 @@
-Sat May 12 12:00 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.3c
-	- Ensure LEDC bit in GPCNTL is cleared when reading the NVRAM.
-	  Fix sent by Stig Telfer <stig@api-networks.com>.
-	- Backport from SYM-2 the work-around that allows to support 
-	  hardwares that fail PCI parity checking.
-	- Check that we received at least 8 bytes of INQUIRY response 
-	  for byte 7, that contains device capabilities, to be valid.
-	- Define scsi_set_pci_device() as nil for kernel < 2.4.4.
-	- + A couple of minor changes.
-	  
-Sat Apr 7 19:30 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.3b
-	- Fix an unaligned LOAD from scripts (was used as dummy read).
-	- In ncr_soft_reset(), only try to ABORT the current operation 
-	  for chips that support SRUN bit in ISTAT1 and if SCRIPTS are 
-	  currently running, as 896 and 1010 manuals suggest.
-	- In the CCB abort path, donnot assume that the CCB is currently 
-	  queued to SCRIPTS. This is not always true, notably after a 
-	  QUEUE FULL status or when using untagged commands.
-
-Sun Mar 4 18:30 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.3a
-	- Fix an issue in the ncr_int_udc() (unexpected disconnect)
-	  handling. If the DSA didn't match a CCB, a bad write to 
-	  memory could happen.
-
-Mon Feb 12 22:30 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.3
-	- Support for hppa.
-	  Tiny patch sent to me by Robert Hirst.
-	- Tiny patch for ia64 sent to me by Pamela Delaney.
-
-Tue Feb 6 13:30 2001 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.3-pre1
-	- Call pci_enable_device() as AC wants this to be done.
-	- Get both the BAR cookies used by CPU and actual PCI BAR 
-	  values used from SCRIPTS. Recent PCI chips are able to 
-	  access themselves using internal cycles, but they compare 
-	  BAR values to destination address to make decision.
-	  Earlier chips simply use PCI transactions to access IO 
-	  registers from SCRIPTS.
-	  The bus_dvma_to_mem() interface that reverses the actual 
-	  PCI BAR value from the BAR cookie is now useless.
-	  This point had been discussed at the list and the solution 
-	  got approved by PCI code maintainer (Martin Mares).
-	- Merge changes for linux-2.4 that declare the host template 
-	  in the driver object also when the driver is statically 
-	  linked with the kernel.
-	- Increase SCSI message size up to 12 bytes, given that 8 
-	  bytes was not enough for the PPR message (fix).
-	- Add field 'maxoffs_st' (max offset for ST data transfers).
-	  The C1010 supports offset 62 in DT mode but only 31 in 
-	  ST mode, to 2 different values for the max SCSI offset 
-	  are needed. Replace the obviously wrong masking of the 
-	  offset against 0x1f for ST mode by a lowering to 
-	  maxoffs_st of the SCSI offset in ST mode.
-	- Refine a work-around for the C1010-66. Revision 1 does 
-	  not requires extra cycles in DT DATA OUT phase.
-	- Add a missing endian-ization (abrt_tbl.addr).
-	- Minor clean-up in the np structure for fields accessed 
-	  from SCRIPTS that requires special alignments.
-
-Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.2
-	- Remove the hack for PPC added in previous driver version.
-	- Add FE_DAC feature bit to distinguish between 64 bit PCI 
-	  addressing (FE_DAC) and 64 bit PCI interface (FE_64BIT).
-	- Get rid of the boot command line "ultra:" argument.
-	  This parameter wasn't that clever since we can use "sync:" 
-	  for Ultra/Ultra2 settings, and for Ultra3 we may want to 
-	  pass PPR options (for now only DT clocking).
-	- Add FE_VARCLK feature bit that indicates that SCSI clock 
-	  frequency may vary depending on board design and thus, 
-	  the driver should try to evaluate the SCSI clock.
-	- Simplify the way the driver determine the SCSI clock:
-	  ULTRA3 -> 160 MHz, ULTRA2 -> 80 MHz otherwise 40 MHz.
-	  Measure the SCSI clock frequency if FE_VARCLK is set.
-	- Remove FE_CLK80 feature bit that got useless.
-	- Add support for the SYM53C875A (Pamela Delaney).
-
-Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.1
-	- Provide OpenFirmare path through the proc FS on PPC.
-	- Download of on-chip SRAM using memcpy_toio() doesn't work 
-	  on PPC. Restore previous method (MEMORY MOVE from SCRIPTS).
-	- Remove trailing argument #2 from a couple of #undefs.
-
-Sun Jul 09 16:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.7.0
-	- Remove the PROFILE C and SCRIPTS code.
-	  This facility was not this useful and thus was not longer 
-	  desirable given the increasing complexity of the driver code.
-	- Merges from FreeBSD sym-1.6.2 driver:
-	  * Clarify memory barriers needed by the driver for architectures 
-	    that implement a weak memory ordering.
-	  * Simpler handling of illegal phases and data overrun from 
-	    SCRIPTS. These errors are now immediately reported to 
-	    the C code by an interrupt.
-	  * Sync the residual handling code with sym-1.6.2 and now 
-	    report `resid' to user for linux version >= 2.3.99 
-	- General cleanup:
-	  Move definitions for barriers and IO/MMIO operations to the 
-	  sym53c8xx_defs.h header files. They are now shared by the 
-	  both drivers.
-	  Remove unused options that claimed to optimize for the 896.
-	  If fact, they were not this clever. :)
-	  Use SCSI_NCR_IOMAPPED instead of NCR_IOMAPPED.
-	  Remove a couple of unused fields from data structures.
-
-Thu May 11 12:40 2000 Pam Delaney (pam.delaney@lsil.com)
-	* version sym53c8xx-1.6b
-	- Merged version.
-
-Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5m
-	- Return value 1 (instead of 0) from the driver setup routine.
-	- Do not enable PCI DAC cycles. This just broke support for 
-	  SYM534C896 on sparc64. Problem fixed by David S. Miller.
-
-Fri Apr 14 9:00 2000 Pam Delaney (pam.delaney@lsil.com)
-	* version sym53c8xx-1.6b-9
-	- Added 53C1010_66 support.
-	- Small fix to integrity checking code.
-	- Removed requirement for integrity checking if want to run
-	  at ultra 3.
- 
-Sat Apr 1  12:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5l
-	- Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that 
-	  applies to cache line size (? Probably from David S Miller).
-	- Make sure no data transfer will happen for Scsi_Cmnd requests 
-	  that supply SCSI_DATA_NONE direction (this avoids some BUG() 
-	  statement in the PCI code when a data buffer is also supplied).
-
-Sat Mar 11 12:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.6b-5
-	- Test against expected data transfer direction from SCRIPTS.
-	- Add support for the new dynamic dma mapping kernel interface.
-	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
-	  Many thanks to David S. Miller for his preliminary changes 
-	  that have been useful guidelines.
-	- Get data transfer direction from the scsi command structure 
-	  (Scsi_Cmnd) with kernels that provide this information.
-
-Mon Mar  6 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5k
-	- Test against expected data transfer direction from SCRIPTS.
-	- Revert the change in 'ncr_flush_done_cmds()' but unmap the 
-	  scsi dma buffer prior to queueing the command to our done 
-	  list.
-	- Miscellaneous (minor) fixes in the code added in driver 
-	  version 1.5j.
-
-Mon Feb 14 4:00 2000 Pam Delaney (pam.delaney@lsil.com)
- 	* version sym53c8xx-pre-1.6b-2.
-	- Updated the SCRIPTS error handling of the SWIDE
-	  condition - to remove any reads of the sbdl
-	  register. Changes needed because the 896 and 1010
-	  chips will check parity in some special circumstances.
-	  This will cause a parity error interrupt if not in
-	  data phase.  Changes based on those made in the
-	  FreeBSD driver version 1.3.2.
-
-Sun Feb 20 11:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5j
-	- Add support for the new dynamic dma mapping kernel interface.
-	  Requires Linux-2.3.47 (tested with pre-2.3.47-6).
-	  Many thanks to David S. Miller for his preliminary changes 
-	  that have been useful guidelines, for having reviewed the 
-	  code and having tested this driver version on Ultra-Sparc.
-	- 2 tiny bugs fixed in the PCI wrapper that provides support 
-	  for early kernels without pci device structure.
-	- Get data transfer direction from the scsi command structure 
-	  (Scsi_Cmnd) with kernels that provide this information.
-	- Fix an old bug that only affected 896 rev. 1 when driver 
-	  profile support option was set in kernel configuration.
-
-Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
- 	* version sym53c8xx-pre-1.6b-1.
-	- Merge parallel driver series 1.61 and 1.5e 
-
-Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com)
-	* version sym53c8xx-1.61
-	- Added support for mounting disks on wide-narrow-wide
-	  scsi configurations. 
-	- Modified offset to be a maximum of 31 in ST mode, 
-	  62 in DT mode.
-	- Based off of 1.60
-
-Mon Jan 10 10:00 2000 Pam Delaney (pam.delaney@lsil.com)
-	* version sym53c8xx-1.60
-	- Added capability to use the integrity checking code
-	  in the kernel (optional).
-	-  Added PPR negotiation.
-	- Added support for 53C1010 Ultra 3 part.
-	- Based off of 1.5f
-
-Sat Jan 8  22:00 2000 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5h
-	- Add year 2000 copyright.
-	- Display correctly bus signals when bus is detected wrong.
-	- Some fix for Sparc from DSM that went directly to kernel tree.
-
-Mon Dec 6  22:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5g
-	- Change messages written by the driver at initialisation and 
-	  through the /proc FS (rather cosmetic changes that consist in
-	  printing out the PCI bus number and PCI device/function).
-	- Ensure the SCRIPTS processor is stopped while calibrating the 
-	  SCSI clock (the initialisation code has been a bit reworked).
-	  Change moved to the FreeBSD sym_hipd driver).
-	- Some fixes in the MODIFY_DP/IGN_RESIDUE code and residual 
-	  calculation (moved from FreeBSD sym_hipd driver).
-	- Add NVRAM support for Tekram boards that use 24C16 EEPROM.
-	  Code moved from the FreeBSD sym_hipd driver, since it has 
-	  been that one that got this feature first.
-	- Definitely disable overlapped PCI arbitration for all dual 
-	  function chips, since I cannot make sure for what chip revisions 
-	  it is actually safe.
-	- Add support for the SYM53C1510D (also for ncr53c8xx).
-	- Fix up properly the PCI latency timer when needed or asked for.
-	- Get rid of the old PCI bios interface, but preserve kernel 2.0 
-	  compatibility from a simple wrapper.
-	- Update the poor Tekram sync factor table.
-	- Fix in a tiny 'printk' bug that may oops in case of extended 
-	  errors (unrecovered parity error, data overrun, etc ...)
-	  (Sent by Pamela Delaney from LSILOGIC)
-	- Remove the compilation condition about having to acquire the 
-	  io_request_lock since it seems to be a definite feature now.:)
-	- Change get_pages by GetPages since Linux >= 2.3.27 now wants 
-	  get_pages to ever be used as a kernel symbol (from 2.3.27).
-	- proc_dir structure no longer needed for kernel >= 2.3.27.
-
-Sun Oct  3  19:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5f
-	- Change the way the driver checks the PCI clock frequency, so 
-	  that overclocked PCI BUS up to 48 MHz will not be refused.
-	  The more the BUS is overclocked, the less the driver will 
-	  guarantee that its measure of the SCSI clock is correct.
-	- Backport some minor improvements of SCRIPTS from the sym_hipd 
-	  driver.
-	- Backport the code rewrite of the START QUEUE dequeuing (on 
-	  bad scsi status received) from the sym_hipd driver.
-
-Sat Sep 11  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5e
-	- New linux-2.3.13 __setup scheme support added.
-	- Cleanup of the extended error status handling:
-	  Use 1 bit per error type.
-	- Also save the extended error status prior to auto-sense.
-	- Add the FE_DIFF chip feature bit to indicate support of 
-	  diff probing from GPIO3 (825/825A/876/875).
-	- Remove the quirk handling that has been useless since day one.
-	- Work-around PCI chips being reported twice on some platforms.
-	- Add some redundant PCI reads in order to deal with common 
-	  bridge misbehaviour regarding posted write flushing.
-	- Add some other conditionnal code for people who have to deal 
-	  with really broken bridges (they will have to edit a source 
-	  file to try these options).
-	- Handle correctly (hopefully) jiffies wrap-around.
-	- Restore the entry used to detect 875 until revision 0xff.
-	  (I removed it inadvertently, it seems :) )
-	- Replace __initfunc() which is deprecated stuff by __init which 
-	  is not yet so. ;-)
-	- Rewrite the MESSAGE IN scripts more generic by using a MOVE 
-	  table indirect. Extended messages of any size are accepted now.
-	  (Size is limited to 8 for now, but a constant is just to be 
-	  increased if necessary)
-	- Fix some bug in the fully untested MDP handling:) and share 
-	  some code between MDP handling and residual calculation.
-	- Calculate the data transfer residual as the 2's complement 
-	  integer (A positive value in returned on data overrun, and 
-	  a negative one on underrun).
-	- Add support of some 'resource handling' for linux-2.3.13.
-	  Basically the BARs have been changed to something more complex 
-	  in the pci_dev structure.
-	- Remove some deprecated code.
-
-Sat Jun  5  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5c
-	- Do not negotiate on auto-sense if we are currently using 8 bit 
-	  async transfer for the target.
-	- Only check for SISL/RAID on i386 platforms.
-	  (A problem has been reported on PPC with that code).
-	- On MSG REJECT for a negotiation, the driver attempted to restart 
-	  the SCRIPT processor when this one was already running.
-
-Sat May 29  12:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5b
-	- Force negotiation prior auto-sense.
-	  This ensures that the driver will be able to grab the sense data 
-	  from a device that has received a BUS DEVICE RESET message from 
-	  another initiator.
-	- Complete all disconnected CCBs for a logical UNIT if we are told 
-	  about a UNIT ATTENTION for a RESET condition by this target.
-	- Add the control command 'cleardev' that allows to send a ABORT  
-	  message to a logical UNIT (for test purpose).
-
-Tue May 25  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5a
-	- Add support for task abort and bus device reset SCSI message 
-	  and implement proper synchonisation with SCRIPTS to handle 
-          correctly task abortion without races.
-	- Send an ABORT message (if untagged) or ABORT TAG message (if tagged)
-	  when the driver is told to abort a command that is disconnected and 
-	  complete the command with appropriate error.
-	  If the aborted command is not yet started, remove it from the start 
-	  queue and complete it with error.
-	- Add the control command 'resetdev' that allows to send a BUS 
-	  DEVICE RESET message to a target (for test purpose).
-	- Clean-up some unused or useless code.
-
-Fri May 21  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.5
-	- Add support for CHMOV with Wide controllers.
-	- Handling of the SWIDE (low byte residue at the end of a CHMOV 
-	  in DATA IN phase with WIDE transfer when the byte count gets odd).
-	- Handling of the IGNORE WIDE RESIDUE message.
-	  Handled from SCRIPTS as possible with some optimizations when both 
-	  a wide device and the controller are odd at the same time (SWIDE 
-	  present and IGNORE WIDE RESIDUE message on the BUS at the same time).
-	- Check against data OVERRUN/UNDERRUN condition at the end of a data 
-	  transfer, whatever a SWIDE is present (OVERRUN in DATA IN phase) 
-	  or the SODL is full (UNDERRUN in DATA out phase).
-	- Handling of the MODIFY DATA POINTER message.
-	  This one cannot be handled from SCRIPTS, but hopefully it will not
-	  happen very often. :)
-	- Large rewrite of the SCSI MESSAGE handling.
-
-Sun May 9  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.4
-	- Support for IMMEDIATE ARBITRATION.
-	  See the README file for detailed information about this feature.
-	  Requires both a compile option and a boot option.
-	- Minor SCRIPTS optimization in reselection pattern for LUN 0.
-	- Simpler algorithm to deal with SCSI command starvation.
-	  Just use 2 tag counters in flip/flop and switch to the other 
-	  one every 3 seconds.
-	- Do some work in SCRIPTS after the SELECT instruction and prior 
-	  to testing for a PHASE. SYMBIOS say this feature is working fine. 
-	  (Btw, only problems with Toshiba 3401B had been reported).
-	- Measure the PCI clock speed and do not attach controllers if 
-	  result is greater than 37 MHz. Since the precision of the 
-	  algorithm (from Stefan Esser) is better than 2%, this should 
-	  be fine.
-	- Fix the misdetection of SYM53C875E (was detected as a 876).
-	- Fix the misdetection of SYM53C810 not A (was detected as a 810A).
-	- Support for up to 256 TAGS per LUN (CMD_PER_LUN).
-	  Currently limited to 255 due to Linux limitation. :)
-	- Support for up to 508 active commands (CAN_QUEUE).
-	- Support for the 53C895A by Pamela Delaney <pam.delaney@lsil.com>
-	  The 53C895A contains all of the features of the 896 but has only 
-	  one channel and has a 32 bit PCI bus. It does 64 bit PCI addressing 
-	  using dual cycle PCI data transfers.
-	- Miscellaneous minor fixes.
-	- Some additions to the README.ncr53c8xx file.
-
-Tue Apr 15  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.3e
-	- Support for any number of LUNs (64) (SPI2-compliant).
-	  (Btw, this may only be ever useful under linux-2.2 ;-))
-
-Sun Apr 11  10:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.3d
-	- Add 'hostid:#id' boot option. This option allows to change the 
-	  default SCSI id the driver uses for controllers.
-	- Make SCRIPTS not use self-mastering for PCI.
-	  There were still 2 places the driver used this feature of the 
-	  53C8XX family.
-	- Move some data structures (nvram layouts and driver set-up) to 
-	  the sym53c8xx_defs.h file. So, the both drivers will share them.
-	- Set MAX LUNS to 16 (instead of 8).
-
-Sat Mar 20  21:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.3b
-	- Add support for NCR PQS PDS.
-	  James Bottomley <James.Bottomley@columbiasc.ncr.com>
-	- Allow value 0 for host ID.
-	- Support more than 8 controllers (> 40 in fact :-) )
-	- Add 'excl=#ioaddr' boot option: exclude controller.
-	  (Version 1.3a driver)
-
-Thu Mar 11  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.3   (8xx-896 driver bundle)
-	- Equivalent changes as ncr53c8xx-3.2 due to the driver bundle.
-	  (See Changelog.ncr53c8xx)
-	- Do a normal soft reset as first chip reset, since aborting current 
-	  operation may raise an interrupt we are not able to handle since 
-	  the interrupt handler is not yet established.
-
-Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.2b
-	- Fix some oooold bug that hangs the bus if a device rejects a 
-	  negotiation. Btw, the corresponding stuff also needed some cleanup 
-	  and thus the change is a bit larger than it could have been.
-	- Still some typo that made compilation fail for 64 bit (trivial fix).
-
-Sun Feb 21  20:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.2a
-	- The rewrite of the interrupt handling broke the SBMC interrupt 
-	  handling due to a 1 bit mask tiny error. Hopefully fixed.
-	- If INQUIRY came from a scatter list, the driver looked into 
-	  the scatterlist instead of the data.:) Since this should never
-	  happen, we just discard the data if use_sg is not zero.
-
-Fri Feb 12  23:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.2
-	- Major rewrite of the interrupt handling and recovery stuff for 
-	  the support of non compliant SCSI removal, insertion and all 
-	  kinds of screw-up that may happen on the SCSI BUS.
-	  Hopefully, the driver is now unbreakable or may-be, it is just 
-	  quite brocken. :-)
-	  Many thanks to Johnson Russel (Symbios) for having responded to 
-	  my questions and for his interesting advices and comments about 
-	  support of SCSI hot-plug.
-	- Add 'recovery' option to driver set-up.
-	- Negotiate SYNC data transfers with CCS devices.
-	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
-	  Pointed out by Leonard Zubkoff.
-
-Sun Jan 31  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.1a
-	- Some 896 chip revisions (all for now :-)), may hang-up if the 
-	  soft reset bit is set at the wrong time while SCRIPTS are running.
-	  We need to first abort the current SCRIPTS operation prior to 
-	  resetting the chip. This fix has been sent to me by SYMBIOS/LSI 
-	  and I just translated it into ncr53c8xx syntax.
-	  Must be considered 100 % trustable, unless I did some mistake 
-	  when translating it. :-)
-
-Sun Jan 24  18:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.1
-	- Major rewrite of the SCSI parity error handling.
-	  The informations contained in the data manuals are incomplete about 
-	  this feature.
-	  I asked SYMBIOS about and got in reply the explanations that are 
-	  _indeed_ missing in the data manuals.
-	- Allow to tune request_irq() flags from the boot command line using 
-	  ncr53c8xx=irqm:??, as follows:
-	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
-	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
-	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
-	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
-	  a 53C8XX adapter and a network board.
-	- Fix for 64 bit PCI address register calculation. (Lance Robinson)
-	- Fix for big-endian in phase mismatch handling. (Michal Jaegermann)
-
-Fri Jan  1  20:00 1999 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.0a
-	- Waiting list look-up didn't work for the first command of the list.
-	  Hopefully fixed, but tested on paper only. ;)
-	- Remove the most part of PPC specific code for Linux-2.2.
-	  Thanks to Cort.
-	- Some other minors changes.
-
-Sat Dec 19  21:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version sym53c8xx-1.0
-	- Define some new IO registers for the 896 (istat1, mbox0, mbox1)
-	- Revamp slighly the Symbios NVRAM lay-out based on the excerpt of 
-	  the header file I received from Symbios.
-	- Check the PCI bus number for the boot order (Using a fast 
-	  PCI controller behing a PCI-PCI bridge seems sub-optimal).
-	- Disable overlapped PCI arbitration for the 896 revision 1.
-	- Reduce a bit the number of IO register reads for phase mismatch 
-	  by reading DWORDS at a time instead of BYTES.
-
-Thu Dec  3  24:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.18
-	- I received this afternoon a 896 from SYMBIOS and started testing  
-	  the driver with this beast. After having fixed 3 buglets, it worked  
-	  with all features enabled including the phase mismatch handling 
-	  from SCRIPTS. Since this feature is not yet tested enough, the 
-	  boot option 'ncr53c8xx=specf:1' is still required to enable the 
-	  driver to handle PM from SCRIPTS. 
-
-Sun Nov 29  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.17
-	- The SISL RAID change requires now remap_pci_mem() stuff to be 
-	  compiled for __i386__ when normal IOs are used.
-	- The PCI memory read from SCRIPTS that should ensure ordering 
-	  was in fact misplaced. BTW, this may explain why broken PCI 
-	  device drivers regarding ordering are working so well. ;-)
-	- Rewrite ncr53c8xx_setup (boot command line options) since the  
-	  binary code was a bit too bloated in my opinion.
-	- Make the code simpler in the wakeup_done routine.
-
-Tue Nov 24  23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.16
-	- Add SCSI_NCR_OPTIMIZE_896_1 compile option and 'optim' boot option.
-	  When set, the driver unconditionnaly assumes that the interrupt 
-	  handler is called for command completion, then clears INTF, scans 
-	  the done queue and returns if some completed CCB is found. If no 
-	  completed CCB are found, interrupt handling will proceed normally.
-	  With a 896 that handles MA from SCRIPTS, this can be a great win, 
-	  since the driver will never performs PCI read transactions, but 
-	  only PCI write transactions that may be posted.
-	  If the driver haven't to also raise the SIGP this would be perfect.
-	  Even with this penalty, I think that this will work great.
-	  Obviously this optimization makes sense only if the IRQ is not 
-	  shared with another device.
-	- Still a buglet in the tags initial settings that needed to be fixed.
-	  It was not possible to disable TGQ at system startup for devices 
-	  that claim TGQ support. The driver used at least 2 for the queue 
-	  depth but did'nt keep track of user settings for tags depth lower 
-	  than 2.
-
-Thu Nov 19  23:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.15
-	- Add support for hardware LED control of the 896.
-	- Ignore chips that are driven by SISL RAID (DAC 960).
-	  Change sent by Leonard Zubkoff and slightly reworked.
-	- Prevent 810A rev 11 and 860 rev 1 from using cache line based 
-	  transactions since those early chip revisions may use such on 
-	  LOAD/STORE instructions (work-around).
-	- Remove some useless and bloat code from the pci init stuff.
-	- Do not use the readX()/writeX() kernel functions for __i386__, 
-	  since they perform useless masking operations in order to deal 
-	  with broken driver in 2.1.X kernel.
-
-Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.14
-	- The driver was unhappy when configured with default_tags > MAX_TAGS
-	  Hopefully doubly-fixed.
-	- Set PCI_PARITY in PCI_COMMAND register in not set (PCI fix-up).
-	- Print out some message if phase mismatch is handled from SCRIPTS.
-
-Sun Nov 1  14H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.13
-	- Some rewrite of the device detection code. This code had been 
-	  patched too much and needed to be face-lifted a bit.
-	  Remove all platform dependant fix-ups that was not needed or
-	  conflicted with some other driver code as work-arounds.
-	  Reread the NVRAM before the calling of ncr_attach(). This spares 
-	  stack space and so allows to handle more boards.
-	  Handle 64 bit base addresses under linux-2.0.X.
-	  Set MASTER bit in PCI COMMAND register if not set.
-
-Wed Oct 30 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.12
-	- Damned! I just broke the driver for Alpha by leaving a stale 
-	  instruction in the source code. Hopefully fixed.
-	- Do not set PFEN when it is useless. Doing so we are sure that BOF 
-	  will be active, since the manual appears to be very unclear on what 
-	  feature is actually used by the chip when both PFEN and BOF are 
-	  set.
-
-Sat Oct 24 16H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.11
-	- LOAD/STORE instructions were miscompiled for register offsets 
-	  beyond 0x7f. This broke accesses to 896' new registers.
-	- Disable by default Phase Mismatch handling from SCRIPTS, since 
-	  current 896 rev.1 seems not to operate safely with the driver
-	  when this feature is enabled (and above LOAD/STORE fix applied).
-	  I will change the default to 'enabled' when this problem will be 
-	  solved.
-	  Using boot option 'ncr53c8xx=specf:1' enables this feature.
-	- Implement a work-around (DEL 472 - ITEM 5) that should allow the 
-	  driver to safely enable hardware phase mismatch with 896 rev. 1.
-
-Tue Oct 20 22H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.10
-	- Add the 53c876 description to the chip table. This is only useful 
-	  for printing the right name of the controller.
-	- Add additionnal checking of INQUIRY data:
-	  Check INQUIRY data received length is at least 7. Byte 7 of 
-	  inquiry data contains device features bits and the driver might 
-	  be confused by garbage. Also check peripheral qualifier.
-	- Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could  
-	  use any tag number from 1 to 253 and some non conformant devices  
-	  might have problems with large tag numbers.
-	- Use NAME53C and NAME53C8XX for chip name prefix chip family name.
-	  Just give a try using "sym53c" and "sym53c8xx" instead of "ncr53c" 
-	  and "ncr53c8xx". :-)
-
-Sun Oct 11 17H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.9
-	- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
-	- Break ncr_scatter() into 2 functions in order to guarantee best 
-	  possible code optimization for the case we get a scatter list.
-	- Add the code intended to support up to 1 tera-byte for 64 bit systems.
-	  It is probably too early, but I wanted to complete the thing.
-
-Sat Oct 3 14H00 1998 Gerard Roudier (groudier@club-internet.fr)
-	* version pre-sym53c8xx-0.8
-	- Do some testing with io_mapped and fix what needed to be so.
-	- Wait for SCSI selection to complete or time-out immediately after 
-	  the chip won arbitration, since executing SCRIPTS while the SCSI 
-	  core is performing SCSI selection breaks the selection procedure 
-	  at least for some chip revisions.
-	- Interrupt the SCRIPTS if a device does not go to MSG OUT phase after 
-	  having been selected with ATN. Such a situation is not recoverable, 
-	  better to fail when we are stuck.
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/Kconfig	Sun Nov 17 20:30:15 2002
@@ -15,7 +15,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sd_mod.o.  If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.  Do not compile this driver as a
+	  <file:Documentation/scsi/scsi.txt>.  Do not compile this driver as a
 	  module if your root file system (the one containing the directory /)
 	  is located on a SCSI disk. In this case, do not compile the driver
 	  for your SCSI host adapter (below) as a module either.
@@ -27,14 +27,14 @@
 	  If you want to use a SCSI tape drive under Linux, say Y and read the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and
-	  <file:drivers/scsi/README.st> in the kernel source.  This is NOT for
+	  <file:Documentation/scsi/st.txt> in the kernel source.  This is NOT for
 	  SCSI CD-ROMs.
 
 	  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 st.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config CHR_DEV_OSST
 	tristate "SCSI OnStream SC-x0 tape support"
@@ -49,7 +49,7 @@
 	  tapes (QIC-157) and can be driven by the standard driver st.
 	  For more information, you may have a look at the SCSI-HOWTO
 	  <http://www.linuxdoc.org/docs.html#howto>  and
-	  <file:drivers/scsi/README.osst>  in the kernel source.
+	  <file:Documentation/scsi/osst.txt>  in the kernel source.
 	  More info on the OnStream driver may be found on
 	  <http://linux1.onstream.nl/test/>
 	  Please also have a look at the standard st docu, as most of it
@@ -59,7 +59,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called osst.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR
 	tristate "SCSI CDROM support"
@@ -74,7 +74,7 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called sr_mod.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>.
+	  <file:Documentation/scsi/scsi.txt>.
 
 config BLK_DEV_SR_VENDOR
 	bool "Enable vendor-specific extensions (for SCSI CDROM)"
@@ -103,13 +103,13 @@
 	  quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
 	  For other devices, it's possible that you'll have to write the
 	  driver software yourself. Please read the file
-	  <file:Documentation/scsi-generic.txt> for more information.
+	  <file:Documentation/scsi/scsi-generic.txt> for more information.
 
 	  If you want to compile this as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/modules.txt> and
-	  <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
-	  say N.
+	  <file:Documentation/scsi/scsi.txt>. The module will be called sg.o.
+	  If unsure, say N.
 
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
@@ -235,7 +235,7 @@
 
 	  It is explained in section 3.3 of the SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>. You might also want to
-	  read the file <file:drivers/scsi/README.aha152x>.
+	  read the file <file:Documentation/scsi/aha152x.txt>.
 
 	  This driver is also available as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want).
@@ -315,7 +315,7 @@
 	  Information on the configuration options for this controller can be
 	  found by checking the help file for each of the available
 	  configuration options. You should read
-	  <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
+	  <file:Documentation/scsi/aic7xxx_old.txt> at a minimum before
 	  contacting the maintainer with any questions.  The SCSI-HOWTO,
 	  available from <http://www.linuxdoc.org/docs.html#howto>, can also
 	  be of great help.
@@ -335,7 +335,7 @@
 	help
 	  This driver supports all of Adaptec's I2O based RAID controllers as 
 	  well as the DPT SmartRaid V cards.  This is an Adaptec maintained
-	  driver by Deanna Bonds.  See <file:drivers/scsi/README.dpti>.
+	  driver by Deanna Bonds.  See <file:Documentation/scsi/dpti.txt>.
 
 	  This driver is also available as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want).
@@ -362,7 +362,7 @@
 	depends on SCSI
 	help
 	  This is support for an ISA bus SCSI host adapter.  You'll find more
-	  information in <file:drivers/scsi/README.in2000>. If it doesn't work
+	  information in <file:Documentation/scsi/in2000.txt>. If it doesn't work
 	  out of the box, you may have to change the jumpers for IRQ or
 	  address selection.
 
@@ -377,7 +377,7 @@
 	depends on !X86_64 && SCSI && PCI
 	---help---
 	  This is support for the AM53/79C974 SCSI host adapters.  Please read
-	  <file:drivers/scsi/README.AM53C974> for details.  Also, the
+	  <file:Documentation/scsi/AM53C974.txt> for details.  Also, the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, is for you.
 
@@ -409,8 +409,8 @@
 	  This is support for BusLogic MultiMaster and FlashPoint SCSI Host
 	  Adapters. Consult the SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and the files
-	  <file:drivers/scsi/README.BusLogic> and
-	  <file:drivers/scsi/README.FlashPoint> for more information. If this
+	  <file:Documentation/scsi/BusLogic.txt> and
+	  <file:Documentation/scsi/FlashPoint.txt> for more information. If this
 	  driver does not work correctly without modification, please contact
 	  the author, Leonard N. Zubkoff, by email to lnz@dandelion.com.
 
@@ -454,7 +454,7 @@
 	  This is support for DTC 3180/3280 SCSI Host Adapters.  Please read
 	  the SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>, and the file
-	  <file:drivers/scsi/README.dtc3x80>.
+	  <file:Documentation/scsi/dtc3x80.txt>.
 
 	  This driver is also available as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want).
@@ -648,7 +648,7 @@
 	  for the Trantor T130B in its default configuration; you might have
 	  to pass a command line option to the kernel at boot time if it does
 	  not detect your card.  See the file
-	  <file:drivers/scsi/README.g_NCR5380> for details.
+	  <file:Documentation/scsi/g_NCR5380.txt> for details.
 
 config SCSI_IBMMCA
 	tristate "IBMMCA SCSI support"
@@ -781,7 +781,7 @@
 	  newer drives)", below.
 
 	  For more information about this driver and how to use it you should
-	  read the file <file:drivers/scsi/README.ppa>.  You should also read
+	  read the file <file:Documentation/scsi/ppa.txt>.  You should also read
 	  the SCSI-HOWTO, which is available from
 	  <http://www.linuxdoc.org/docs.html#howto>.  If you use this driver,
 	  you will still be able to use the parallel port for other tasks,
@@ -810,7 +810,7 @@
 	  here and Y to "IOMEGA Parallel Port (ppa - older drives)", above.
 
 	  For more information about this driver and how to use it you should
-	  read the file <file:drivers/scsi/README.ppa>.  You should also read
+	  read the file <file:Documentation/scsi/ppa.txt>.  You should also read
 	  the SCSI-HOWTO, which is available from
 	  <http://www.linuxdoc.org/docs.html#howto>.  If you use this driver,
 	  you will still be able to use the parallel port for other tasks,
@@ -916,7 +916,7 @@
 	  <http://www.linuxdoc.org/docs.html#howto>.  If it doesn't work out
 	  of the box, you may have to change some settings in
 	  <file:drivers/scsi/53c7,8xx.h>.  Please read
-	  <file:drivers/scsi/README.ncr53c7xx> for the available boot time
+	  <file:Documentation/scsi/ncr53c7xx.txt> for the available boot time
 	  command line options.
 
 	  Note: there is another driver for the 53c8xx family of controllers
@@ -1048,7 +1048,7 @@
 	  only one may be active at a time.  If you have a 53c8xx board, you
 	  probably do not want to use the "NCR53c7,8xx SCSI support".
 
-	  Please read <file:drivers/scsi/README.ncr53c8xx> for more
+	  Please read <file:Documentation/scsi/ncr53c8xx.txt> for more
 	  information.
 
 config SCSI_SYM53C8XX
@@ -1075,7 +1075,7 @@
 	  SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them.
 	  The 'excl' option is also supported by the NCR53C8XX driver.
 
-	  Please read <file:drivers/scsi/README.ncr53c8xx> for more
+	  Please read <file:Documentation/scsi/ncr53c8xx.txt> for more
 	  information.
 
 config SCSI_NCR53C8XX_DEFAULT_TAGS
@@ -1301,7 +1301,7 @@
 	  SCSI support"), below.
 
 	  Information about this driver is contained in
-	  <file:drivers/scsi/README.qlogicfas>.  You should also read the
+	  <file:Documentation/scsi/qlogicfas.txt>.  You should also read the
 	  SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>.
 
@@ -1321,7 +1321,7 @@
 	  If you say Y here, make sure to choose "BIOS" at the question "PCI
 	  access mode".
 
-	  Please read the file <file:drivers/scsi/README.qlogicisp>.  You
+	  Please read the file <file:Documentation/scsi/qlogicisp.txt>.  You
 	  should also read the SCSI-HOWTO, available from
 	  <http://www.linuxdoc.org/docs.html#howto>.
 
@@ -1422,7 +1422,7 @@
 	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
 	  PCscsi/PCnet (Am53/79C974) solutions.
 
-	  Documentation can be found in <file:drivers/scsi/README.tmscsim>.
+	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
 
 	  Note that this driver does NOT support Tekram DC390W/U/F, which are
 	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
@@ -1442,7 +1442,7 @@
 	  EEPROM to get initial values for its settings, such as speed,
 	  termination, etc.  If it can't find this EEPROM, it will use
 	  defaults or the user supplied boot/module parameters.  For details
-	  on driver configuration see <file:drivers/scsi/README.tmscsim>.
+	  on driver configuration see <file:Documentation/scsi/tmscsim.txt>.
 
 	  If you say Y here and if no EEPROM is found, the driver gives up and
 	  thus only supports Tekram DC390(T) adapters.  This can be useful if
diff -Nru a/drivers/scsi/LICENSE.FlashPoint b/drivers/scsi/LICENSE.FlashPoint
--- a/drivers/scsi/LICENSE.FlashPoint	Sun Nov 17 20:30:16 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,60 +0,0 @@
-                     FlashPoint Driver Developer's Kit
-                                Version 1.0
-
-                   Copyright 1995-1996 by Mylex Corporation
-                            All Rights Reserved
-
-This program is free software; you may redistribute and/or modify it under
-the terms of either:
-
-    a) the GNU General Public License as published by the Free Software
-    Foundation; either version 2, or (at your option) any later version,
-
-    or
-
-    b) the "BSD-style License" included below.
-
-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 either the GNU General Public
-License or the BSD-style License below for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-675 Mass Ave, Cambridge, MA 02139, USA.
-
-The BSD-style License is as follows:
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-1. Redistributions of source code must retain this LICENSE.FlashPoint
-   file, without modification, this list of conditions, and the following
-   disclaimer.  The following copyright notice must appear immediately at
-   the beginning of all source files:
-
-        Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
-
-        This file is available under both the GNU General Public License
-        and a BSD-style copyright; see LICENSE.FlashPoint for details.
-
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-3. The name of Mylex Corporation may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY MYLEX CORP. ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/Makefile	Sun Nov 17 20:30:15 2002
@@ -18,7 +18,7 @@
 CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS
 CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
 
-export-objs	:= scsi_syms.o 53c700.o
+export-objs	:= scsi_syms.o scsi_proc.o 53c700.o
 
 subdir-$(CONFIG_PCMCIA)		+= pcmcia
 
@@ -123,8 +123,11 @@
 obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 
 scsi_mod-objs	:= scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
-			scsi_proc.o scsi_error.o scsi_lib.o scsi_scan.o \
-			scsi_syms.o
+		   scsi_error.o scsi_lib.o scsi_scan.o scsi_syms.o
+
+ifdef CONFIG_PROC_FS
+scsi_mod-objs	+= scsi_proc.o
+endif
 			
 sd_mod-objs	:= sd.o
 sr_mod-objs	:= sr.o sr_ioctl.o sr_vendor.o
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/NCR53C9x.c	Sun Nov 17 20:30:12 2002
@@ -732,9 +732,6 @@
 	/* Reset the thing before we try anything... */
 	esp_bootup_reset(esp, eregs);
 
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif
 	esps_in_use++;
 }
 
@@ -3638,7 +3635,6 @@
 void cleanup_module(void) {}
 void esp_release(void)
 {
-	MOD_DEC_USE_COUNT;
 	esps_in_use--;
 	esps_running = esps_in_use;
 }
diff -Nru a/drivers/scsi/README.53c700 b/drivers/scsi/README.53c700
--- a/drivers/scsi/README.53c700	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,154 +0,0 @@
-General Description
-===================
-
-This driver supports the 53c700 and 53c700-66 chips.  It also supports
-the 53c710 but only in 53c700 emulation mode.  It is full featured and
-does sync (-66 and 710 only), disconnects and tag command queueing.
-
-Since the 53c700 must be interfaced to a bus, you need to wrapper the
-card detector around this driver.  For an example, see the
-NCR_D700.[ch] or lasi700.[ch] files.
-
-The comments in the 53c700.[ch] files tell you which parts you need to
-fill in to get the driver working.
-
-
-Compile Time Flags
-==================
-
-The driver may be either io mapped or memory mapped.  This is
-selectable by configuration flags:
-
-CONFIG_53C700_MEM_MAPPED
-
-define if the driver is memory mapped.
-
-CONFIG_53C700_IO_MAPPED
-
-define if the driver is to be io mapped.
-
-One or other of the above flags *must* be defined.
-
-Other flags are:
-
-CONFIG_53C700_LE_ON_BE
-
-define if the chipset must be supported in little endian mode on a big
-endian architecture (used for the 700 on parisc).
-
-CONFIG_53C700_USE_CONSISTENT
-
-allocate consistent memory (should only be used if your architecture
-has a mixture of consistent and inconsistent memory).  Fully
-consistent or fully inconsistent architectures should not define this.
-
-
-Using the Chip Core Driver
-==========================
-
-In order to plumb the 53c700 chip core driver into a working SCSI
-driver, you need to know three things about the way the chip is wired
-into your system (or expansion card).
-
-1. The clock speed of the SCSI core
-2. The interrupt line used
-3. The memory (or io space) location of the 53c700 registers.
-
-Optionally, you may also need to know other things, like how to read
-the SCSI Id from the card bios or whether the chip is wired for
-differential operation.
-
-Usually you can find items 2. and 3. from general spec. documents or
-even by examining the configuration of a working driver under another
-operating system.
-
-The clock speed is usually buried deep in the technical literature.
-It is required because it is used to set up both the synchronous and
-asynchronous dividers for the chip.  As a general rule of thumb,
-manufacturers set the clock speed at the lowest possible setting
-consistent with the best operation of the chip (although some choose
-to drive it off the CPU or bus clock rather than going to the expense
-of an extra clock chip).  The best operation clock speeds are:
-
-53c700 - 25MHz
-53c700-66 - 50MHz
-53c710 - 40Mhz
-
-Writing Your Glue Driver
-========================
-
-This will be a standard SCSI driver (I don't know of a good document
-describing this, just copy from some other driver) with at least a
-detect and release entry.
-
-In the detect routine, you need to allocate a struct
-NCR_700_Host_Parameters sized memory area and clear it (so that the
-default values for everything are 0).  Then you must fill in the
-parameters that matter to you (see below), plumb the NCR_700_intr
-routine into the interrupt line and call NCR_700_detect with the host
-template and the new parameters as arguments.  You should also call
-the relevant request_*_region function and place the register base
-address into the `base' pointer of the host parameters.
-
-In the release routine, you must free the NCR_700_Host_Parameters that
-you allocated, call the corresponding release_*_region and free the
-interrupt.
-
-Handling Interrupts
--------------------
-
-In general, you should just plumb the card's interrupt line in with 
-
-request_irq(irq, NCR_700_intr, <irq flags>, <driver name>, host);
-
-where host is the return from the relevant NCR_700_detect() routine.
-
-You may also write your own interrupt handling routine which calls
-NCR_700_intr() directly.  However, you should only really do this if
-you have a card with more than one chip on it and you can read a
-register to tell which set of chips wants the interrupt.
-
-Settable NCR_700_Host_Parameters
---------------------------------
-
-The following are a list of the user settable parameters:
-
-clock: (MANDATORY)
-
-Set to the clock speed of the chip in MHz.
-
-base: (MANDATORY)
-
-set to the base of the io or mem region for the register set. On 64
-bit architectures this is only 32 bits wide, so the registers must be
-mapped into the low 32 bits of memory.
-
-pci_dev: (OPTIONAL)
-
-set to the PCI board device.  Leave NULL for a non-pci board.  This is
-used for the pci_alloc_consistent() and pci_map_*() functions.
-
-dmode_extra: (OPTIONAL, 53c710 only)
-
-extra flags for the DMODE register.  These are used to control bus
-output pins on the 710.  The settings should be a combination of
-DMODE_FC1 and DMODE_FC2.  What these pins actually do is entirely up
-to the board designer.  Usually it is safe to ignore this setting.
-
-differential: (OPTIONAL)
-
-set to 1 if the chip drives a differential bus.
-
-force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set)
-
-set to 1 if the chip is operating in little endian mode on a big
-endian architecture.
-
-chip710: (OPTIONAL)
-
-set to 1 if the chip is a 53c710.
-
-burst_disable: (OPTIONAL, 53c710 only)
-
-disable 8 byte bursting for DMA transfers.
-
diff -Nru a/drivers/scsi/README.AM53C974 b/drivers/scsi/README.AM53C974
--- a/drivers/scsi/README.AM53C974	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,246 +0,0 @@
-SUBJECT
--------
-AM53/79C974 PC-SCSI Driver
-
-
-DISCLAIMER
-----------
-***  THIS SHOULD BE CONSIDERED AS BETA SOFTWARE  ***
-***  USE AT YOUR OWN RISK!                       ***
-
-
-Copyright
----------
-The architecture and much of the code of this device driver was 
-originally developed by Drew Eckhardt for the NCR5380. The 
-following copyrights apply:
-
-For the architecture and all pieces of code which can also be found 
-in the NCR5380 device driver:
-Copyright 1993, Drew Eckhardt
-  Visionary Computing 
-  (Unix and Linux consulting and custom programming)
-  drew@colorado.edu
-  +1 (303) 666-5836
- 
-The AM53C974_nobios_detect code was originally developed by
-Robin Cutshaw (robin@xfree86.org) and is used here in a 
-slightly modified form.
- 
-For the remaining code:
-  Copyright 1994, D. Frieauff
-  EMail: fri@rsx42sun0.dofn.de
-  Phone: x49-7545-8-2256 , x49-7541-42305
-
-
-Version
--------
-AM53/79C974 (PC-SCSI) Linux driver ALPHA release 0.5, 19 November 1995
-
-
-Changelog
----------
-0.1 -> 0.2: 
-  - Extended message handling re-written to eliminate 'invalid message 17' bug
-  - Parameters of AM53C974_intr adapted
-  - Debug messages structured
-  - Spelling improved
-0.2 -> 0.3:
-  - README file updated -- please read this file up to the end!
-  - Automatic scanning of io_port and irq implemented; no need for BIOS32 
-    anymore
-  - Improved configuration (now via LILO parameter string)
-  - Cleanup of probing and initialization code
-  - Improved sync. negotiation (can be setup individually for every device)
-  - Improved/ debugged code for reception of ext. messages
-0.3 -> 0.4:
-  - Improved PCI probing and initialization code
-  - Compatibility changes for Linux 1.3.x
-0.4 -> 0.5:
-  - Compatibility changes for Linux 1.3.42
-
-
-Bugs & Todo
------------
- - Add proc info function
- - Support SCSI-2 tagged queuing
- - Finalize abort code 
-
-
-Features
---------
-This driver supports asynchronous and synchronous SCSI-I and SCSI-II
-devices.  It is capable of transfer rate and synchronous negotiation
-(see below).  The driver supports scatter-gather.  Transfers are DMA
-based, but do not (yet) make use of the AM53/79C974 MDL mode.
-Max. transfer rate is 10MHz (whatever this is in real life).  The
-transfer rate is negotiated with each device (see dmesg output).  The
-AM53/79C974 has a 96-byte DMA FIFO to the PCI bus and a 16-byte SCSI
-FIFO.  It provides active negation and glitch suppression functions.
-Burst DMA transfer rate is 132 MBytes/sec.
-
-
-Configuration
--------------
-
-The following communication characteristics can be set individually
-for every SCSI device on the bus:
-
-  - enable/disable sync. negotiation
-  - transfer rate
-  - asynchronous or synchronous communication
-  - in case of sync. communication, the sync. offset
-
-The sync. offset specifies the number of bytes that can be sent or 
-received from the SCSI bus without ACK resp. REQ signal.
-CAUTION: USING SYNCHRONOUS MODE ON LONG SCSI CABLES MAY CAUSE 
-         COMMUNICATION PROBLEMS LEADING TO LOSS OF DATA. 
-
-The default setting of the SCSI communication parameters is as follows:
-  - no negotiation
-  - 5.0 MHz transfer rate
-  - asynchronous mode
-  - zero offset
-
-The parameters can be modified by passing a string with the following
-syntax to the kernel:
-
-	AM53C974=host-scsi-id,target-scsi-id,max-rate,max-offset
-
-The parameters will be used by the driver as negotiation basis.  The
-range of the rate parameter is 3 to 10 MHz.  The range of the
-sync. offset parameter is 0 to 15 bytes. A value of 0 denotes
-asynchronous comm. mode.  If the target cannot cope with the specified
-transfer rate, sync. mode or sync.  offset, the negotiation result
-will differ from the specified values.  The negotiation result is
-printed out at the end of the negotiation process (to read it, use the
-dmesg program or the appropriate syslog).  The parameter strings
-(blank separated) can be passed to the kernel at the LILO prompt, or
-as part of the LILO configuration file.
-
-For example, the string "AM53C974=7,2,8,15" would be interpreted as
-follows:
-
-For communication between the controller with SCSI-ID 7 and the
-device with SCSI-ID 2 a transfer rate of 8MHz in synchronous mode with
-max. 15 bytes offset should be negotiated.
-
-As an example, here my LILO configuration file:
-  boot = /dev/sda
-  compact
-  #prompt
-  delay = 50	# optional, for systems that boot very quickly
-  vga = normal	# force sane state
-  ramdisk = 0	# paranoia setting
-  root = current  # use "current" root
-  image = /usr/src/linux/arch/i386/boot/zImage
-    label = linux
-    append = "AM53C974=7,0,10,0 AM53C974=7,1,10,0 AM53C974=7,2,10,15 AM53C974=7,4,10,0 AM53C974=7,5,10,0"
-    read-only
-  other = /dev/sda4
-    label = os2
-  other = /dev/sdb3
-    loader = /boot/any_d.b
-    table = /dev/sdb
-    label = setup
-
-The same parameters at the LILO prompt:
-
-  LILO boot: linux AM53C974=7,0,10,0 AM53C974=7,1,10,0 AM53C974=7,2,10,15 AM53C974=7,4,10,0 AM53C974=7,5,10,0
-
-You can override parameters specified in the LILO configuration file
-by parameters specified on the LILO command line.
-
-
-BIOS usage
-----------
-Version 0.4 of the driver will use the BIOS, if available. Otherwise
-it will try its internal PCI scan and access routines.  The driver
-assumes that the controller's SCSI-ID (usually 7) has been correctly
-loaded by the BIOS into the controller's register during system
-boot. If the driver detects that the controller's SCSI ID is not '7'
-it will print out a warning. If this happens to you please correct
-setting of the controller's SCSI-ID. If it is wrong, then edit the
-AM53C974_SCSI_ID definition in file AM53C974.h accordingly.
-
-
-Test environment
-----------------
-This driver was tested on a Compaq XL566 with the following SCSI configuration:
-2 x HP C2247 fixed disk (internal, rate=10MHz, async.)
-1 x Micropolis 1624 fixed disk (external, rate=8MHz, sync., offset=15 bytes)
-1 x Wangtek W5525ES cartridge streamer (internal, rate=5MHz, async.)
-1 x Toshiba XM-3301B CD-ROM (external, rate=5MHz, async.)
-
-
-Known problems
---------------
- - Compaq/Matsushita CD-ROM:
-   Use of this device with AM53C974 driver version 0.2 caused the kernel to
-   hang during Linux boot. If you encounter the problem, don't enable sync.
-   negotiation with the CD-ROM, i.e. simply don't specify comm. parameters 
-   for this device on the LILO command line or configuration file. 
-   The driver will thus use its default for the CD-ROM, which is 5MHz 
-   transfer rate async and no sync. negotiation.
- - Some disks cause problems.
-
-
-What to do if there is a SCSI problem possibly related to the driver
---------------------------------------------------------------------
-
-Read Klaus Liedl's WWW page (http://www-c724.uibk.ac.at/XL/).  In case
-this does not help: Send me a complete description of the problem,
-including your SCSI configuration plus as much debugging information
-as possible.  Don't wait until I ask you for this information. To
-enable the generation of debugging output, remove the comments from
-the following definitions in the AM53C974.h file:
-
-    AM53C974_DEBUG
-    AM53C974_DEBUG_MSG
-    AM53C974_DEBUG_KEYWAIT
-    AM53C974_DEBUG_INFO
-    AM53C974_DEBUG_INTR
-
-With these definitions enabled, the driver will enter single-step mode
-during Linux boot. Use the spacebar for stepping.  Take note of at
-least the last 10 printout sections (marked by dashes) before the
-crash/hangup or whatever happens and send me all of this information
-via email. If the system can boot, use the syslogd daemon to record
-the debugging output. Maybe you can use the ramdisk for this purpose
-too (if necessary, kindly ask K. Liedl (Klaus.Liedl@uibk.ac.at) for
-support, he knows how to do it -- I never tried). Stay in email
-contact with me. Be aware that the following weeks/months could be the
-worst of your life.  Note: If single-stepping takes up too much time,
-you can try to let the driver catch the problem by pressing the 'r'
-key. The driver will automatically enter single-step mode if it has
-detected something weird.
-
-
-Author's Contact Address
------------------------
-Email: fri@rsx42sun0.dofn.de
-Phone: x49-7545-2256 (office), x49-7541-42305 (home)
-Home address: D. Frieauff, Stockerholzstr. 27, 88048 Friedrichshafen, Germany
-
-
-!!!! Important Notice !!!!
------------------------------
-- Klaus Liedl maintains an excellent WWW page about Linux on Compaq XL.
-  It includes an FAQ, lots of tips & tricks as well as downloadable 
-  boot disk images. The URL is: http://www-c724.uibk.ac.at/XL/
-- Volunteer wanted for further maintenance of this driver software. I
-  don't have the time anymore to do serious support as some of you will know.
-
-
-Literature
-----------
- - AMD AM53C974 PC-SCSI Technical Manual, publication #18624B
- - Amendment to the AMD AM53C974 PC-SCSI Technical Manual
- - AMD AM79C974 PC-NET Datasheet, publication #18681
- - Amendment to the AMD AM79C974 PC-NET Datasheet
-
-
-THANKS to
----------
- - Drew Eckhardt, Robin Cutshaw, K. Liedl, Robert J. Pappas, A. Grenier, 
-   Mark Stockton, David C. Niemi, Ben Craft, and many others who have helped
diff -Nru a/drivers/scsi/README.BusLogic b/drivers/scsi/README.BusLogic
--- a/drivers/scsi/README.BusLogic	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,613 +0,0 @@
-	   BusLogic MultiMaster and FlashPoint SCSI Driver for Linux
-
-			 Version 2.0.15 for Linux 2.0
-			 Version 2.1.15 for Linux 2.1
-
-			      PRODUCTION RELEASE
-
-				17 August 1998
-
-			       Leonard N. Zubkoff
-			       Dandelion Digital
-			       lnz@dandelion.com
-
-	 Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
-
-
-				 INTRODUCTION
-
-BusLogic, Inc. designed and manufactured a variety of high performance SCSI
-host adapters which share a common programming interface across a diverse
-collection of bus architectures by virtue of their MultiMaster ASIC technology.
-BusLogic was acquired by Mylex Corporation in February 1996, but the products
-supported by this driver originated under the BusLogic name and so that name is
-retained in the source code and documentation.
-
-This driver supports all present BusLogic MultiMaster Host Adapters, and should
-support any future MultiMaster designs with little or no modification.  More
-recently, BusLogic introduced the FlashPoint Host Adapters, which are less
-costly and rely on the host CPU, rather than including an onboard processor.
-Despite not having an onboard CPU, the FlashPoint Host Adapters perform very
-well and have very low command latency.  BusLogic has recently provided me with
-the FlashPoint Driver Developer's Kit, which comprises documentation and freely
-redistributable source code for the FlashPoint SCCB Manager.  The SCCB Manager
-is the library of code that runs on the host CPU and performs functions
-analogous to the firmware on the MultiMaster Host Adapters.  Thanks to their
-having provided the SCCB Manager, this driver now supports the FlashPoint Host
-Adapters as well.
-
-My primary goals in writing this completely new BusLogic driver for Linux are
-to achieve the full performance that BusLogic SCSI Host Adapters and modern
-SCSI peripherals are capable of, and to provide a highly robust driver that can
-be depended upon for high performance mission critical applications.  All of
-the major performance and error recovery features can be configured from the
-Linux kernel command line or at module initialization time, allowing individual
-installations to tune driver performance and error recovery to their particular
-needs.
-
-The latest information on Linux support for BusLogic SCSI Host Adapters, as
-well as the most recent release of this driver and the latest firmware for the
-BT-948/958/958D, will always be available from my Linux Home Page at URL
-"http://www.dandelion.com/Linux/".
-
-Bug reports should be sent via electronic mail to "lnz@dandelion.com".  Please
-include with the bug report the complete configuration messages reported by the
-driver and SCSI subsystem at startup, along with any subsequent system messages
-relevant to SCSI operations, and a detailed description of your system's
-hardware configuration.
-
-Mylex has been an excellent company to work with and I highly recommend their
-products to the Linux community.  In November 1995, I was offered the
-opportunity to become a beta test site for their latest MultiMaster product,
-the BT-948 PCI Ultra SCSI Host Adapter, and then again for the BT-958 PCI Wide
-Ultra SCSI Host Adapter in January 1996.  This was mutually beneficial since
-Mylex received a degree and kind of testing that their own testing group cannot
-readily achieve, and the Linux community has available high performance host
-adapters that have been well tested with Linux even before being brought to
-market.  This relationship has also given me the opportunity to interact
-directly with their technical staff, to understand more about the internal
-workings of their products, and in turn to educate them about the needs and
-potential of the Linux community.
-
-More recently, Mylex has reaffirmed the company's interest in supporting the
-Linux community, and I am now working on a Linux driver for the DAC960 PCI RAID
-Controllers.  Mylex's interest and support is greatly appreciated.
-
-Unlike some other vendors, if you contact Mylex Technical Support with a
-problem and are running Linux, they will not tell you that your use of their
-products is unsupported.  Their latest product marketing literature even states
-"Mylex SCSI host adapters are compatible with all major operating systems
-including: ... Linux ...".
-
-Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont, California
-94555, USA and can be reached at 510/796-6100 or on the World Wide Web at
-http://www.mylex.com.  Mylex HBA Technical Support can be reached by electronic
-mail at techsup@mylex.com, by Voice at 510/608-2400, or by FAX at 510/745-7715.
-Contact information for offices in Europe and Japan is available on the Web
-site.
-
-
-				DRIVER FEATURES
-
-o Configuration Reporting and Testing
-
-  During system initialization, the driver reports extensively on the host
-  adapter hardware configuration, including the synchronous transfer parameters
-  requested and negotiated with each target device.  AutoSCSI settings for
-  Synchronous Negotiation, Wide Negotiation, and Disconnect/Reconnect are
-  reported for each target device, as well as the status of Tagged Queuing and
-  Error Recovery.  If the same setting is in effect for all target devices,
-  then a single word or phrase is used; otherwise, a letter is provided for
-  each target device to indicate the individual status.  The following examples
-  should clarify this reporting format:
-
-    Synchronous Negotiation: Ultra
-
-      Synchronous negotiation is enabled for all target devices and the host
-      adapter will attempt to negotiate for 20.0 mega-transfers/second.
-
-    Synchronous Negotiation: Fast
-
-      Synchronous negotiation is enabled for all target devices and the host
-      adapter will attempt to negotiate for 10.0 mega-transfers/second.
-
-    Synchronous Negotiation: Slow
-
-      Synchronous negotiation is enabled for all target devices and the host
-      adapter will attempt to negotiate for 5.0 mega-transfers/second.
-
-    Synchronous Negotiation: Disabled
-
-      Synchronous negotiation is disabled and all target devices are limited to
-      asynchronous operation.
-
-    Synchronous Negotiation: UFSNUUU#UUUUUUUU
-
-      Synchronous negotiation to Ultra speed is enabled for target devices 0
-      and 4 through 15, to Fast speed for target device 1, to Slow speed for
-      target device 2, and is not permitted to target device 3.  The host
-      adapter's SCSI ID is represented by the "#".
-
-    The status of Wide Negotiation, Disconnect/Reconnect, and Tagged Queuing
-    are reported as "Enabled", Disabled", or a sequence of "Y" and "N" letters.
-
-    The Error Recovery option is reported as "Default", "Hard Reset",
-    "Bus Device Reset", "None" or a sequence of "D", "H", "B", and "N" letters.
-
-o Performance Features
-
-  BusLogic SCSI Host Adapters directly implement SCSI-2 Tagged Queuing, and so
-  support has been included in the driver to utilize tagged queuing with any
-  target devices that report having the tagged queuing capability.  Tagged
-  queuing allows for multiple outstanding commands to be issued to each target
-  device or logical unit, and can improve I/O performance substantially.  In
-  addition, BusLogic's Strict Round Robin Mode is used to optimize host adapter
-  performance, and scatter/gather I/O can support as many segments as can be
-  effectively utilized by the Linux I/O subsystem.  Control over the use of
-  tagged queuing for each target device as well as individual selection of the
-  tagged queue depth is available through driver options provided on the kernel
-  command line or at module initialization time.  By default, the queue depth
-  is determined automatically based on the host adapter's total queue depth and
-  the number, type, speed, and capabilities of the target devices found.  In
-  addition, tagged queuing is automatically disabled whenever the host adapter
-  firmware version is known not to implement it correctly, or whenever a tagged
-  queue depth of 1 is selected.  Tagged queuing is also disabled for individual
-  target devices if disconnect/reconnect is disabled for that device.
-
-o Robustness Features
-
-  The driver implements extensive error recovery procedures.  When the higher
-  level parts of the SCSI subsystem request that a timed out command be reset,
-  a selection is made between a full host adapter hard reset and SCSI bus reset
-  versus sending a bus device reset message to the individual target device
-  based on the recommendation of the SCSI subsystem.  Error recovery strategies
-  are selectable through driver options individually for each target device,
-  and also include sending a bus device reset to the specific target device
-  associated with the command being reset, as well as suppressing error
-  recovery entirely to avoid perturbing an improperly functioning device.  If
-  the bus device reset error recovery strategy is selected and sending a bus
-  device reset does not restore correct operation, the next command that is
-  reset will force a full host adapter hard reset and SCSI bus reset.  SCSI bus
-  resets caused by other devices and detected by the host adapter are also
-  handled by issuing a soft reset to the host adapter and re-initialization.
-  Finally, if tagged queuing is active and more than one command reset occurs
-  in a 10 minute interval, or if a command reset occurs within the first 10
-  minutes of operation, then tagged queuing will be disabled for that target
-  device.  These error recovery options improve overall system robustness by
-  preventing individual errant devices from causing the system as a whole to
-  lock up or crash, and thereby allowing a clean shutdown and restart after the
-  offending component is removed.
-
-o PCI Configuration Support
-
-  On PCI systems running kernels compiled with PCI BIOS support enabled, this
-  driver will interrogate the PCI configuration space and use the I/O port
-  addresses assigned by the system BIOS, rather than the ISA compatible I/O
-  port addresses.  The ISA compatible I/O port address is then disabled by the
-  driver.  On PCI systems it is also recommended that the AutoSCSI utility be
-  used to disable the ISA compatible I/O port entirely as it is not necessary.
-  The ISA compatible I/O port is disabled by default on the BT-948/958/958D.
-
-o /proc File System Support
-
-  Copies of the host adapter configuration information together with updated
-  data transfer and error recovery statistics are available through the
-  /proc/scsi/BusLogic/<N> interface.
-
-o Shared Interrupts Support
-
-  On systems that support shared interrupts, any number of BusLogic Host
-  Adapters may share the same interrupt request channel.
-
-
-			    SUPPORTED HOST ADAPTERS
-
-The following list comprises the supported BusLogic SCSI Host Adapters as of
-the date of this document.  It is recommended that anyone purchasing a BusLogic
-Host Adapter not in the following table contact the author beforehand to verify
-that it is or will be supported.
-
-FlashPoint Series PCI Host Adapters:
-
-FlashPoint LT (BT-930)	Ultra SCSI-3
-FlashPoint LT (BT-930R)	Ultra SCSI-3 with RAIDPlus
-FlashPoint LT (BT-920)	Ultra SCSI-3 (BT-930 without BIOS)
-FlashPoint DL (BT-932)	Dual Channel Ultra SCSI-3
-FlashPoint DL (BT-932R)	Dual Channel Ultra SCSI-3 with RAIDPlus
-FlashPoint LW (BT-950)	Wide Ultra SCSI-3
-FlashPoint LW (BT-950R)	Wide Ultra SCSI-3 with RAIDPlus
-FlashPoint DW (BT-952)	Dual Channel Wide Ultra SCSI-3
-FlashPoint DW (BT-952R)	Dual Channel Wide Ultra SCSI-3 with RAIDPlus
-
-MultiMaster "W" Series Host Adapters:
-
-BT-948	    PCI		Ultra SCSI-3
-BT-958	    PCI		Wide Ultra SCSI-3
-BT-958D	    PCI		Wide Differential Ultra SCSI-3
-
-MultiMaster "C" Series Host Adapters:
-
-BT-946C	    PCI		Fast SCSI-2
-BT-956C	    PCI		Wide Fast SCSI-2
-BT-956CD    PCI		Wide Differential Fast SCSI-2
-BT-445C	    VLB		Fast SCSI-2
-BT-747C	    EISA	Fast SCSI-2
-BT-757C	    EISA	Wide Fast SCSI-2
-BT-757CD    EISA	Wide Differential Fast SCSI-2
-BT-545C	    ISA		Fast SCSI-2
-BT-540CF    ISA		Fast SCSI-2
-
-MultiMaster "S" Series Host Adapters:
-
-BT-445S	    VLB		Fast SCSI-2
-BT-747S	    EISA	Fast SCSI-2
-BT-747D	    EISA	Differential Fast SCSI-2
-BT-757S	    EISA	Wide Fast SCSI-2
-BT-757D	    EISA	Wide Differential Fast SCSI-2
-BT-545S	    ISA		Fast SCSI-2
-BT-542D	    ISA		Differential Fast SCSI-2
-BT-742A	    EISA	SCSI-2 (742A revision H)
-BT-542B	    ISA		SCSI-2 (542B revision H)
-
-MultiMaster "A" Series Host Adapters:
-
-BT-742A	    EISA	SCSI-2 (742A revisions A - G)
-BT-542B	    ISA		SCSI-2 (542B revisions A - G)
-
-AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also
-supported by this driver.
-
-BusLogic SCSI Host Adapters are available packaged both as bare boards and as
-retail kits.  The BT- model numbers above refer to the bare board packaging.
-The retail kit model numbers are found by replacing BT- with KT- in the above
-list.  The retail kit includes the bare board and manual as well as cabling and
-driver media and documentation that are not provided with bare boards.
-
-
-			 FLASHPOINT INSTALLATION NOTES
-
-o RAIDPlus Support
-
-  FlashPoint Host Adapters now include RAIDPlus, Mylex's bootable software
-  RAID.  RAIDPlus is not supported on Linux, and there are no plans to support
-  it.  The MD driver in Linux 2.0 provides for concatenation (LINEAR) and
-  striping (RAID-0), and support for mirroring (RAID-1), fixed parity (RAID-4),
-  and distributed parity (RAID-5) is available separately.  The built-in Linux
-  RAID support is generally more flexible and is expected to perform better
-  than RAIDPlus, so there is little impetus to include RAIDPlus support in the
-  BusLogic driver.
-
-o Enabling UltraSCSI Transfers
-
-  FlashPoint Host Adapters ship with their configuration set to "Factory
-  Default" settings that are conservative and do not allow for UltraSCSI speed
-  to be negotiated.  This results in fewer problems when these host adapters
-  are installed in systems with cabling or termination that is not sufficient
-  for UltraSCSI operation, or where existing SCSI devices do not properly
-  respond to synchronous transfer negotiation for UltraSCSI speed.  AutoSCSI
-  may be used to load "Optimum Performance" settings which allow UltraSCSI
-  speed to be negotiated with all devices, or UltraSCSI speed can be enabled on
-  an individual basis.  It is recommended that SCAM be manually disabled after
-  the "Optimum Performance" settings are loaded.
-
-
-		      BT-948/958/958D INSTALLATION NOTES
-
-The BT-948/958/958D PCI Ultra SCSI Host Adapters have some features which may
-require attention in some circumstances when installing Linux.
-
-o PCI I/O Port Assignments
-
-  When configured to factory default settings, the BT-948/958/958D will only
-  recognize the PCI I/O port assignments made by the motherboard's PCI BIOS.
-  The BT-948/958/958D will not respond to any of the ISA compatible I/O ports
-  that previous BusLogic SCSI Host Adapters respond to.  This driver supports
-  the PCI I/O port assignments, so this is the preferred configuration.
-  However, if the obsolete BusLogic driver must be used for any reason, such as
-  a Linux distribution that does not yet use this driver in its boot kernel,
-  BusLogic has provided an AutoSCSI configuration option to enable a legacy ISA
-  compatible I/O port.
-
-  To enable this backward compatibility option, invoke the AutoSCSI utility via
-  Ctrl-B at system startup and select "Adapter Configuration", "View/Modify
-  Configuration", and then change the "ISA Compatible Port" setting from
-  "Disable" to "Primary" or "Alternate".  Once this driver has been installed,
-  the "ISA Compatible Port" option should be set back to "Disable" to avoid
-  possible future I/O port conflicts.  The older BT-946C/956C/956CD also have
-  this configuration option, but the factory default setting is "Primary".
-
-o PCI Slot Scanning Order
-
-  In systems with multiple BusLogic PCI Host Adapters, the order in which the
-  PCI slots are scanned may appear reversed with the BT-948/958/958D as
-  compared to the BT-946C/956C/956CD.  For booting from a SCSI disk to work
-  correctly, it is necessary that the host adapter's BIOS and the kernel agree
-  on which disk is the boot device, which requires that they recognize the PCI
-  host adapters in the same order.  The motherboard's PCI BIOS provides a
-  standard way of enumerating the PCI host adapters, which is used by the Linux
-  kernel.  Some PCI BIOS implementations enumerate the PCI slots in order of
-  increasing bus number and device number, while others do so in the opposite
-  direction.
-
-  Unfortunately, Microsoft decided that Windows 95 would always enumerate the
-  PCI slots in order of increasing bus number and device number regardless of
-  the PCI BIOS enumeration, and requires that their scheme be supported by the
-  host adapter's BIOS to receive Windows 95 certification.  Therefore, the
-  factory default settings of the BT-948/958/958D enumerate the host adapters
-  by increasing bus number and device number.  To disable this feature, invoke
-  the AutoSCSI utility via Ctrl-B at system startup and select "Adapter
-  Configuration", "View/Modify Configuration", press Ctrl-F10, and then change
-  the "Use Bus And Device # For PCI Scanning Seq." option to OFF.
-
-  This driver will interrogate the setting of the PCI Scanning Sequence option
-  so as to recognize the host adapters in the same order as they are enumerated
-  by the host adapter's BIOS.
-
-o Enabling UltraSCSI Transfers
-
-  The BT-948/958/958D ship with their configuration set to "Factory Default"
-  settings that are conservative and do not allow for UltraSCSI speed to be
-  negotiated.  This results in fewer problems when these host adapters are
-  installed in systems with cabling or termination that is not sufficient for
-  UltraSCSI operation, or where existing SCSI devices do not properly respond
-  to synchronous transfer negotiation for UltraSCSI speed.  AutoSCSI may be
-  used to load "Optimum Performance" settings which allow UltraSCSI speed to be
-  negotiated with all devices, or UltraSCSI speed can be enabled on an
-  individual basis.  It is recommended that SCAM be manually disabled after the
-  "Optimum Performance" settings are loaded.
-
-
-				DRIVER OPTIONS
-
-BusLogic Driver Options may be specified either via the Linux Kernel Command
-Line or via the Loadable Kernel Module Installation Facility.  Driver Options
-for multiple host adapters may be specified either by separating the option
-strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
-command line.  Individual option specifications for a single host adapter are
-separated by commas.  The Probing and Debugging Options apply to all host
-adapters whereas the remaining options apply individually only to the
-selected host adapter.
-
-The BusLogic Driver Probing Options comprise the following:
-
-IO:<integer>
-
-  The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
-  MultiMaster Host Adapter.  If neither "IO:" nor "NoProbeISA" options are
-  specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
-  will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134).  Multiple
-  "IO:" options may be specified to precisely determine the I/O Addresses to
-  be probed, but the probe order will always follow the standard list.
-
-NoProbe
-
-  The "NoProbe" option disables all probing and therefore no BusLogic Host
-  Adapters will be detected.
-
-NoProbeISA
-
-  The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
-  Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
-  will be detected.
-
-NoProbePCI
-
-  The "NoProbePCI" options disables the interrogation of PCI Configuration
-  Space and therefore only ISA Multimaster Host Adapters will be detected, as
-  well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
-  Port set to "Primary" or "Alternate".
-
-NoSortPCI
-
-  The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
-  enumerated in the order provided by the PCI BIOS, ignoring any setting of
-  the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
-
-MultiMasterFirst
-
-  The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
-  before FlashPoint Host Adapters.  By default, if both FlashPoint and PCI
-  MultiMaster Host Adapters are present, this driver will probe for
-  FlashPoint Host Adapters first unless the BIOS primary disk is controlled
-  by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
-  Adapters will be probed first.
-
-FlashPointFirst
-
-  The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
-  before MultiMaster Host Adapters.
-
-The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
-the Queue Depth and whether Tagged Queuing is permitted for each Target
-Device (assuming that the Target Device supports Tagged Queuing).  The Queue
-Depth is the number of SCSI Commands that are allowed to be concurrently
-presented for execution (either to the Host Adapter or Target Device).  Note
-that explicitly enabling Tagged Queuing may lead to problems; the option to
-enable or disable Tagged Queuing is provided primarily to allow disabling
-Tagged Queuing on Target Devices that do not implement it correctly.  The
-following options are available:
-
-QueueDepth:<integer>
-
-  The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
-  Target Devices that support Tagged Queuing, as well as the maximum Queue
-  Depth for devices that do not support Tagged Queuing.  If no Queue Depth
-  option is provided, the Queue Depth will be determined automatically based
-  on the Host Adapter's Total Queue Depth and the number, type, speed, and
-  capabilities of the detected Target Devices.  For Host Adapters that
-  require ISA Bounce Buffers, the Queue Depth is automatically set by default
-  to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
-  excessive preallocation of DMA Bounce Buffer memory.  Target Devices that
-  do not support Tagged Queuing always have their Queue Depth set to
-  BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
-  lower Queue Depth option is provided.  A Queue Depth of 1 automatically
-  disables Tagged Queuing.
-
-QueueDepth:[<integer>,<integer>...]
-
-  The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
-  individually for each Target Device.  If an <integer> is omitted, the
-  associated Target Device will have its Queue Depth selected automatically.
-
-TaggedQueuing:Default
-
-  The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
-  based on the firmware version of the BusLogic Host Adapter and based on
-  whether the Queue Depth allows queuing multiple commands.
-
-TaggedQueuing:Enable
-
-  The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
-  all Target Devices on this Host Adapter, overriding any limitation that
-  would otherwise be imposed based on the Host Adapter firmware version.
-
-TaggedQueuing:Disable
-
-  The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
-  for all Target Devices on this Host Adapter.
-
-TaggedQueuing:<Target-Spec>
-
-  The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
-  Tagged Queuing individually for each Target Device.  <Target-Spec> is a
-  sequence of "Y", "N", and "X" characters.  "Y" enables Tagged Queuing, "N"
-  disables Tagged Queuing, and "X" accepts the default based on the firmware
-  version.  The first character refers to Target Device 0, the second to
-  Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
-  does not cover all the Target Devices, unspecified characters are assumed
-  to be "X".
-
-The BusLogic Driver Error Recovery Option allows for explicitly specifying
-the Error Recovery action to be performed when BusLogic_ResetCommand is
-called due to a SCSI Command failing to complete successfully.  The following
-options are available:
-
-ErrorRecovery:Default
-
-  The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
-  Reset and Bus Device Reset options based on the recommendation of the SCSI
-  Subsystem.
-
-ErrorRecovery:HardReset
-
-  The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
-  Adapter Hard Reset which also causes a SCSI Bus Reset.
-
-ErrorRecovery:BusDeviceReset
-
-  The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
-  a Bus Device Reset message to the individual Target Device causing the
-  error.  If Error Recovery is again initiated for this Target Device and no
-  SCSI Command to this Target Device has completed successfully since the Bus
-  Device Reset message was sent, then a Hard Reset will be attempted.
-
-ErrorRecovery:None
-
-  The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
-  This option should only be selected if a SCSI Bus Reset or Bus Device Reset
-  will cause the Target Device or a critical operation to suffer a complete
-  and unrecoverable failure.
-
-ErrorRecovery:<Target-Spec>
-
-  The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
-  Error Recovery individually for each Target Device.  <Target-Spec> is a
-  sequence of "D", "H", "B", and "N" characters.  "D" selects Default, "H"
-  selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
-  The first character refers to Target Device 0, the second to Target Device
-  1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
-  cover all the possible Target Devices, unspecified characters are assumed
-  to be "D".
-
-The BusLogic Driver Miscellaneous Options comprise the following:
-
-BusSettleTime:<seconds>
-
-  The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
-  seconds.  The Bus Settle Time is the amount of time to wait between a Host
-  Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
-  Commands.  If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
-
-InhibitTargetInquiry
-
-  The "InhibitTargetInquiry" option inhibits the execution of an Inquire
-  Target Devices or Inquire Installed Devices command on MultiMaster Host
-  Adapters.  This may be necessary with some older Target Devices that do not
-  respond correctly when Logical Units above 0 are addressed.
-
-The BusLogic Driver Debugging Options comprise the following:
-
-TraceProbe
-
-  The "TraceProbe" option enables tracing of Host Adapter Probing.
-
-TraceHardwareReset
-
-  The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
-  Reset.
-
-TraceConfiguration
-
-  The "TraceConfiguration" option enables tracing of Host Adapter
-  Configuration.
-
-TraceErrors
-
-  The "TraceErrors" option enables tracing of SCSI Commands that return an
-  error from the Target Device.  The CDB and Sense Data will be printed for
-  each SCSI Command that fails.
-
-Debug
-
-  The "Debug" option enables all debugging options.
-
-The following examples demonstrate setting the Queue Depth for Target Devices
-1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
-Devices on the second host adapter to 31, and the Bus Settle Time on the
-second host adapter to 30 seconds.
-
-Linux Kernel Command Line:
-
-  linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
-
-LILO Linux Boot Loader (in /etc/lilo.conf):
-
-  append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
-
-INSMOD Loadable Kernel Module Installation Facility:
-
-  insmod BusLogic.o \
-      'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
-
-NOTE: Module Utilities 2.1.71 or later is required for correct parsing
-      of driver options containing commas.
-
-
-			      DRIVER INSTALLATION
-
-This distribution was prepared for Linux kernel version 2.0.35, but should be
-compatible with 2.0.4 or any later 2.0 series kernel.
-
-To install the new BusLogic SCSI driver, you may use the following commands,
-replacing "/usr/src" with wherever you keep your Linux kernel source tree:
-
-  cd /usr/src
-  tar -xvzf BusLogic-2.0.15.tar.gz
-  mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi
-  patch -p0 < BusLogic.patch (only for 2.0.33 and below)
-  cd linux
-  make config
-  make depend
-  make zImage
-
-Then install "arch/i386/boot/zImage" as your standard kernel, run lilo if
-appropriate, and reboot.
-
-
-		      BUSLOGIC ANNOUNCEMENTS MAILING LIST
-
-The BusLogic Announcements Mailing List provides a forum for informing Linux
-users of new driver releases and other announcements regarding Linux support
-for BusLogic SCSI Host Adapters.  To join the mailing list, send a message to
-"buslogic-announce-request@dandelion.com" with the line "subscribe" in the
-message body.
diff -Nru a/drivers/scsi/README.FlashPoint b/drivers/scsi/README.FlashPoint
--- a/drivers/scsi/README.FlashPoint	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,163 +0,0 @@
-The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux.
-The upgrade program described below has been officially terminated effective
-31 March 1997 since it is no longer needed.
-
-
-
-	  MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS
-	      BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS
-
-
-FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux
-operating system support to its BusLogic brand of FlashPoint Ultra SCSI
-host adapters.  All of BusLogic's other SCSI host adapters, including the
-MultiMaster line, currently support the Linux operating system.  Linux
-drivers and information will be available on October 15th at
-http://www.dandelion.com/Linux/.
-
-"Mylex is committed to supporting the Linux community," says Peter Shambora,
-vice president of marketing for Mylex.  "We have supported Linux driver
-development and provided technical support for our host adapters for several
-years, and are pleased to now make our FlashPoint products available to this
-user base."
-
-The Linux Operating System
-
-Linux is a freely-distributed implementation of UNIX for Intel x86, Sun
-SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC
-machines.  It supports a wide range of software, including the X Window
-System, Emacs, and TCP/IP networking.  Further information is available at
-http://www.linux.org and http://www.ssc.com/linux.
-
-FlashPoint Host Adapters
-
-The FlashPoint family of Ultra SCSI host adapters, designed for workstation
-and file server environments, are available in narrow, wide, dual channel,
-and dual channel wide versions.  These adapters feature SeqEngine
-automation technology, which minimizes SCSI command overhead and reduces
-the number of interrupts generated to the CPU.
-
-About Mylex
-
-Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading
-producer of RAID technology and network management products.  The company
-produces high performance disk array (RAID) controllers, and complementary
-computer products for network servers, mass storage systems, workstations
-and system boards.  Through its wide range of RAID controllers and its
-BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling
-intelligent I/O technologies that increase network management control,
-enhance CPU utilization, optimize I/O performance, and ensure data security
-and availability.  Products are sold globally through a network of OEMs,
-major distributors, VARs, and system integrators.  Mylex Corporation is
-headquartered at 34551 Ardenwood Blvd., Fremont, CA.
-
-				   ####
-
-Contact:
-
-Peter Shambora
-Vice President of Marketing
-Mylex Corp.
-510/796-6100
-peters@mylex.com
-
-			       ANNOUNCEMENT
-	       BusLogic FlashPoint LT/BT-948 Upgrade Program
-			      1 February 1996
-
-			  ADDITIONAL ANNOUNCEMENT
-	       BusLogic FlashPoint LW/BT-958 Upgrade Program
-			       14 June 1996
-
-Ever since its introduction last October, the BusLogic FlashPoint LT has
-been problematic for members of the Linux community, in that no Linux
-drivers have been available for this new Ultra SCSI product.  Despite it's
-officially being positioned as a desktop workstation product, and not being
-particularly well suited for a high performance multitasking operating
-system like Linux, the FlashPoint LT has been touted by computer system
-vendors as the latest thing, and has been sold even on many of their high
-end systems, to the exclusion of the older MultiMaster products.  This has
-caused grief for many people who inadvertently purchased a system expecting
-that all BusLogic SCSI Host Adapters were supported by Linux, only to
-discover that the FlashPoint was not supported and would not be for quite
-some time, if ever.
-
-After this problem was identified, BusLogic contacted its major OEM
-customers to make sure the BT-946C/956C MultiMaster cards would still be
-made available, and that Linux users who mistakenly ordered systems with
-the FlashPoint would be able to upgrade to the BT-946C.  While this helped
-many purchasers of new systems, it was only a partial solution to the
-overall problem of FlashPoint support for Linux users.  It did nothing to
-assist the people who initially purchased a FlashPoint for a supported
-operating system and then later decided to run Linux, or those who had
-ended up with a FlashPoint LT, believing it was supported, and were unable
-to return it.
-
-In the middle of December, I asked to meet with BusLogic's senior
-management to discuss the issues related to Linux and free software support
-for the FlashPoint.  Rumors of varying accuracy had been circulating
-publicly about BusLogic's attitude toward the Linux community, and I felt
-it was best that these issues be addressed directly.  I sent an email
-message after 11pm one evening, and the meeting took place the next
-afternoon.  Unfortunately, corporate wheels sometimes grind slowly,
-especially when a company is being acquired, and so it's taken until now
-before the details were completely determined and a public statement could
-be made.
-
-BusLogic is not prepared at this time to release the information necessary
-for third parties to write drivers for the FlashPoint.  The only existing
-FlashPoint drivers have been written directly by BusLogic Engineering, and
-there is no FlashPoint documentation sufficiently detailed to allow outside
-developers to write a driver without substantial assistance.  While there
-are people at BusLogic who would rather not release the details of the
-FlashPoint architecture at all, that debate has not yet been settled either
-way.  In any event, even if documentation were available today it would
-take quite a while for a usable driver to be written, especially since I'm
-not convinced that the effort required would be worthwhile.
-
-However, BusLogic does remain committed to providing a high performance
-SCSI solution for the Linux community, and does not want to see anyone left
-unable to run Linux because they have a Flashpoint LT.  Therefore, BusLogic
-has put in place a direct upgrade program to allow any Linux user worldwide
-to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra
-SCSI Host Adapter.  The BT-948 is the Ultra SCSI successor to the BT-946C
-and has all the best features of both the BT-946C and FlashPoint LT,
-including smart termination and a flash PROM for easy firmware updates, and
-is of course compatible with the present Linux driver.  The price for this
-upgrade has been set at US $45 plus shipping and handling, and the upgrade
-program will be administered through BusLogic Technical Support, which can
-be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408
-654-0760, or by FAX at +1 408 492-1542.
-
-As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade
-program has now been extended to encompass the FlashPoint LW Wide Ultra
-SCSI Host Adapter.  Any Linux user worldwide may trade in their FlashPoint
-LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter.  The
-price for this upgrade has been set at US $65 plus shipping and handling.
-
-I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of
-my BusLogic driver already included latent support for the BT-948/958.
-Additional cosmetic support for the Ultra SCSI MultiMaster cards was added
-subsequent releases.  As a result of this cooperative testing process,
-several firmware bugs were found and corrected.  My heavily loaded Linux
-test system provided an ideal environment for testing error recovery
-processes that are much more rarely exercised in production systems, but
-are crucial to overall system stability.  It was especially convenient
-being able to work directly with their firmware engineer in demonstrating
-the problems under control of the firmware debugging environment; things
-sure have come a long way since the last time I worked on firmware for an
-embedded system.  I am presently working on some performance testing and
-expect to have some data to report in the not too distant future.
-
-BusLogic asked me to send this announcement since a large percentage of the
-questions regarding support for the FlashPoint have either been sent to me
-directly via email, or have appeared in the Linux newsgroups in which I
-participate.  To summarize, BusLogic is offering Linux users an upgrade
-from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US
-$45 plus shipping and handling, or from the unsupported FlashPoint LW
-(BT-950) to the supported BT-958 for $65 plus shipping and handling.
-Contact BusLogic Technical Support at techsup@buslogic.com or +1 408
-654-0760 to take advantage of their offer.
-
-		Leonard N. Zubkoff
-		lnz@dandelion.com
diff -Nru a/drivers/scsi/README.Mylex b/drivers/scsi/README.Mylex
--- a/drivers/scsi/README.Mylex	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,5 +0,0 @@
-Please see the file README.BusLogic for information about Linux support for
-Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters.
-
-The Mylex DAC960 PCI RAID Controllers are now supported.  Please consult
-http://www.dandelion.com/Linux/ for further information on the DAC960 driver.
diff -Nru a/drivers/scsi/README.aha152x b/drivers/scsi/README.aha152x
--- a/drivers/scsi/README.aha152x	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,183 +0,0 @@
-$Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $
-Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x)
-
-Copyright 1993-1999 Jürgen Fischer <fischer@norbit.de>
-TC1550 patches by Luuk van Dijk (ldz@xs4all.nl)
-
-
-In Revision 2 the driver was modified a lot (especially the
-bottom-half handler complete()).
-
-The driver is much cleaner now, has support for the new
-error handling code in 2.3, produced less cpu load (much
-less polling loops), has slightly higher throughput (at
-least on my ancient test box; a i486/33Mhz/20MB).
-
-
-CONFIGURATION ARGUMENTS:
-
-IOPORT        base io address                           (0x340/0x140)
-IRQ           interrupt level                           (9-12; default 11)
-SCSI_ID       scsi id of controller                     (0-7; default 7)
-RECONNECT     allow targets to disconnect from the bus  (0/1; default 1 [on])
-PARITY        enable parity checking                    (0/1; default 1 [on])
-SYNCHRONOUS   enable synchronous transfers              (0/1; default 1 [on])
-DELAY:        bus reset delay                           (default 100)
-EXT_TRANS:    enable extended translation               (0/1: default 0 [off])
-              (see NOTES)
-
-COMPILE TIME CONFIGURATION (go into AHA152X in drivers/scsi/Makefile):
-
--DAUTOCONF
- use configuration the controller reports (AHA-152x only)
-
--DSKIP_BIOSTEST
- Don't test for BIOS signature (AHA-1510 or disabled BIOS)
-
--DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
- override for the first controller 
-
--DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
- override for the second controller
-
--DAHA152X_DEBUG
- enable debugging output
-
--DAHA152X_STAT
- enable some statistics
-
-
-LILO COMMAND LINE OPTIONS:
-
-aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY> [,<EXT_TRANS]]]]]]]
-
- The normal configuration can be overridden by specifying a command line.
- When you do this, the BIOS test is skipped. Entered values have to be
- valid (known).  Don't use values that aren't supported under normal
- operation.  If you think that you need other values: contact me.
- For two controllers use the aha152x statement twice.
-
-
-SYMBOLS FOR MODULE CONFIGURATION:
-
-Choose from 2 alternatives:
-
-1. specify everything (old)
-
-aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
-  configuration override for first controller
-
-
-aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
-  configuration override for second controller
-
-2. specify only what you need to (irq or io is required; new)
-
-io=IOPORT0[,IOPORT1]
-  IOPORT for first and second controller
-
-irq=IRQ0[,IRQ1]
-  IRQ for first and second controller
-
-scsiid=SCSIID0[,SCSIID1]
-  SCSIID for first and second controller
-
-reconnect=RECONNECT0[,RECONNECT1]
-  allow targets to disconnect for first and second controller
-
-parity=PAR0[PAR1]
-  use parity for first and second controller
-
-sync=SYNCHRONOUS0[,SYNCHRONOUS1]
-  enable synchronous transfers for first and second controller
-
-delay=DELAY0[,DELAY1]
-  reset DELAY for first and second controller
-
-exttrans=EXTTRANS0[,EXTTRANS1]
-  enable extended translation for first and second controller
-
-
-If you use both alternatives the first will be taken.
-
-
-NOTES ON EXT_TRANS: 
-
-SCSI uses block numbers to address blocks/sectors on a device.
-The BIOS uses a cylinder/head/sector addressing scheme (C/H/S)
-scheme instead.  DOS expects a BIOS or driver that understands this
-C/H/S addressing.
-
-The number of cylinders/heads/sectors is called geometry and is required
-as base for requests in C/H/S addressing.  SCSI only knows about the
-total capacity of disks in blocks (sectors).
-
-Therefore the SCSI BIOS/DOS driver has to calculate a logical/virtual
-geometry just to be able to support that addressing scheme.  The geometry
-returned by the SCSI BIOS is a pure calculation and has nothing to
-do with the real/physical geometry of the disk (which is usually
-irrelevant anyway).
-
-Basically this has no impact at all on Linux, because it also uses block
-instead of C/H/S addressing.  Unfortunately C/H/S addressing is also used
-in the partition table and therefore every operating system has to know
-the right geometry to be able to interpret it.
-
-Moreover there are certain limitations to the C/H/S addressing scheme,
-namely the address space is limited to upto 255 heads, upto 63 sectors
-and a maximum of 1023 cylinders.
-
-The AHA-1522 BIOS calculates the geometry by fixing the number of heads
-to 64, the number of sectors to 32 and by calculating the number of
-cylinders by dividing the capacity reported by the disk by 64*32 (1 MB).
-This is considered to be the default translation.
-
-With respect to the limit of 1023 cylinders using C/H/S you can only
-address the first GB of your disk in the partition table.  Therefore
-BIOSes of some newer controllers based on the AIC-6260/6360 support
-extended translation.  This means that the BIOS uses 255 for heads,
-63 for sectors and then divides the capacity of the disk by 255*63
-(about 8 MB), as soon it sees a disk greater than 1 GB.  That results
-in a maximum of about 8 GB addressable diskspace in the partition table
-(but there are already bigger disks out there today).
-
-To make it even more complicated the translation mode might/might
-not be configurable in certain BIOS setups.
-
-This driver does some more or less failsafe guessing to get the
-geometry right in most cases:
-
-- for disks<1GB: use default translation (C/32/64)
-
-- for disks>1GB:
-  - take current geometry from the partition table
-    (using scsicam_bios_param and accept only `valid' geometries,
-    ie. either (C/32/64) or (C/63/255)).  This can be extended translation
-    even if it's not enabled in the driver.
-
-  - if that fails, take extended translation if enabled by override,
-    kernel or module parameter, otherwise take default translation and
-    ask the user for verification.  This might on not yet partitioned
-    disks.
-
-
-REFERENCES USED:
-
- "AIC-6260 SCSI Chip Specification", Adaptec Corporation.
-
- "SCSI COMPUTER SYSTEM INTERFACE - 2 (SCSI-2)", X3T9.2/86-109 rev. 10h
-
- "Writing a SCSI device driver for Linux", Rik Faith (faith@cs.unc.edu)
-
- "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu)
-
- "Adaptec 1520/1522 User's Guide", Adaptec Corporation.
-
- Michael K. Johnson (johnsonm@sunsite.unc.edu)
-
- Drew Eckhardt (drew@cs.colorado.edu)
-
- Eric Youngdale (eric@andante.org) 
-
- special thanks to Eric Youngdale for the free(!) supplying the
- documentation on the chip.
diff -Nru a/drivers/scsi/README.aic7xxx b/drivers/scsi/README.aic7xxx
--- a/drivers/scsi/README.aic7xxx	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,477 +0,0 @@
-			    AIC7xxx Driver for Linux
-
-Introduction
-----------------------------
-The AIC7xxx SCSI driver adds support for Adaptec (http://www.adaptec.com)
-SCSI controllers and chipsets. Major portions of the driver and driver
-development are shared between both Linux and FreeBSD. Support for the
-AIC-7xxx chipsets have been in the default Linux kernel since approximately
-linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
-2.1.0 or later.
-
-  Supported cards/chipsets
-  ----------------------------
-    Adaptec Cards
-    ----------------------------
-    AHA-274x
-    AHA-274xT
-    AHA-274xW
-    AHA-284x
-    AHA-284xW
-    All PCI based cards using any of the chipsets listed under motherboard
-    chipsets.  In general, this means *all* of the Adaptec SCSI controllers
-    except the ones specifically excluded later on in this document.
-
-    Motherboard Chipsets
-    ----------------------------
-    AIC-777x
-    AIC-785x
-    AIC-786x
-    AIC-787x
-    AIC-788x
-    AIC-789x
-    AIC-3860
-
-    Bus Types
-    ----------------------------
-    W - Wide SCSI, SCSI-3, 16bit bus, 68pin connector, will also support
-        SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
-    U - Ultra SCSI, transfer rates up to 40MB/s.
-    U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
-    U3- Ultra 3 SCSI, transfer rates up to 160MB/s.
-    D - Differential SCSI.
-    T - Twin Channel SCSI. Up to 14 SCSI devices.
-
-    AHA-274x - EISA SCSI controller
-    AHA-284x - VLB SCSI controller
-    AHA-29xx - PCI SCSI controller
-    AHA-39xx - PCI controllers with multiple separate SCSI channels on-board.
-
-  Not Supported Devices
-  ------------------------------
-    Adaptec Cards
-    ----------------------------
-    AHA-2920 (Only the cards that use the Future Domain chipset are not
-              supported, any 2920 cards based on Adaptec AIC chipsets,
-	      such as the 2920C, are supported)
-    AAA-13x Raid Adapters
-    AAA-113x Raid Port Card
-
-    Motherboard Chipsets
-    ----------------------------
-    AIC-781x
-
-    Bus Types
-    ----------------------------
-    R - Raid Port busses are not supported.
-
-    The hardware RAID devices sold by Adaptec are *NOT* supported by this
-    driver (and will people please stop emailing me about them, they are
-    a totally separate beast from the bare SCSI controllers and this driver
-    can not be retrofitted in any sane manner to support the hardware RAID
-    features on those cards - Doug Ledford).
-    
-
-  People
-  ------------------------------
-    Justin T Gibbs  gibbs@plutotech.com
-      (BSD Driver Author)
-    Dan Eischen     deischen@iworks.InterWorks.org
-      (Original Linux Driver Co-maintainer)
-    Dean Gehnert    deang@teleport.com
-      (Original Linux FTP/patch maintainer)
-    Jess Johnson    jester@frenzy.com
-      (AIC7xxx FAQ author)
-    Doug Ledford    dledford@redhat.com
-      (Current Linux aic7xxx-5.x.x Driver/Patch/FTP maintainer)
-    
-    Special thanks go to John Aycock (aycock@cpsc.ucalgary.ca), the original
-    author of the driver. John has since retired from the project. Thanks
-    again for all his work!
-    
-  Mailing list
-  ------------------------------
-    There is a mailing list available for users who want to track development
-    and converse with other users and developers. This list is for both
-    FreeBSD and Linux support of the AIC7xxx chipsets.
-
-    To subscribe to the AIC7xxx mailing list send mail to the list server,
-    with "subscribe AIC7xxx" in the body (no Subject: required):
-        To: majordomo@FreeBSD.ORG
-        ---
-        subscribe AIC7xxx
-
-    To unsubscribe from the list, send mail to the list server with:
-        To: majordomo@FreeBSD.ORG
-        ---
-        unsubscribe AIC7xxx
-
-    Send regular messages and replies to: AIC7xxx@FreeBSD.ORG
-    
-  Boot Command line options
-  ------------------------------
-    "aic7xxx=no_reset" -  Eliminate the SCSI bus reset during startup.
-        Some SCSI devices need the initial reset that this option disables
-	in order to work.  If you have problems at bootup, please make sure
-	you aren't using this option.
-	
-    "aic7xxx=reverse_scan" - Certain PCI motherboards scan for devices at
-        bootup by scanning from the highest numbered PCI device to the
-	lowest numbered PCI device, others do just the opposite and scan
-	from lowest to highest numbered PCI device.  There is no reliable
-	way to autodetect this ordering.  So, we default to the most common
-	order, which is lowest to highest.  Then, in case your motherboard
-	scans from highest to lowest, we have this option.  If your BIOS
-	finds the drives on controller A before controller B but the linux
-	kernel finds your drives on controller B before A, then you should
-	use this option.
-	
-    "aic7xxx=extended" - Force the driver to detect extended drive translation
-        on your controller.  This helps those people who have cards without
-        a SEEPROM make sure that linux and all other operating systems think
-        the same way about your hard drives.
-
-    "aic7xxx=scbram" - Some cards have external SCB RAM that can be used to
-        give the card more hardware SCB slots.  This allows the driver to use
-	that SCB RAM.  Without this option, the driver won't touch the SCB
-	RAM because it is known to cause problems on a few cards out there
-	(such as 3985 class cards).
-	
-    "aic7xxx=irq_trigger:x" - Replace x with either 0 or 1 to force the kernel
-        to use the correct IRQ type for your card.  This only applies to EISA
-        based controllers.  On these controllers, 0 is for Edge triggered
-        interrupts, and 1 is for Level triggered interrupts.  If you aren't
-        sure or don't know which IRQ trigger type your EISA card uses, then
-        let the kernel autodetect the trigger type.
-	
-    "aic7xxx=verbose" - This option can be used in one of two ways.  If you
-        simply specify aic7xxx=verbose, then the kernel will automatically
-	pick the default set of verbose messages for you to see.
-	Alternatively, you can specify the command as 
-	"aic7xxx=verbose:0xXXXX" where the X entries are replaced with
-	hexadecimal digits.  This option is a bit field type option.  For
-	a full listing of the available options, search for the 
-	#define VERBOSE_xxxxxx lines in the aic7xxx.c file.  If you want
-	verbose messages, then it is recommended that you simply use the
-	aic7xxx=verbose variant of this command.
-	
-    "aic7xxx=pci_parity:x" - This option controls whether or not the driver
-        enables PCI parity error checking on the PCI bus.  By default, this
-        checking is disabled.  To enable the checks, simply specify pci_parity
-        with no value afterwords.  To reverse the parity from even to odd,
-        supply any number other than 0 or 255.  In short:
-          pci_parity     - Even parity checking (even is the normal PCI parity)
-          pci_parity:x   - Where x > 0, Odd parity checking
-          pci_parity:0   - No check (default)
-        NOTE: In order to get Even PCI parity checking, you must use the
-        version of the option that does not include the : and a number at
-        the end (unless you want to enter exactly 2^32 - 1 as the number).
-	
-    "aic7xxx=no_probe" - This option will disable the probing for any VLB
-        based 2842 controllers and any EISA based controllers.  This is
-	needed on certain newer motherboards where the normal EISA I/O ranges
-	have been claimed by other PCI devices.  Probing on those machines
-	will often result in the machine crashing or spontaneously rebooting
-	during startup.  Examples of machines that need this are the
-	Dell PowerEdge 6300 machines.
-
-    "aic7xxx=seltime:2" - This option controls how long the card waits
-        during a device selection sequence for the device to respond.
-	The original SCSI spec says that this "should be" 256ms.  This
-	is generally not required with modern devices.  However, some
-	very old SCSI I devices need the full 256ms.  Most modern devices
-	can run fine with only 64ms.  The default for this option is
-	64ms.  If you need to change this option, then use the following
-	table to set the proper value in the example above:
-	  0  -  256ms
-	  1  -  128ms
-	  2  -   64ms
-	  3  -   32ms
-	
-    "aic7xxx=panic_on_abort" - This option is for debugging and will cause
-        the driver to panic the linux kernel and freeze the system the first
-	time the drivers abort or reset routines are called.  This is most
-	helpful when some problem causes infinite reset loops that scroll too
-	fast to see.  By using this option, you can write down what the errors
-	actually are and send that information to me so it can be fixed.
-	
-    "aic7xxx=dump_card" - This option will print out the *entire* set of
-        configuration registers on the card during the init sequence.  This
-	is a debugging aid used to see exactly what state the card is in
-	when we finally finish our initialization routines.  If you don't
-	have documentation on the chipsets, this will do you absolutely
-	no good unless you are simply trying to write all the information
-	down in order to send it to me.
-	
-    "aic7xxx=dump_sequencer" - This is the same as the above options except
-        that instead of dumping the register contents on the card, this
-	option dumps the contents of the sequencer program RAM.  This gives
-	the ability to verify that the instructions downloaded to the
-	card's sequencer are indeed what they are suppossed to be.  Again,
-	unless you have documentation to tell you how to interpret these
-	numbers, then it is totally useless.
-	
-    "aic7xxx=override_term:0xffffffff" - This option is used to force the
-    	termination on your SCSI controllers to a particular setting.  This
-	is a bit mask variable that applies for up to 8 aic7xxx SCSI channels.
-	Each channel gets 4 bits, divided as follows:
-	bit   3   2   1   0
-	      |   |   |   Enable/Disable Single Ended Low Byte Termination
-	      |   |   En/Disable Single Ended High Byte Termination
-	      |   En/Disable Low Byte LVD Termination
-	      En/Disable High Byte LVD Termination
-
-	The upper 2 bits that deal with LVD termination only apply to Ultra2
-	controllers.  Futhermore, due to the current Ultra2 controller
-	designs, these bits are tied together such that setting either bit
-	enables both low and high byte LVD termination.  It is not possible
-	to only set high or low byte LVD termination in this manner.  This is
-	an artifact of the BIOS definition on Ultra2 controllers.  For other
-	controllers, the only important bits are the two lowest bits.  Setting
-	the higher bits on non-Ultra2 controllers has no effect.  A few
-	examples of how to use this option:
-
-	Enable low and high byte termination on a non-ultra2 controller that
-	is the first aic7xxx controller (the correct bits are 0011), 
-	aic7xxx=override_term:0x3
-
-	Enable all termination on the third aic7xxx controller, high byte
-	termination on the second aic7xxx controller, and low and high byte
-	SE termination on the first aic7xxx controller 
-	(bits are 1111 0010 0011), 
-	aic7xxx=override_term:0xf23
-	
-	No attempt has been made to make this option non-cryptic.  It really
-	shouldn't be used except in dire circumstances, and if that happens,
-	I'm probably going to be telling you what to set this to anyway :)
-
-    "aic7xxx=stpwlev:0xffffffff" - This option is used to control the STPWLEV
-        bit in the DEVCONFIG PCI register.  Currently, this is one of the
-	very few registers that we have absolutely *no* way of detecting
-	what the variable should be.  It depends entirely on how the chipset
-	and external terminators were coupled by the card/motherboard maker.
-	Further, a chip reset (at power up) always sets this bit to 0.  If
-	there is no BIOS to run on the chipset/card (such as with a 2910C
-	or a motherboard controller with the BIOS totally disabled) then
-	the variable may not get set properly.  Of course, if the proper
-	setting was 0, then that's what it would be after the reset, but if
-	the proper setting is actually 1.....you get the picture.  Now, since
-	we can't detect this at all, I've added this option to force the
-	setting.  If you have a BIOS on your controller then you should never
-	need to use this option.  However, if you are having lots of SCSI
-	reset problems and can't seem to get them knocked out, this may help.
-
-	Here's a test to know for certain if you need this option.  Make
-	a boot floppy that you can use to boot your computer up and that
-	will detect the aic7xxx controller.  Next, power down your computer.
-	While it's down, unplug all SCSI cables from your Adaptec SCSI
-	controller.  Boot the system back up to the Adaptec EZ-SCSI BIOS
-	and then make sure that termination is enabled on your adapter (if
-	you have an Adaptec BIOS of course).  Next, boot up the floppy you
-	made and wait for it to detect the aic7xxx controller.  If the kernel
-	finds the controller fine, says scsi : x hosts and then tries to
-	detect your devices like normal, up to the point where it fails to
-	mount your root file system and panics, then you're fine.  If, on
-	the other hand, the system goes into an infinite reset loop, then
-	you need to use this option and/or the previous option to force the
-	proper termination settings on your controller.   If this happens,
-	then you next need to figure out what your settings should be.
-
-	To find the correct settings, power your machine back down, connect
-	back up the SCSI cables, and boot back into your machine like normal.
-	However, boot with the aic7xxx=verbose:0x39 option.  Record the
-	initial DEVCONFIG values for each of your aic7xxx controllers as
-	they are listed, and also record what the machine is detecting as
-	the proper termination on your controllers.  NOTE: the order in
-	which the initial DEVCONFIG values are printed out is not gauranteed
-	to be the same order as the SCSI controllers are registered.  The
-	above option and this option both work on the order of the SCSI
-	controllers as they are registered, so make sure you match the right
-	DEVCONFIG values with the right controllers if you have more than
-	one aic7xxx controller.
-
-	Once you have the detected termination settings and the initial
-	DEVCONFIG values for each controller, then figure out what the
-	termination on each of the controllers *should* be.  Hopefully, that
-	part is correct, but it could possibly be wrong if there is
-	bogus cable detection logic on your controller or something similar.
-	If all the controllers have the correct termination settings, then
-	don't set the aic7xxx=override_term variable at all, leave it alone.
-	Next, on any controllers that go into an infinite reset loop when
-	you unplug all the SCSI cables, get the starting DEVCONFIG value.
-	If the initial DEVCONFIG value is divisible by 2, then the correct
-	setting for that controller is 0.  If it's an odd number, then
-	the correct setting for that controller is 1.  For any other
-	controllers that didn't have an infinite reset problem, then reverse
-	the above options.  If DEVCONFIG was even, then the correct setting
-	is 1, if not then the correct setting is 0.
-
-	Now that you know what the correct setting was for each controller,
-	we need to encode that into the aic7xxx=stpwlev:0x... variable.
-	This variable is a bit field encoded variable.  Bit 0 is for the first
-	aic7xxx controller, bit 1 for the next, etc.  Put all these bits
-	together and you get a number.  For example, if the third aic7xxx
-	needed a 1, but the second and first both needed a 0, then the bits
-	would be 100 in binary.  This then translates to 0x04.  You would
-	therefore set aic7xxx=stpwlev:0x04.  This is fairly standard binary
-	to hexadecimal conversions here.  If you aren't up to speed on the
-	binary->hex conversion then send an email to the aic7xxx mailing
-	list and someone can help you out.
-
-    "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
-        or enable Tagged Command Queueing (TCQ) on specific devices.  As of
-	driver version 5.1.11, TCQ is now either on or off by default
-	according to the setting you choose during the make config process.
-	In order to en/disable TCQ for certian devices at boot time, a user
-	may use this boot param.  The driver will then parse this message out
-        and en/disable the specific device entries that are present based upon
-        the value given.  The param line is parsed in the following manner:
-
-          { - first instance indicates the start of this parameter values
-              second instance is the start of entries for a particular
-              device entry
-          } - end the entries for a particular host adapter, or end the entire
-              set of parameter entries
-          , - move to next entry.  Inside of a set of device entries, this
-              moves us to the next device on the list.  Outside of device
-              entries, this moves us to the next host adapter
-          . - Same effect as , but is safe to use with insmod.
-          x - the number to enter into the array at this position.  
-              0 = Enable tagged queueing on this device and use the default
-                  queue depth
-              1-254 = Enable tagged queueing on this device and use this
-                      number as the queue depth
-              255 = Disable tagged queueing on this device.
-              Note: anything above 32 for an actual queue depth is wasteful
-                    and not recommended.
-
-        A few examples of how this can be used:
-
-        tag_info:{{8,12,,0,,255,4}}
-          This line will only effect the first aic7xxx card registered.  It
-          will set scsi id 0 to a queue depth of 8, id 1 to 12, leave id 2
-          at the default, set id 3 to tagged queueing enabled and use the
-          default queue depth, id 4 default, id 5 disabled, and id 6 to 4.
-          Any not specified entries stay at the default value, repeated
-          commas with no value specified will simply increment to the next id
-          without changing anything for the missing values.
-
-        tag_info:{,,,{,,,255}}
-          First, second, and third adapters at default values.  Fourth
-          adapter, id 3 is disabled.  Notice that leading commas simply
-	  increment what the first number effects, and there are no need
-	  for trailing commas.  When you close out an adapter, or the
-	  entire entry, anything not explicitly set stays at the default
-	  value.
-
-        A final note on this option.  The scanner I used for this isn't
-        perfect or highly robust.  If you mess the line up, the worst that
-        should happen is that the line will get ignored.  If you don't
-        close out the entire entry with the final bracket, then any other
-        aic7xxx options after this will get ignored.  So, in general, be
-        sure of what you are entering, and after you have it right, just
-        add it to the lilo.conf file so there won't be any mistakes.  As
-        a means of checking this parser, the entire tag_info array for
-        each card is now printed out in the /proc/scsi/aic7xxx/x file.  You
-        can use that to verify that your options were parsed correctly. 
-        
-    Boot command line options may be combined to form the proper set of options
-    a user might need.  For example, the following is valid:
-    
-    aic7xxx=verbose,extended,irq_trigger:1
-    
-    The only requirement is that individual options be separated by a comma or
-    a period on the command line.
-        
-  Module Loading command options
-  ------------------------------
-    When loading the aic7xxx driver as a module, the exact same options are
-    available to the user.  However, the syntax to specify the options changes
-    slightly.  For insmod, you need to wrap the aic7xxx= argument in quotes
-    and replace all ',' with '.'.  So, for example, a valid insmod line
-    would be:
-
-    insmod aic7xxx aic7xxx='verbose.irq_trigger:1.extended'
-
-    This line should result in the *exact* same behaviour as if you typed
-    it in at the lilo prompt and the driver was compiled into the kernel
-    instead of being a module.  The reason for the single quote is so that
-    the shell won't try to interpret anything in the line, such as {. 
-    Insmod assumes any options starting with a letter instead of a number
-    is a character string (which is what we want) and by switching all of
-    the commas to periods, insmod won't interpret this as more than one
-    string and write junk into our binary image.  I consider it a bug in
-    the insmod program that even if you wrap your string in quotes (quotes
-    that pass the shell mind you and that insmod sees) it still treates
-    a comma inside of those quotes as starting a new variable, resulting
-    in memory scribbles if you don't switch the commas to periods.
-
-
-  Kernel Compile options
-  ------------------------------
-    The various kernel compile time options for this driver are now fairly
-    well documented in the file Documentation/Configure.help.  In order to
-    see this documentation, you need to use one of the advanced configuration
-    programs (menuconfig and xconfig).  If you are using the "make menuconfig"
-    method of configuring your kernel, then you would simply highlight the
-    option in question and hit the ? key.  If you are using the "make xconfig"
-    method of configuring your kernel, then simply click on the help button
-    next to the option you have questions about.  The help information from
-    the Configure.help file will then get automatically displayed.
-
-  /proc support
-  ------------------------------
-    The /proc support for the AIC7xxx can be found in the /proc/scsi/aic7xxx/
-    directory. That directory contains a file for each SCSI controller in
-    the system. Each file presents the current configuration and transfer
-    statistics (enabled with #define in aic7xxx.c) for each controller.
-
-    Thanks to Michael Neuffer for his upper-level SCSI help, and
-    Matthew Jacob for statistics support.
-
-  Debugging the driver
-  ------------------------------
-    Should you have problems with this driver, and would like some help in
-    getting them solved, there are a couple debugging items built into
-    the driver to facilitate getting the needed information from the system.
-    In general, I need a complete description of the problem, with as many
-    logs as possible concerning what happens.  To help with this, there is
-    a command option aic7xxx=panic_on_abort.  This option, when set, forces
-    the driver to panic the kernel on the first SCSI abort issued by the
-    mid level SCSI code.  If your system is going to reset loops and you
-    can't read the screen, then this is what you need.  Not only will it
-    stop the system, but it also prints out a large amount of state
-    information in the process.  Second, if you specify the option
-    "aic7xxx=verbose:0x1ffff", the system will print out *SOOOO* much
-    information as it runs that you won't be able to see anything.
-    However, this can actually be very useful if your machine simply
-    locks up when trying to boot, since it will pin-point what was last
-    happening (in regards to the aic7xxx driver) immediately prior to
-    the lockup.  This is really only useful if your machine simply can
-    not boot up successfully.  If you can get your machine to run, then
-    this will produce far too much information.
-
-  FTP sites
-  ------------------------------
-    ftp://ftp.redhat.com/pub/aic/
-      - Out of date.  I used to keep stuff here, but too many people
-        complained about having a hard time getting into Red Hat's ftp
-	server.  So use the web site below instead.
-    ftp://ftp.pcnet.com/users/eischen/Linux/
-      - Dan Eischen's driver distribution area
-    ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
-      - European Linux mirror of Teleport site
-
-  Web sites
-  ------------------------------
-    http://people.redhat.com/dledford/
-      - My web site, also the primary aic7xxx site with several related
-        pages.
-
-Dean W. Gehnert
-deang@teleport.com
-
-$Revision: 3.0 $
-
-Modified by Doug Ledford 1998-2000
-
diff -Nru a/drivers/scsi/README.dpti b/drivers/scsi/README.dpti
--- a/drivers/scsi/README.dpti	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,83 +0,0 @@
- /* TERMS AND CONDITIONS OF USE
- * 
- * Redistribution and use in source form, with or without modification, are
- * permitted provided that redistributions of source code must retain the
- * above copyright notice, this list of conditions and the following disclaimer.
- * 
- * This software is provided `as is' by Adaptec and
- * any express or implied warranties, including, but not limited to, the
- * implied warranties of merchantability and fitness for a particular purpose,
- * are disclaimed. In no event shall Adaptec be
- * liable for any direct, indirect, incidental, special, exemplary or
- * consequential damages (including, but not limited to, procurement of
- * substitute goods or services; loss of use, data, or profits; or business
- * interruptions) however caused and on any theory of liability, whether in
- * contract, strict liability, or tort (including negligence or otherwise)
- * arising in any way out of the use of this driver software, even if advised
- * of the possibility of such damage.
- * 
- ****************************************************************
- * This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards.
- *
- * CREDITS:
- * The original linux driver was ported to Linux by Karen White while at 
- * Dell Computer.  It was ported from Bob Pasteur's (of DPT) original 
- * non-Linux driver.  Mark Salyzyn and Bob Pasteur consulted on the original
- * driver. 
- * 
- * 2.0 version of the driver by Deanna Bonds and Mark Salyzyn.
- *
- * HISTORY:
- * The driver was originally ported to linux version 2.0.34 
- *
- * V2.0 Rewrite of driver.  Re-architectured based on i2o subsystem.
- *   This was the first full GPL version since the last version used
- *   i2osig headers which were not GPL.  Developer Testing version.
- * V2.1 Internal testing
- * V2.2 First released version
- *
- * V2.3 
- *   Changes:
- *      Added Raptor Support
- *      Fixed bug causing system to hang under extreme load with 
- *         management utilities running (removed GFP_DMA from kmalloc flags)
- *
- *
- * V2.4 First version ready to be submitted to be embedded in the kernel
- *   Changes: 
- *      Implemented suggestions from Alan Cox
- *      Added calculation of resid for sg layer
- *      Better error handling
- *         Added checking underflow condtions 
- *         Added DATAPROTECT checking
- *         Changed error return codes
- *         Fixed pointer bug in bus reset routine
- *      Enabled hba reset from ioctls (allows a FW flash to reboot and use the new
- *         FW without having to reboot)
- *      Changed proc output
- *
- * TODO:
- *      Add 64 bit Scatter Gather when compiled on 64 bit architectures
- *      Add sparse lun scanning 
- *      Add code that checks if a device that had been taken offline is
- *         now online (at the FW level) when test unit ready or inquiry 
- *         command from scsi-core
- *      Add proc read interface
- *         busrescan command
- *         rescan command
- *      Add code to rescan routine that notifies scsi-core about new devices
- *      Add support for C-PCI (hotplug stuff)
- *      Add ioctl passthru error recovery
- *
- * NOTES:
- * The DPT card optimizes the order of processing commands.  Consequently,
- * a command may take up to 6 minutes to complete after it has been sent
- * to the board.  
- *
- * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the
- * interface files for Adaptecs managment routines.  These define the structures used
- * in the ioctls.  They are written to be portable.  They are hard to read, but I need
- * to use them 'as is' or I can miss changes in the interface.
- *
- */
-
diff -Nru a/drivers/scsi/README.dtc3x80 b/drivers/scsi/README.dtc3x80
--- a/drivers/scsi/README.dtc3x80	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,45 +0,0 @@
-README file for the Linux DTC3180/3280 scsi driver.
-by Ray Van Tassle (rayvt@comm.mot.com)  March 1996
-Based on the generic & core NCR5380 code by Drew Eckhard
-
-SCSI device driver for the DTC 3180/3280.
-Data Technology Corp---a division of Qume.
-
-The 3280 has a standard floppy interface.
-
-The 3180 does not.  Otherwise, they are identical.
-
-The DTC3x80 does not support DMA but it does have Pseudo-DMA which is
-supported by the driver.
-
-It's DTC406 scsi chip is supposedly compatible with the NCR 53C400.
-It is memory mapped, uses an IRQ, but no dma or io-port.  There is
-internal DMA, between SCSI bus and an on-chip 128-byte buffer.  Double
-buffering is done automagically by the chip.  Data is transferred
-between the on-chip buffer and CPU/RAM via memory moves.
-
-The driver detects the possible memory addresses (jumper selectable):
-	CC00, DC00, C800, and D800
-The possible IRQ's (jumper selectable) are:
-	IRQ 10, 11, 12, 15
-Parity is supported by the chip, but not by this driver.
-Information can be obtained from /proc/scsi/dtc3c80/N.
-
-Note on interrupts:
-
-The documentation says that it can be set to interrupt whenever the
-on-chip buffer needs CPU attention.  I couldn't get this to work.  So
-the driver polls for data-ready in the pseudo-DMA transfer routine.
-The interrupt support routines in the NCR3280.c core modules handle
-scsi disconnect/reconnect, and this (mostly) works.  However.....  I
-have tested it with 4 totally different hard drives (both SCSI-1 and
-SCSI-2), and one CDROM drive.  Interrupts works great for all but one
-specific hard drive.  For this one, the driver will eventually hang in
-the transfer state.  I have tested with: "dd bs=4k count=2k
-of=/dev/null if=/dev/sdb".  It reads ok for a while, then hangs.
-After beating my head against this for a couple of weeks, getting
-nowhere, I give up.  So.....This driver does NOT use interrupts, even
-if you have the card jumpered to an IRQ.  Probably nobody will ever
-care.
-
-
diff -Nru a/drivers/scsi/README.g_NCR5380 b/drivers/scsi/README.g_NCR5380
--- a/drivers/scsi/README.g_NCR5380	Sun Nov 17 20:30:13 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,63 +0,0 @@
-README file for the Linux g_NCR5380 driver.
-
-(c) 1993 Drew Eckhard
-NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin
-
-This file documents the NCR53c400 extensions by Kevin Lentin and some
-enhancements to the NCR5380 core.
-
-This driver supports both NCR5380 and NCR53c400 cards in port or memory
-mapped modes. Currently this driver can only support one of those mapping
-modes at a time but it does support both of these chips at the same time.
-The next release of this driver will support port & memory mapped cards at
-the same time. It should be able to handle multiple different cards in the
-same machine.
-
-The drivers/scsi/Makefile has an override in it for the most common
-NCR53c400 card, the Trantor T130B in its default configuration:
-	Port: 0x350
-	IRQ : 5
-
-The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
-supported by the driver.
-
-If the default configuration does not work for you, you can use the kernel
-command lines (eg using the lilo append command):
-	ncr5380=port,irq,dma
-	ncr53c400=port,irq
-or
-	ncr5380=base,irq,dma
-	ncr53c400=base,irq
-
-The driver does not probe for any addresses or ports other than those in
-the OVERRIDE or given to the kernel as above.
-
-This driver provides some information on what it has detected in
-/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot
-time. More info to come in the future.
-
-When NCR53c400 support is compiled in, BIOS parameters will be returned by
-the driver (the raw 5380 driver does not and I don't plan to fiddle with
-it!).
-
-This driver works as a module.
-When included as a module, parameters can be passed on the insmod/modprobe
-command line:
-  ncr_irq=xx   the interrupt
-  ncr_addr=xx  the port or base address (for port or memory
-               mapped, resp.)
-  ncr_dma=xx   the DMA
-  ncr_5380=1   to set up for a NCR5380 board
-  ncr_53c400=1 to set up for a NCR53C400 board
-e.g.
-modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
-  for a port mapped NCR5380 board or
-modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
-  for a memory mapped NCR53C400 board with interrupts disabled.
-
-(255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
-     IRQ line if overridden on the command line.)
-
-
-Kevin Lentin
-K.Lentin@cs.monash.edu.au
diff -Nru a/drivers/scsi/README.ibmmca b/drivers/scsi/README.ibmmca
--- a/drivers/scsi/README.ibmmca	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1402 +0,0 @@
-
-               -=< The IBM Microchannel SCSI-Subsystem >=-
-	       
-	                 for the IBM PS/2 series
-		 
-	  	   Low Level Software-Driver for Linux
-		 
-     Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU 
-  General Public License. Originally written by Martin Kolinek, December 1995.
-   Officially modified and maintained by Michael Lang since January 1999.
-	   
- 	                       Version 4.0a
-	
-   Last update: January 3, 2001
-   
-   Before you Start
-   ----------------
-   This is the common README.ibmmca file for all driver releases of the 
-   IBM MCA SCSI driver for Linux. Please note, that driver releases 4.0
-   or newer do not work with kernel versions older than 2.4.0, while driver
-   versions older than 4.0 do not work with kernels 2.4.0 or later! If you
-   try to compile your kernel with the wrong driver source, the 
-   compilation is aborted and you get a corresponding error message. This is
-   no bug in the driver. It prevents you from using the wrong sourcecode
-   with the wrong kernel version.
-
-   Authors of this Driver
-   ----------------------
-    - Chris Beauregard (improvement of the SCSI-device mapping by the driver)
-    - Martin Kolinek (origin, first release of this driver)
-    - Klaus Kudielka (multiple SCSI-host management/detection, adaption to
-                      Linux Kernel 2.1.x, module support)
-    - Michael Lang (assigning original pun/lun mapping, dynamical ldn
-                    assignment, rewritten adapter detection, this file, 
-		    patches, official driver maintenance and subsequent 
-		    debugging, related with the driver)
-
-   Table of Contents
-   -----------------
-   1 Abstract
-   2 Driver Description
-     2.1  IBM SCSI-Subsystem Detection
-     2.2  Physical Units, Logical Units, and Logical Devices
-     2.3  SCSI-Device Recognition and dynamical ldn Assignment
-     2.4  SCSI-Device Order
-     2.5  Regular SCSI-Command-Processing
-     2.6  Abort & Reset Commands
-     2.7  Disk Geometry
-     2.8  Kernel Boot Option
-     2.9  Driver Module Support
-     2.10 Multiple Hostadapter Support
-     2.11 /proc/scsi-Filesystem Information
-     2.12 /proc/mca-Filesystem Information
-     2.13 Supported IBM SCSI-Subsystems
-     2.14 Linux Kernel Versions
-   3 Code History
-   4 To do
-   5 Users' Manual
-     5.1 Commandline Parameters
-     5.2 Troubleshooting
-     5.3 Bugreports
-     5.4 Support WWW-page
-   6 References
-   7 Credits to
-     7.1 People
-     7.2 Sponsors & Supporters
-   8 Trademarks
-   9 Disclaimer
-
-                              * * *
-
-   1 Abstract
-   ----------
-   This README-file describes the IBM SCSI-subsystem low level driver for 
-   Linux. The descriptions which were formerly kept in the source-code have 
-   been taken out to this file to easify the codes' readability. The driver 
-   description has been updated, as most of the former description was already
-   quite outdated. The history of the driver development is also kept inside 
-   here. Multiple historical developments have been summarized to shorten the 
-   textsize a bit. At the end of this file you can find a small manual for 
-   this driver and hints to get it running on your machine.
-
-   2 Driver Description
-   --------------------
-   2.1 IBM SCSI-Subsystem Detection
-   --------------------------------
-   This is done in the ibmmca_detect() function. It first checks, if the
-   Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
-   Microchannel. In a next step, a free interrupt is chosen and the main
-   interrupt handler is connected to it to handle answers of the SCSI-
-   subsystem(s). If the F/W SCSI-adapter is forced by the BIOS to use IRQ11
-   instead of IRQ14, IRQ11 is used for the IBM SCSI-2 F/W adapter. In a 
-   further step it is checked, if the adapter gets detected by force from
-   the kernel commandline, where the I/O port and the SCSI-subsystem id can 
-   be specified. The next step checks if there is an integrated SCSI-subsystem
-   installed. This register area is fixed through all IBM PS/2 MCA-machines 
-   and appears as something like a virtual slot 10 of the MCA-bus. On most
-   PS/2 machines, the POS registers of slot 10 are set to 0xff or 0x00 if not
-   integrated SCSI-controller is available. But on certain PS/2s, like model 
-   9595, this slot 10 is used to store other information which at earlier
-   stage confused the driver and resulted in the detection of some ghost-SCSI. 
-   If POS-register 2 and 3 are not 0x00 and not 0xff, but all other POS
-   registers are either 0xff or 0x00, there must be an integrated SCSI-
-   subsystem present and it will be registered as IBM Integrated SCSI-
-   Subsystem. The next step checks, if there is a slot-adapter installed on 
-   the MCA-bus. To get this, the first two POS-registers, that represent the 
-   adapter ID are checked. If they fit to one of the ids, stored in the 
-   adapter list, a SCSI-subsystem is assumed to be found in a slot and will be 
-   registered. This check is done through all possible MCA-bus slots to allow 
-   more than one SCSI-adapter to be present in the PS/2-system and this is 
-   already the first point of problems. Looking into the technical reference 
-   manual for the IBM PS/2 common interfaces, the POS2 register must have 
-   different interpretation of its single bits to avoid overlapping I/O
-   regions. While one can assume, that the integrated subsystem has a fix 
-   I/O-address at 0x3540 - 0x3547, further installed IBM SCSI-adapters must 
-   use a different I/O-address. This is expressed by bit 1 to 3 of POS2 
-   (multiplied by 8 + 0x3540). Bits 2 and 3 are reserved for the integrated 
-   subsystem, but not for the adapters! The following list shows, how the 
-   bits of POS2 and POS3 should be interpreted.
-   
-   The POS2-register of all PS/2 models' integrated SCSI-subsystems has the 
-   following interpretation of bits:
-                           Bit 7 - 4 : Chip Revision ID (Release)
-                           Bit 3 - 2 : Reserved
-                           Bit 1     : 8k NVRAM Disabled
-                           Bit 0     : Chip Enable (EN-Signal)
-   The POS3-register is interpreted as follows (for most IBM SCSI-subsys.):
-                           Bit 7 - 5 : SCSI ID
-                           Bit 4 - 0 : Reserved = 0
-   The slot-adapters have different interpretation of these bits. The IBM SCSI
-   adapter (w/Cache) and the IBM SCSI-2 F/W adapter use the following
-   interpretation of the POS2 register:
-                           Bit 7 - 4 : ROM Segment Address Select
-			   Bit 3 - 1 : Adapter I/O Address Select (*8+0x3540)
-			   Bit 0     : Adapter Enable (EN-Signal)
-   and for the POS3 register:
-                           Bit 7 - 5 : SCSI ID 
-			   Bit 4     : Fairness Enable (SCSI ID3 f. F/W)
-			   Bit 3 - 0 : Arbitration Level
-   The most modern product of the series is the IBM SCSI-2 F/W adapter, it 
-   allows dual-bus SCSI and SCSI-wide addressing, which means, PUNs may be
-   between 0 and 15. Here, Bit 4 is the high-order bit of the 4-bit wide
-   adapter PUN expression. In short words, this means, that IBM PS/2 machines 
-   can only support 1 single integrated subsystem by default. Additional
-   slot-adapters get ports assigned by the automatic configuration tool.
-
-   One day I found a patch in ibmmca_detect(), forcing the I/O-address to be 
-   0x3540 for integrated SCSI-subsystems, there was a remark placed, that on 
-   integrated IBM SCSI-subsystems of model 56, the POS2 register was showing 5.
-   This means, that really for these models, POS2 has to be interpreted
-   sticking to the technical reference guide. In this case, the bit 2 (4) is 
-   a reserved bit and may not be interpreted. These differences between the 
-   adapters and the integrated controllers are taken into account by the 
-   detection routine of the driver on from version >3.0g. 
-
-   Every time, a SCSI-subsystem is discovered, the ibmmca_register() function
-   is called. This function checks first, if the requested area for the I/O-
-   address of this SCSI-subsystem is still available and assigns this I/O-
-   area to the SCSI-subsystem. There are always 8 sequential I/O-addresses
-   taken for each individual SCSI-subsystem found, which are:
-   
-     Offset            Type                  Permissions
-       0     Command Interface Register 1    Read/Write
-       1     Command Interface Register 2    Read/Write
-       2     Command Interface Register 3    Read/Write
-       3     Command Interface Register 4    Read/Write
-       4     Attention Register              Read/Write
-       5     Basic Control Register          Read/Write
-       6     Interrupt Status Register       Read
-       7     Basic Status Register           Read
-   
-   After the I/O-address range is assigned, the host-adapter is assigned
-   to a local structure which keeps all adapter information needed for the
-   driver itself and the mid- and higher-level SCSI-drivers. The SCSI pun/lun
-   and the adapters' ldn tables are initialized and get probed afterwards by
-   the check_devices() function. If no further adapters are found, 
-   ibmmca_detect() quits.
-   
-   2.2 Physical Units, Logical Units, and Logical Devices
-   ------------------------------------------------------
-   There can be up to 56 devices on the SCSI bus (besides the adapter):
-   there are up to 7 "physical units" (each identified by physical unit 
-   number or pun, also called the scsi id, this is the number you select
-   with hardware jumpers), and each physical unit can have up to 8 
-   "logical units" (each identified by logical unit number, or lun, 
-   between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two
-   busses and provides support for 30 logical devices at the same time, where
-   in wide-addressing mode you can have 16 puns with 32 luns on each device.
-   This section dexribes you the handling of devices on non-F/W adapters.
-   Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter
-   which means a lot of possible devices for such a small machine.
-
-   Typically the adapter has pun=7, so puns of other physical units
-   are between 0 and 6(15). On a wide-adapter a pun higher than 7 is
-   possible, but is normally not used. Almost all physical units have only 
-   one logical unit, with lun=0. A CD-ROM jukebox would be an example of a 
-   physical unit with more than one logical unit.
-
-   The embedded microprocessor of the IBM SCSI-subsystem hides the complex
-   two-dimensional (pun,lun) organization from the operating system.
-   When the machine is powered-up (or rebooted), the embedded microprocessor 
-   checks, on its own, all 56 possible (pun,lun) combinations, and the first 
-   15 devices found are assigned into a one-dimensional array of so-called 
-   "logical devices", identified by "logical device numbers" or ldn. The last 
-   ldn=15 is reserved for the subsystem itself. Wide adapters may have 
-   to check up to 15 * 8 = 120 pun/lun combinations.
-   
-   2.3 SCSI-Device Recognition and Dynamical ldn Assignment
-   --------------------------------------------------------
-   One consequence of information hiding is that the real (pun,lun)    
-   numbers are also hidden. The two possibilities to get around this problem
-   is to offer fake pun/lun combinations to the operating system or to 
-   delete the whole mapping of the adapter and to reassign the ldns, using
-   the immediate assign command of the SCSI-subsystem for probing through
-   all possible pun/lun combinations. a ldn is a "logical device number"
-   which is used by IBM SCSI-subsystems to access some valid SCSI-device.
-   At the beginning of the development of this driver, the following approach 
-   was used:
-   
-   First, the driver checked the ldn's (0 to 6) to find out which ldn's
-   have devices assigned. This was done by the functions check_devices() and
-   device_exists(). The interrupt handler has a special paragraph of code
-   (see local_checking_phase_flag) to assist in the checking. Assume, for
-   example, that three logical devices were found assigned at ldn 0, 1, 2.
-   These are presented to the upper layer of Linux SCSI driver
-   as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0). 
-   On the other hand, if the upper layer issues a command to device
-   say (4,0), this driver returns DID_NO_CONNECT error.
-
-   In a second step of the driver development, the following improvement has
-   been applied: The first approach limited the number of devices to 7, far
-   fewer than the 15 that it could usem then it just maped ldn -> 
-   (ldn/8,ldn%8) for pun,lun.  We ended up with a real mishmash of puns
-   and luns, but it all seemed to work.
-
-   The latest development, which is implemented from the driver version 3.0
-   and later, realizes the device recognition in the following way:
-   The physical SCSI-devices on the SCSI-bus are probed via immediate_assign- 
-   and device_inquiry-commands, that is all implemented in a completely new
-   made check_devices() subroutine. This delivers an exact map of the physical
-   SCSI-world that is now stored in the get_scsi[][]-array. This means,
-   that the once hidden pun,lun assignment is now known to this driver.
-   It no longer believes in default-settings of the subsystem and maps all
-   ldns to existing pun,lun "by foot". This assures full control of the ldn
-   mapping and allows dynamical remapping of ldns to different pun,lun, if
-   there are more SCSI-devices installed than ldns available (n>15). The
-   ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
-   excluding the pun of the subsystem. This assures, that at least simple 
-   SCSI-installations have optimum access-speed and are not touched by
-   dynamical remapping. The ldns 7 to 14 are put to existing devices with 
-   lun>0 or to non-existing devices, in order to satisfy the subsystem, if 
-   there are less than 15 SCSI-devices connected. In the case of more than 15 
-   devices, the dynamical mapping goes active. If the get_scsi[][] reports a 
-   device to be existant, but it has no ldn assigned, it gets a ldn out of 7 
-   to 14. The numbers are assigned in cyclic order. Therefore it takes 8 
-   dynamical reassignments on the SCSI-devices, until a certain device 
-   looses its ldn again. This assures, that dynamical remapping is avoided 
-   during intense I/O between up to 15 SCSI-devices (means pun,lun 
-   combinations). A further advantage of this method is, that people who
-   build their kernel without probing on all luns will get what they expect,
-   because the driver just won't assign everything with lun>0 when 
-   multpile lun probing is inactive.
- 
-   2.4 SCSI-Device Order
-   ---------------------
-   Because of the now correct recognition of physical pun,lun, and 
-   their report to mid-level- and higher-level-drivers, the new reported puns
-   can be different from the old, faked puns. Therefore, Linux will eventually
-   change /dev/sdXXX assignments and prompt you for corrupted superblock
-   repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
-   You have to reboot (CTRL-D) with an old kernel and set the /etc/fstab-file
-   entries right. After that, the system should come up as errorfree as before.
-   If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
-   in a Linux session booted on old kernel and run lilo before reboot. Check
-   lilo.conf anyway to get boot on other partitions with foreign OSes right
-   again. But there exists a feature of this driver that allows you to change
-   the assignment order of the SCSI-devices by flipping the PUN-assignment.
-   See the next paragraph for a description.
- 
-   The problem for this is, that Linux does not assign the SCSI-devices in the
-   way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to 
-   the device with at minimum id 0. But the first drive should be at id 6,
-   because for historical reasons, drive at id 6 has, by hardware, the highest
-   priority and a drive at id 0 the lowest. IBM was one of the rare producers,
-   where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most 
-   other producers' BIOS does not (I think even Adaptec-BIOS). The 
-   IBMMCA_SCSI_ORDER_STANDARD flag, which you set while configuring the
-   kernel enables to choose the preferred way of SCSI-device-assignment. 
-   Defining this flag would result in Linux determining the devices in the 
-   same order as DOS and OS/2 does on your MCA-machine. This is also standard 
-   on most industrial computers and OSes, like e.g. OS-9. Leaving this flag 
-   undefined will get your devices ordered in the default way of Linux. See 
-   also the remarks of Chris Beauregard from Dec 15, 1997 and the followups 
-   in section 3.
-   
-   2.5 Regular SCSI-Command-Processing
-   -----------------------------------
-   Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
-   and interrupt_handler().
-
-   The upper layer issues a scsi command by calling function 
-   ibmmca_queuecommand(). This function fills a "subsystem control block"
-   (scb) and calls a local function issue_cmd(), which writes a scb 
-   command into subsystem I/O ports. Once the scb command is carried out, 
-   the interrupt_handler() is invoked. If a device is determined to be 
-   existant and it has not assigned any ldn, it gets one dynamically.
-   For this, the whole stuff is done in ibmmca_queuecommand().
-
-   2.6 Abort & Reset Commands
-   --------------------------
-   These are implemented with busy waiting for interrupt to arrive.
-   ibmmca_reset() and ibmmca_abort() do not work sufficently well
-   up to now and need still a lot of development work. But, this seems
-   to be even a problem with other SCSI-low level drivers, too. However,
-   this should be no excuse.
-
-   2.7 Disk Geometry
-   -----------------
-   The ibmmca_biosparams() function should return the same disk geometry 
-   as the bios. This is needed for fdisk, etc. The returned geometry is 
-   certainly correct for disks smaller than 1 gigabyte. In the meantime,
-   it has been proved, that this works fine even with disks larger than
-   1 gigabyte.
-
-   2.8 Kernel Boot Option
-   ----------------------
-   The function ibmmca_scsi_setup() is called if option ibmmcascsi=n 
-   is passed to the kernel. See file linux/init/main.c for details.
-   
-   2.9 Driver Module Support
-   -------------------------
-   Is implemented and tested by K. Kudielka. This could probably not work
-   on kernels <2.1.0.
-  
-   2.10 Multiple Hostadapter Support
-   ---------------------------------
-   This driver supports up to eight interfaces of type IBM-SCSI-Subsystem. 
-   Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
-   IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
- 
-   2.11 /proc/scsi-Filesystem Information
-   --------------------------------------
-   Information about the driver condition is given in 
-   /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
-   
-   This table is quite informative for interested users. It shows the load
-   of commands on the subsystem and wether you are running the bypassed 
-   (software) or integrated (hardware) SCSI-command set (see below). The
-   amount of accesses is shown. Read, write, modeselect is shown seperately
-   in order to help debugging problems with CD-ROMs or tapedrives.
-   
-   The following table shows the list of 15 logical device numbers, that are
-   used by the SCSI-subsystem. The load on each ldn is shown in the table,
-   again, read and write commands are split. The last column shows the amount
-   of reassignments, that have been applied to the ldns, if you have more than
-   15 pun/lun combinations available on the SCSI-bus.
-   
-   The last two tables show the pun/lun map and the positions of the ldns
-   on this pun/lun map. This may change during operation, when a ldn is
-   reassigned to another pun/lun combination. If the necessity for dynamical
-   assignments is set to 'no', the ldn structure keeps static.
-   
-   2.12 /proc/mca-Filesystem Information
-   -------------------------------------
-   The slot-file contains all default entries and in addition chip and I/O-
-   address information of the SCSI-subsystem. This information is provided
-   by ibmmca_getinfo().
-   
-   2.13 Supported IBM SCSI-Subsystems
-   ----------------------------------
-   The following IBM SCSI-subsystems are supported by this driver:
-   
-     - IBM Fast/Wide SCSI-2 Adapter
-     - IBM 7568 Industrial Computer SCSI Adapter w/Cache
-     - IBM Expansion Unit SCSI Controller
-     - IBM SCSI Adapter w/Cache
-     - IBM SCSI Adapter
-     - IBM Integrated SCSI Controller
-     - All clones, 100% compatible with the chipset and subsystem command
-       system of IBM SCSI-adapters (forced detection)
-     
-   2.14 Linux Kernel Versions
-   --------------------------
-   The IBM SCSI-subsystem low level driver is prepared to be used with
-   all versions of Linux between 2.0.x and 2.4.x. The compatibility checks
-   are fully implemented up from version 3.1e of the driver. This means, that
-   you just need the latest ibmmca.h and ibmmca.c file and copy it in the
-   linux/drivers/scsi directory. The code is automatically adapted during 
-   kernel compilation. This is different from kernel 2.4.0! Here version 
-   4.0 or later of the driver must be used for kernel 2.4.0 or later. Version
-   4.0 or later does not work together with older kernels! Driver versions
-   older than 4.0 do not work together with kernel 2.4.0 or later. They work
-   on all older kernels.
-
-   3 Code History
-   --------------
-   Jan 15 1996:  First public release.
-   - Martin Kolinek
-
-   Jan 23 1996:  Scrapped code which reassigned scsi devices to logical
-   device numbers. Instead, the existing assignment (created
-   when the machine is powered-up or rebooted) is used. 
-   A side effect is that the upper layer of Linux SCSI 
-   device driver gets bogus scsi ids (this is benign), 
-   and also the hard disks are ordered under Linux the 
-   same way as they are under dos (i.e., C: disk is sda, 
-   D: disk is sdb, etc.).
-   - Martin Kolinek
-
-   I think that the CD-ROM is now detected only if a CD is 
-   inside CD_ROM while Linux boots. This can be fixed later,
-   once the driver works on all types of PS/2's.
-   - Martin Kolinek
-
-   Feb 7 1996:   Modified biosparam function. Fixed the CD-ROM detection. 
-   For now, devices other than harddisk and CD_ROM are 
-   ignored. Temporarily modified abort() function 
-   to behave like reset().
-   - Martin Kolinek
-
-   Mar 31 1996:  The integrated scsi subsystem is correctly found
-   in PS/2 models 56,57, but not in model 76. Therefore
-   the ibmmca_scsi_setup() function has been added today.
-   This function allows the user to force detection of
-   scsi subsystem. The kernel option has format
-   ibmmcascsi=n
-   where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
-   - Martin Kolinek
-
-   Aug 21 1996:  Modified the code which maps ldns to (pun,0).  It was
-   insufficient for those of us with CD-ROM changers.
-   - Chris Beauregard
- 
-   Dec 14 1996: More improvements to the ldn mapping.  See check_devices
-   for details.  Did more fiddling with the integrated SCSI detection,
-   but I think it's ultimately hopeless without actually testing the
-   model of the machine.  The 56, 57, 76 and 95 (ultimedia) all have
-   different integrated SCSI register configurations.  However, the 56
-   and 57 are the only ones that have problems with forced detection.
-   - Chris Beauregard
- 
-   Mar 8-16 1997: Modified driver to run as a module and to support 
-   multiple adapters. A structure, called ibmmca_hostdata, is now
-   present, containing all the variables, that were once only
-   available for one single adapter. The find_subsystem-routine has vanished.
-   The hardware recognition is now done in ibmmca_detect directly.
-   This routine checks for presence of MCA-bus, checks the interrupt
-   level and continues with checking the installed hardware.
-   Certain PS/2-models do not recognize a SCSI-subsystem automatically.
-   Hence, the setup defined by command-line-parameters is checked first.
-   Thereafter, the routine probes for an integrated SCSI-subsystem.
-   Finally, adapters are checked. This method has the advantage to cover all
-   possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
-   eight SCSI-subsystems can be recognized and announced to the upper-level
-   drivers with this improvement. A set of defines made changes to other
-   routines as small as possible.
-   - Klaus Kudielka
-   
-   May 30 1997: (v1.5b)
-   1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
-      This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which 
-      allows data to be written from the system to the device. It is a
-      necessary step to be allowed to set blocksize of SCSI-tape-drives and 
-      the tape-speed, whithout confusing the SCSI-Subsystem.
-   2) The recognition of a tape is included in the check_devices routine.
-      This is done by checking for TYPE_TAPE, that is already defined in
-      the kernel-scsi-environment. The markup of a tape is done in the 
-      global ldn_is_tape[] array. If the entry on index ldn 
-      is 1, there is a tapedrive connected.
-   3) The ldn_is_tape[] array is necessary to distinguish between tape- and 
-      other devices. Fixed blocklength devices should not cause a problem
-      with the SCB-command for read and write in the ibmmca_queuecommand
-      subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
-      the tape-devices, as recommended by IBM in this Technical Reference,
-      mentioned below. (IBM recommends to avoid using the read/write of the
-      subsystem, but the fact was, that read/write causes a command error from
-      the subsystem and this causes kernel-panic.)
-   4) In addition, I propose to use the ldn instead of a fix char for the
-      display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
-      devices that are accessed. It shows activity and easyfies debugging.   
-   The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
-   (I do not know yet the type). Optimization and CD-ROM audio-support, 
-   I am working on ...
-   - Michael Lang
-   
-   June 19 1997: (v1.6b)
-   1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
-      device-array. 
-   2) CD-ROM Audio-Play seems to work now.
-   3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
-      0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears 
-      also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that 
-      the problem is independent of the low-level-driver/bus-architecture.
-   4) Hexadecimal ldn on PS/2-95 LED-display.
-   5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
-      does not confuse the disk_rw_in_progress counter.
-   - Michael Lang
-  
-   June 21 1997: (v1.7b)
-   1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
-      outer-world about operational load statistics on the different ldns,
-      seen by the driver. Everybody that has more than one IBM-SCSI should
-      test this, because I only have one and cannot see what happens with more
-      than one IBM-SCSI hosts.
-   2) Definition of a driver version-number to have a better recognition of 
-      the source when there are existing too much releases that may confuse
-      the user, when reading about release-specific problems. Up to know,
-      I calculated the version-number to be 1.7. Because we are in BETA-test
-      yet, it is today 1.7b.
-   3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
-      CD-ROM did not work any more! The C7-command was a fake impression
-      I got while programming. Now, the READ and WRITE commands for CD-ROM are
-      no longer running over the subsystem, but just over 
-      IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
-      much faster(!) and hopefully all fancy multimedia-functions, like direct
-      digital recording from audio-CDs also work. (I tried it with cdda2wav
-      from the cdwtools-package and it filled up the harddisk immediately :-).)
-      To easify boolean logics, a further local device-type in ld[], called
-      is_cdrom has been included.
-   4) If one uses a SCSI-device of unsupported type/commands, one
-      immediately runs into a kernel-panic caused by Command Error. To better
-      understand which SCSI-command caused the problem, I extended this
-      specific panic-message slightly.
-   - Michael Lang
- 
-   June 25 1997: (v1.8b)
-   1) Some cosmetical changes for the handling of SCSI-device-types.
-      Now, also CD-Burners / WORMs and SCSI-scanners should work. For
-      MO-drives I have no experience, therefore not yet supported.
-      In logical_devices I changed from different type-variables to one
-      called 'device_type' where the values, corresponding to scsi.h,
-      of a SCSI-device are stored.
-   2) There existed a small bug, that maps a device, coming after a SCSI-tape
-      wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
-      -> problem removed.
-   3) Extension of the logical_device structure. Now it contains also device,
-      vendor and revision-level of a SCSI-device for internal usage.
-   - Michael Lang
-
-   June 26-29 1997: (v2.0b)
-   1) The release number 2.0b is necessary because of the completely new done
-      recognition and handling of SCSI-devices with the adapter. As I got
-      from Chris the hint, that the subsystem can reassign ldns dynamically,
-      I remembered this immediate_assign-command, I found once in the handbook.
-      Now, the driver first kills all ldn assignments that are set by default
-      on the SCSI-subsystem. After that, it probes on all puns and luns for
-      devices by going through all combinations with immediate_assign and
-      probing for devices, using device_inquiry. The found physical(!) pun,lun
-      structure is stored in get_scsi[][] as device types. This is followed
-      by the assignment of all ldns to existing SCSI-devices. If more ldns
-      than devices are available, they are assigned to non existing pun,lun
-      combinations to satisfy the adapter. With this, the dynamical mapping
-      was possible to implement. (For further info see the text in the 
-      source-code and in the description below. Read the description
-      below BEFORE installing this driver on your system!)
-   2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
-   3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
-      (pun) of the accessed SCSI-device. This is now senseful, because the 
-      pun known within the driver is exactly the pun of the physical device
-      and no longer a fake one.
-   4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
-      hit-statistics of ldns is shown and a second part, where the maps of 
-      physical and logical SCSI-devices are displayed. This could be very 
-      interesting, when one is using more than 15 SCSI-devices in order to 
-      follow the dynamical remapping of ldns.
-   - Michael Lang
- 
-   June 26-29 1997: (v2.0b-1)
-   1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
-      in the dynamical remapping part in ibmmca_queuecommand for the 
-      device_exist routine. Sorry.
-   - Michael Lang
- 
-   July 1-13 1997: (v3.0b,c)
-   1) Merging of the driver-developments of Klaus Kudielka and Michael Lang 
-      in order to get a optimum and unified driver-release for the 
-      IBM-SCSI-Subsystem-Adapter(s).
-         For people, using the Kernel-release >=2.1.0, module-support should 
-      be no problem. For users, running under <2.1.0, module-support may not 
-      work, because the methods have changed between 2.0.x and 2.1.x.
-   2) Added some more effective statistics for /proc-output.
-   3) Change typecasting at necessary points from (unsigned long) to
-      virt_to_bus().
-   4) Included #if... at special points to have specific adaption of the
-      driver to kernel 2.0.x and 2.1.x. It should therefore also run with 
-      later releases.
-   5) Magneto-Optical drives and medium-changers are also recognized, now.
-      Therefore, we have a completely gapfree recognition of all SCSI-
-      device-types, that are known by Linux up to kernel 2.1.31.
-   6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
-      the configuration, each connected SCSI-device will get a reset command
-      during boottime. This can be necessary for some special SCSI-devices.
-      This flag should be included in Config.in.
-      (See also the new Config.in file.)
-   Probable next improvement: bad disk handler.
-   - Michael Lang
- 
-   Sept 14 1997: (v3.0c)
-   1) Some debugging and speed optimization applied.
-   - Michael Lang
-
-   Dec 15, 1997
-    - chrisb@truespectra.com
-    - made the front panel display thingy optional, specified from the
-    command-line via ibmmcascsi=display.  Along the lines of the /LED
-    option for the OS/2 driver.
-    - fixed small bug in the LED display that would hang some machines.
-    - reversed ordering of the drives (using the
-    IBMMCA_SCSI_ORDER_STANDARD define).  This is necessary for two main
-    reasons:
-	- users who've already installed Linux won't be screwed.  Keep
-	in mind that not everyone is a kernel hacker.
-	- be consistent with the BIOS ordering of the drives.  In the
-	BIOS, id 6 is C:, id 0 might be D:.  With this scheme, they'd be
-	backwards.  This confuses the crap out of those heathens who've
-	got a impure Linux installation (which, <wince>, I'm one of).
-    This whole problem arises because IBM is actually non-standard with
-    the id to BIOS mappings.  You'll find, in fdomain.c, a similar
-    comment about a few FD BIOS revisions.  The Linux (and apparently
-    industry) standard is that C: maps to scsi id (0,0).  Let's stick
-    with that standard.
-    - Since this is technically a branch of my own, I changed the
-    version number to 3.0e-cpb.
-
-   Jan 17, 1998: (v3.0f)
-   1) Addition of some statistical info for /proc in proc_info.
-   2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
-      1997. In fact, IBM is right, concerning the assignment of SCSI-devices 
-      to driveletters. It is conform to the ANSI-definition of the SCSI-
-      standard to assign drive C: to SCSI-id 6, because it is the highest
-      hardware priority after the hostadapter (that has still today by
-      default everywhere id 7). Also realtime-operating systems that I use, 
-      like LynxOS and OS9, which are quite industrial systems use top-down
-      numbering of the harddisks, that is also starting at id 6. Now, one
-      sits a bit between two chairs. On one hand side, using the define
-      IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
-      the IBM- and ANSI-SCSI-standard and keeps this driver downward
-      compatible to older releases, on the other hand side, people is quite
-      habituated in believing that C: is assigned to (0,0) and much other
-      SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD 
-      define out of the driver and put it into Config.in as subitem of 
-      'IBM SCSI support'. A help, added to Documentation/Configure.help 
-      explains the differences between saying 'y' or 'n' to the user, when 
-      IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to 
-      choose the way of assignment, depending on his own situation and gusto.
-   3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
-      now called IBMMCA_SCSI_DEV_RESET.
-   4) Optimization of proc_info and its subroutines.
-   5) Added more in-source-comments and extended the driver description by
-      some explanation about the SCSI-device-assignment problem.
-   - Michael Lang
-   
-   Jan 18, 1998: (v3.0g)
-   1) Correcting names to be absolutely conform to the later 2.1.x releases.
-      This is necessary for 
-            IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
-            IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
-   - Michael Lang
- 
-   Jan 18, 1999: (v3.1 MCA-team internal)
-   1) The multiple hosts structure is accessed from every subroutine, so there
-      is no longer the address of the device structure passed from function
-      to function, but only the hostindex. A call by value, nothing more. This
-      should really be understood by the compiler and the subsystem should get
-      the right values and addresses.
-   2) The SCSI-subsystem detection was not complete and quite hugely buggy up
-      to now, compared to the technical manual. The interpretation of the pos2
-      register is not as assumed by people before, therefore, I dropped a note
-      in the ibmmca_detect function to show the registers' interpretation.
-      The pos-registers of integrated SCSI-subsystems do not contain any 
-      information concerning the IO-port offset, really. Instead, they contain
-      some info about the adapter, the chip, the NVRAM .... The I/O-port is
-      fixed to 0x3540 - 0x3547. There can be more than one adapters in the 
-      slots and they get an offset for the I/O area in order to get their own
-      I/O-address area. See chapter 2 for detailed description. At least, the 
-      detection should now work right, even on models other than 95. The 95ers
-      came happily around the bug, as their pos2 register contains always 0 
-      in the critical area. Reserved bits are not allowed to be interpreted, 
-      therefore, IBM is allowed to set those bits as they like and they may 
-      really vary between different PS/2 models. So, now, no interpretation 
-      of reserved bits - hopefully no trouble here anymore.
-   3) The command error, which you may get on models 55, 56, 57, 70, 77 and
-      P70 may have been caused by the fact, that adapters of older design do
-      not like sending commands to non-existing SCSI-devices and will react
-      with a command error as a sign of protest. While this error is not
-      present on IBM SCSI Adapter w/cache, it appears on IBM Integrated SCSI
-      Adapters. Therefore, I implemented a workarround to forgive those 
-      adapters their protests, but it is marked up in the statisctis, so
-      after a successful boot, you can see in /proc/scsi/ibmmca/<host_number>
-      how often the command errors have been forgiven to the SCSI-subsystem.
-      If the number is bigger than 0, you have a SCSI subsystem of older
-      design, what should no longer matter.
-   4) ibmmca_getinfo() has been adapted very carefully, so it shows in the 
-      slotn file really, what is senseful to be presented.
-   5) ibmmca_register() has been extended in its parameter list in order to
-      pass the right name of the SCSI-adapter to Linux.
-   - Michael Lang
-
-   Feb 6, 1999: (v3.1)
-   1) Finally, after some 3.1Beta-releases, the 3.1 release. Sorry, for 
-      the delayed release, but it was not finished with the release of 
-      Kernel 2.2.0.
-   - Michael Lang
-   
-   Feb 10, 1999 (v3.1)
-   1) Added a new commandline parameter called 'bypass' in order to bypass
-      every integrated subsystem SCSI-command consequently in case of
-      troubles.
-   2) Concatenated read_capacity requests to the harddisks. It gave a lot
-      of troubles with some controllers and after I wanted to apply some
-      extensions, it jumped out in the same situation, on my w/cache, as like 
-      on D. Weinehalls' Model 56, having integrated SCSI. This gave me the 
-      descissive hint to move the code-part out and declare it global. Now,
-      it seems to work by far much better an more stable. Let us see, what
-      the world thinks of it...
-   3) By the way, only Sony DAT-drives seem to show density code 0x13. A
-      test with a HP drive gave right results, so the problem is vendor-
-      specific and not a problem of the OS or the driver.
-   - Michael Lang
-   
-   Feb 18, 1999 (v3.1d)
-   1) The abort command and the reset function have been checked for 
-      inconsistencies. From the logical point of thinking, they work
-      at their optimum, now, but as the subsystem does not answer with an
-      interrupt, abort never finishes, sigh...
-   2) Everything, that is accessed by a busmaster request from the adapter
-      is now declared as global variable, even the return-buffer in the
-      local checking phase. This assures, that no accesses to undefined memory
-      areas are performed.
-   3) In ibmmca.h, the line unchecked_isa_dma is added with 1 in order to
-      avoid memory-pointers for the areas higher than 16MByte in order to
-      be sure, it also works on 16-Bit Microchannel bus systems.
-   4) A lot of small things have been found, but nothing that endangered the
-      driver operations. Just it should be more stable, now.
-   - Michael Lang
-      
-   Feb 20, 1999 (v3.1e)
-   1) I took the warning from the Linux Kernel Hackers Guide serious and 
-      checked the cmd->result return value to the done-function very carefully.
-      It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
-      some error appeared, else it is undefined. Now, this is fixed. Before
-      any SCB command gets queued, the tsb.dev_status is set to 0, so the 
-      cmd->result won't screw up Linux higher level drivers.
-   2) The reset-function has slightly improved. This is still planed for 
-      abort. During the abort and the reset function, no interrupts are 
-      allowed. This is however quite hard to cope with, so the INT-status
-      register is read. When the interrupt gets queued, one can find its
-      status immediately on that register and is enabled to continue in the
-      reset function. I had no chance to test this really, only in a bogus 
-      situation, I got this function running, but the situation was too much
-      worse for Linux :-(, so tests will continue.
-   3) Buffers got now consistent. No open address mapping, as before and
-      therefore no further troubles with the unassigned memory segmentation
-      faults that scrambled probes on 95XX series and even on 85XX series,
-      when the kernel is done in a not so perfectly fitting way.
-   4) Spontaneous interrupts from the subsystem, appearing without any
-      command previously queued are answered with a DID_BAD_INTR result.
-   5) Taken into account ZP Gus' proposals to reverse the SCSI-device
-      scan order. As it does not work on Kernel 2.1.x or 2.2.x, as proposed
-      by him, I implemented it in a slightly derived way, which offers in 
-      addition more flexibility.
-   - Michael Lang
-
-   Apr 23, 2000 (v3.2pre1)
-   1) During a very long time, I collected a huge amount of bugreports from
-      various people, trying really quite different things on their SCSI-
-      PS/2s. Today, all these bugreports are taken into account and should be
-      mostly solved. The major topics were:
-      - Driver crashes during boottime by no obvious reason.
-      - Driver panics while the midlevel-SCSI-driver is trying to inquire
-        the SCSI-device properties, even though hardware is in perfect state.
-      - Displayed info for the various slot-cards is interpreted wrong.
-      The main reasons for the crashes were two:
-      1) The commands to check for device information like INQUIRY, 
-         TEST_UNIT_READY, REQUEST_SENSE and MODE_SENSE cause the devices
-	 to deliver information of up to 255 bytes. Midlevel drivers offer
-	 1024 bytes of space for the answer, but the IBM-SCSI-adapters do
-	 not accept this, as they stick quite near to ANSI-SCSI and report
-	 a COMMAND_ERROR message which causes the driver to panic. The main
-	 problem was located around the INQUIRY command. Now, for all the
-	 mentioned commands, the buffersize, sent to the adapter is at 
-	 maximum 255 which seems to be a quite reasonable solution. 
-	 TEST_UNIT_READY gets a buffersize of 0 to make sure, that no 
-	 data is transferred in order to avoid any possible command failure.
-      2) On unsuccessful TEST_UNIT_READY, the midlevel-driver has to send
-         a REQUEST_SENSE in order to see, where the problem is located. This
-	 REQUEST_SENSE may have various length in its answer-buffer. IBM
-	 SCSI-subsystems report a command failure, if the returned buffersize
-	 is different from the sent buffersize, but this can be supressed by
-	 a special bit, which is now done and problems seem to be solved.
-   2) Code adaption to all kernel-releases. Now, the 3.2 code compiles on 
-      2.0.x, 2.1.x, 2.2.x and 2.3.x kernel releases without any code-changes.
-   3) Commandline-parameters are recognized again, even under Kernel 2.3.x or
-      higher.
-   - Michael Lang   
-
-   April 27, 2000 (v3.2pre2)
-   1) Bypassed commands get read by the adapter by one cycle instead of two.
-      This increases SCSI-performance.
-   2) Synchronous datatransfer is provided for sure to be 5 MHz on older
-      SCSI and 10 MHz on internal F/W SCSI-adapter.
-   3) New commandline parameters allow to force the adapter to slow down while
-      in synchronous transfer. Could be helpful for very old devices.
-   - Michael Lang
-   
-   June 2, 2000 (v3.2pre5)
-   1) Added Jim Shorney's contribution to make the activity indicator
-      flashing in addition to the LED-alphanumeric display-panel on
-      models 95A. To be enabled to choose this feature freely, a new
-      commandline parameter is added, called 'activity'.
-   2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
-   3) Added some suppress_exception bits to read_device_capacity and
-      all device_inquiry occurences in the driver code.
-   4) Complaints about the various KERNEL_VERSION implementations are
-      taken into account. Every local_LinuxKernelVersion occurence is
-      now replaced by KERNEL_VERSION, defined in linux/version.h. 
-      Corresponding changes were applied to ibmmca.h, too. This was a
-      contribution to all kernel-parts by Philipp Hahn.
-   - Michael Lang
-   
-   July 17, 2000 (v3.2pre8)
-   A long period of collecting bugreports from all corners of the world
-   now lead to the following corrections to the code:
-   1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this 
-      was, that it is possible to disbale Fast-SCSI for the external bus.
-      The feature-control command, where this crash appeared regularly tried
-      to set the maximum speed of 10MHz synchronous transfer speed and that
-      reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now,
-      the feature-command probes down from maximum speed until the adapter 
-      stops to complain, which is at the same time the maximum possible
-      speed selected in the reference program. So, F/W external can run at
-      5 MHz (slow-) or 10 MHz (fast-SCSI). During feature probing, the 
-      COMMAND ERROR message is used to detect if the adapter does not complain.
-   2) Up to now, only combined busmode is supported, if you use external
-      SCSI-devices, attached to the F/W-controller. If dual bus is selected,
-      only the internal SCSI-devices get accessed by Linux. For most 
-      applications, this should do fine. 
-   3) Wide-SCSI-addressing (16-Bit) is now possible for the internal F/W
-      bus on the F/W adapter. If F/W adapter is detected, the driver
-      automatically uses the extended PUN/LUN <-> LDN mapping tables, which
-      are now new from 3.2pre8. This allows PUNs between 0 and 15 and should
-      provide more fun with the F/W adapter.
-   4) Several machines use the SCSI: POS registers for internal/undocumented
-      storage of system relevant info. This confused the driver, mainly on
-      models 9595, as it expected no onboard SCSI only, if all POS in
-      the integrated SCSI-area are set to 0x00 or 0xff. Now, the mechanism
-      to check for integrated SCSI is much more restrictive and these problems
-      should be history.
-   - Michael Lang          
-
-   July 18, 2000 (v3.2pre9)
-   This develop rather quickly at the moment. Two major things were still
-   missing in 3.2pre8:
-   1) The adapter PUN for F/W adapters has 4-bits, while all other adapters
-      have 3-bits. This is now taken into account for F/W.
-   2) When you select CONFIG_IBMMCA_SCSI_ORDER_STANDARD, you should 
-      normally get the inverse probing order of your devices on the SCSI-bus.
-      The ANSI device order gets scrambled in version 3.2pre8!! Now, a new
-      and tested algorithm inverts the device-order on the SCSI-bus and
-      automatically avoids accidental access to whatever SCSI PUN the adapter 
-      is set and works with SCSI- and Wide-SCSI-addressing.
-   - Michael Lang
-
-   July 23, 2000 (v3.2pre10 unpublished) 
-   1) LED panel display supports wide-addressing in ibmmca=display mode.
-   2) Adapter-information and autoadaption to address-space is done.
-   3) Auto-probing for maximum synchronous SCSI transfer rate is working.
-   4) Optimization to some embedded function calls is applied.
-   5) Added some comment for the user to wait for SCSI-devices beeing probed.
-   6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
-   - Michael Lang
-   
-   July 26, 2000 (v3.2pre11)
-   1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and
-      a model 9595. Asking around in the community, nobody except of me has
-      seen such errors. Weired, but I am trying to recompile everything on
-      the model 9595. Maybe, as I use a specially modified gcc, that could
-      cause problems. But, it was not the reason. The true background was,
-      that the kernel was compiled for i386 and the 9595 has a 486DX-2. 
-      Normally, no troubles should appear, but for this special machine,
-      only the right processor support is working fine!
-   2) Previous problems with synchronous speed, slowing down from one adapter 
-      to the next during probing are corrected. Now, local variables store
-      the synchronous bitmask for every single adapter found on the MCA bus.
-   3) LED alphanumeric panel support for XX95 systems is now showing some
-      alive rotator during boottime. This makes sense, when no monitor is 
-      connected to the system. You can get rid of all display activity, if
-      you do not use any parameter or just ibmmcascsi=activity, for the 
-      harddrive activity LED, existant on all PS/2, except models 8595-XXX.
-      If no monitor is available, please use ibmmcascsi=display, which works
-      fine together with the linuxinfo utility for the LED-panel.
-   - Michael Lang
-   
-   July 29, 2000 (v3.2)
-   1) Submission of this driver for kernel 2.4test-XX and 2.2.17.
-   - Michael Lang
-   
-   December 28, 2000 (v3.2d / v4.0)
-   1) The interrupt handler had some wrong statement to wait for. This
-      was done due to experimental reasons during 3.2 development but it
-      has shown that this is not stable enough. Going back to wait for the
-      adapter to be not busy is best.
-   2) Inquiry requests can be shorter than 255 bytes of return buffer. Due
-      to a bug in the ibmmca_queuecommand routine, this buffer was forced
-      to 255 at minimum. If the memory address, this return buffer is pointing
-      to does not offer more space, invalid memory accesses destabilized the
-      kernel.
-   3) version 4.0 is only valid for kernel 2.4.0 or later. This is necessary
-      to remove old kernel version dependant waste from the driver. 3.2d is
-      only distributed with older kernels but keeps compatibility with older
-      kernel versions. 4.0 and higher versions cannot be used with older 
-      kernels anymore!! You must have at least kernel 2.4.0!!
-   4) The commandline argument 'bypass' and all its functionality got removed
-      in version 4.0. This was never really necessary, as all troubles were
-      based on non-command related reasons up to now, so bypassing commands
-      did not help to avoid any bugs. It is kept in 3.2X for debugging reasons.
-   5) Dynamical reassignment of ldns was again verified and analyzed to be
-      completely inoperational. This is corrected and should work now.
-   6) All commands that get sent to the SCSI adapter were verified and
-      completed in such a way, that they are now completely conform to the
-      demands in the technical description of IBM. Main candidates were the
-      DEVICE_INQUIRY, REQUEST_SENSE and DEVICE_CAPACITY commands. They must
-      be tranferred by bypassing the internal command buffer of the adapter
-      or else the response can be a random result. GET_POS_INFO would be more
-      safe in usage, if one could use the SUPRESS_EXCEPTION_SHORT, but this
-      is not allowed by the technical references of IBM. (Sorry, folks, the
-      model 80 problem is still a task to be solved in a different way.)
-   7) v3.2d is still hold back for some days for testing, while 4.0 is 
-      released.
-   - Michael Lang
-   
-   January 3, 2001 (v4.0a)
-   1) A lot of complains after the 2.4.0-prerelease kernel came in about
-      the impossibility to compile the driver as a module. This problem is
-      solved. In combination with that problem, some unprecise declaration
-      of the function option_setup() gave some warnings during compilation.
-      This is solved, too by a forward declaration in ibmmca.c.
-   2) #ifdef argument concerning CONFIG_SCSI_IBMMCA is no longer needed and
-      was entirely removed.
-   3) Some switch statements got optimized in code, as some minor variables
-      in internal SCSI-command handlers.
-   - Michael Lang
-
-   4 To do
-   -------
-        - IBM SCSI-2 F/W external SCSI bus support in seperate mode!
-	- It seems that the handling of bad disks is really bad -
-	  non-existent, in fact. However, a low-level driver cannot help
-	  much, if such things happen.
-
-   5 Users' Manual
-   ---------------
-   5.1 Commandline Parameters
-   --------------------------
-   There exist several features for the IBM SCSI-subsystem driver.
-   The commandline parameter format is:
-   
-         ibmmcascsi=<command1>,<command2>,<command3>,...
-	 
-   where commandN can be one of the following:
-   
-         display    Owners of a model 95 or other PS/2 systems with an
-	            alphanumeric LED display may set this to have their
-		    display showing the following output of the 8 digits:
-		      
-		                ------DA
-				
-		    where '-' stays dark, 'D' shows the SCSI-device id
-		    and 'A' shows the SCSI hostindex, beeing currently 
-		    accessed. During boottime, this will give the message
-		    
-		                SCSIini*
-				
-                    on the LED-panel, where the * represents a rotator, 
-		    showing the activity during the probing phase of the
-		    driver which can take up to two minutes per SCSI-adapter.
-	 adisplay   This works like display, but gives more optical overview 
-	            of the activities on the SCSI-bus. The display will have
-		    the following output:
-		    
-		                6543210A
-				
-		    where the numbers 0 to 6 light up at the shown position,
-		    when the SCSI-device is accessed. 'A' shows again the SCSI
-		    hostindex. If display nor adisplay is set, the internal
-		    PS/2 harddisk LED is used for media-activities. So, if
-		    you really do not have a system with a LED-display, you
-		    should not set display or adisplay. Keep in mind, that
-		    display and adisplay can only be used alternatively. It
-		    is not recommended to use this option, if you have some
-		    wide-addressed devices e.g. at the SCSI-2 F/W adapter in
-		    your system. In addition, the usage of the display for
-		    other tasks in parallel, like the linuxinfo-utility makes 
-		    no sense with this option.
-	 activity   This enables the PS/2 harddisk LED activity indicator.
-	            Most PS/2 have no alphanumeric LED display, but some
-		    indicator. So you should use this parameter to activate it.
-		    If you own model 9595 (Server95), you can have both, the 
-		    LED panel and the activity indicator in parallel. However,
-		    some PS/2s, like the 8595 do not have any harddisk LED 
-		    activity indicator, which means, that you must use the
-		    alphanumeric LED display if you want to monitor SCSI-
-		    activity.
-	 bypass     This is obsolete from driver version 4.0, as the adapters
-	            got that far understood, that the selection between 
-		    integrated and bypassed commands should now work completely
-		    correct! For historical reasons, the old description is
-		    kept here:
-	            This commandline parameter forces the driver never to use
-	            SCSI-subsystems' integrated SCSI-command set. Except of
-		    the immediate assign, which is of vital importance for
-		    every IBM SCSI-subsystem to set its ldns right. Instead,
-		    the ordinary ANSI-SCSI-commands are used and passed by the
-		    controller to the SCSI-devices, therefore 'bypass'. The
-		    effort, done by the subsystem is quite bogus and at a
-		    minimum and therefore it should work everywhere. This
-		    could maybe solve troubles with old or integrated SCSI-
-		    controllers and nasty harddisks. Keep in mind, that using 
-		    this flag will slow-down SCSI-accesses slightly, as the 
-		    software generated commands are always slower than the 
-		    hardware. Non-harddisk devices always get read/write-
-		    commands in bypass mode. On the most recent releases of 
-		    the Linux IBM-SCSI-driver, the bypass command should be
-		    no longer a necessary thing, if you are sure about your
-		    SCSI-hardware!
-	 normal     This is the parameter, introduced on the 2.0.x development
-	            rail by ZP Gu. This parameter defines the SCSI-device
-		    scan order in the new industry standard. This means, that
-		    the first SCSI-device is the one with the lowest pun.
-		    E.g. harddisk at pun=0 is scanned before harddisk at
-		    pun=6, which means, that harddisk at pun=0 gets sda
-		    and the one at pun=6 gets sdb.
-	 ansi       The ANSI-standard for the right scan order, as done by
-	            IBM, Microware and Microsoft, scans SCSI-devices starting
-		    at the highest pun, which means, that e.g. harddisk at
-		    pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
-		    like to have the same SCSI-device order, as in DOS, OS-9
-		    or OS/2, just use this parameter.
-         fast       SCSI-I/O in synchronous mode is done at 5 MHz for IBM-
-                    SCSI-devices. SCSI-2 Fast/Wide Adapter/A external bus
-                    should then run at 10 MHz if Fast-SCSI is enabled,
-                    and at 5 MHz if Fast-SCSI is disabled on the external
-                    bus. This is the default setting when nothing is 
-                    specified here.
-         medium     Synchronous rate is at 50% approximately, which means
-                    2.5 MHz for IBM SCSI-adapters and 5.0 MHz for F/W ext.
-                    SCSI-bus (when Fast-SCSI speed enabled on external bus).
-         slow       The slowest possible synchronous transfer rate is set. 
-                    This means 1.82 MHz for IBM SCSI-adapters and 2.0 MHz
-                    for F/W external bus at Fast-SCSI speed on the external
-		    bus.
-		    
-   A further option is that you can force the SCSI-driver to accept a SCSI-
-   subsystem at a certain I/O-address with a predefined adapter PUN. This
-   is done by entering 
-
-                  commandN   = I/O-base
-		  commandN+1 = adapter PUN
-		  
-   e.g. ibmmcascsi=0x3540,7 will force the driver to detect a SCSI-subsystem 
-   at I/O-address 0x3540 with adapter PUN 7. Please only use this method, if
-   the driver does really not recognize your SCSI-adapter! With driver version
-   3.2, this recognition of various adapters was hugely improved and you
-   should try first to remove your commandline arguments of such type with a 
-   newer driver. I bet, it will be recognized correctly. Even multiple and 
-   different types of IBM SCSI-adapters should be recognized correctly, too.
-   Use the forced detection method only as last solution!
-   
-   Examples:
-   
-        ibmmcascsi=adisplay
-	
-   This will use the advanced display mode for the model 95 LED alphanumeric
-   display.
-   
-        ibmmcascsi=display,0x3558,7
-	
-   This will activate the default display mode for the model 95 LED display
-   and will force the driver to accept a SCSI-subsystem at I/O-base 0x3558
-   with adapter PUN 7.
-   
-   5.2 Troubleshooting
-   -------------------
-   The following FAQs should help you to solve some major problems with this
-   driver.
-   
-     Q: "Reset SCSI-devices at boottime" halts the system at boottime, why?
-     A: This is only tested with the IBM SCSI Adapter w/cache. It is not
-        yet prooved to run on other adapters, however you may be lucky.
-	In version 3.1d this has been hugely improved and should work better,
-	now. Normally you really won't need to activate this flag in the
-	kernel configuration, as all post 1989 SCSI-devices should accept
-	the reset-signal, when the computer is switched on. The SCSI-
-	subsystem generates this reset while beeing initialized. This flag
-	is really reserved for users with very old, very strange or self-made
-	SCSI-devices.
-     Q: Why is the SCSI-order of my drives mirrored to the device-order
-        seen from OS/2 or DOS ?
-     A: It depends on the operating system, if it looks at the devices in
-        ANSI-SCSI-standard (starting from pun 6 and going down to pun 0) or
-	if it just starts at pun 0 and counts up. If you want to be conform
-	with OS/2 and DOS, you have to activate this flag in the kernel
-	configuration or you should set 'ansi' as parameter for the kernel.
-	The parameter 'normal' sets the new industry standard, starting
-	from pun 0, scanning up to pun 6. This allows you to change your 
-	opinion still after having already compiled the kernel.
-     Q: Why I cannot find the IBM MCA SCSI support in the config menue?
-     A: You have to activate MCA bus support, first.
-     Q: Where can I find the latest info about this driver?
-     A: See the file MAINTAINERS for the current WWW-address, which offers
-        updates, info and Q/A lists. At this files' origin, the webaddress
-	was: http://www.uni-mainz.de/~langm000/linux.html
-     Q: My SCSI-adapter is not recognized by the driver, what can I do?
-     A: Just force it to be recognized by kernel parameters. See section 5.1.
-        If this really happens, do also send e-mail to the maintainer, as
-	forced detection should be never necessary. Forced detection is in
-	principal some flaw of the driver adapter detection and goes into 
-	bugreports.
-     Q: The driver screws up, if it starts to probe SCSI-devices, is there
-        some way out of it?
-     A: Yes, that was some recognition problem of the correct SCSI-adapter
-        and its I/O base addresses. Upgrade your driver to the latest release
-	and it should be fine again.
-     Q: I get a message: panic IBM MCA SCSI: command error .... , what can
-        I do against this?
-     A: Previously, I followed the way by ignoring command errors by using
-        ibmmcascsi=forgiveall, but this command no longer exists and is
-	obsolete. If such a problem appears, it is caused by some segmentation
-	fault of the driver, which maps to some unallowed area. The latest 
-	version of the driver should be ok, as most bugs have been solved.
-     Q: There are still kernel panics, even after having set 
-        ibmmcascsi=forgiveall. Are there other possibilities to prevent
-	such panics?
-     A: No, get just the latest release of the driver and it should work 
-        better and better with increasing version number. Forget about this
-	ibmmcascsi=forgiveall, as also ignorecmd are obsolete.!
-     Q: Linux panics or stops without any comment, but it is probable, that my
-        harddisk(s) have bad blocks.
-     A: Sorry, the bad-block handling is still a feeble point of this driver,
-        but is on the schedule for development in the near future.
-     Q: Linux panics while dynamically assigning SCSI-ids or ldns.
-     A: If you disconnect a SCSI-device from the machine, while Linux is up
-        and the driver uses dynamical reassignment of logical device numbers
-	(ldn), it really gets "angry" if it won't find devices, that were still
-	present at boottime and stops Linux.
-     Q: The system does not recover after an abort-command has been generated.
-     A: This is regrettably true, as it is not yet understood, why the 
-        SCSI-adapter does really NOT generate any interrupt at the end of
-	the abort-command. As no interrupt is generated, the abort command
-	cannot get finished and the system hangs, sorry, but checks are 
-	running to hunt down this problem. If there is a real pending command,
-	the interrupt MUST get generated after abort. In this case, it
-	should finish well.
-     Q: The system gets in bad shape after a SCSI-reset, is this known?
-     A: Yes, as there are a lot of prescriptions (see the Linux Hackers'
-        Guide) what has to be done for reset, we still share the bad shape of
-	the reset functions with all other low level SCSI-drivers. 
-	Astonishingly, reset works in most cases quite ok, but the harddisks
-	won't run in synchonous mode anymore after a reset, until you reboot.
-     Q: Why does my XXX w/Cache adapter not use read-prefetch?
-     A: Ok, that is not completely possible. If a cache is present, the 
-        adapter tries to use it internally. Explicitly, one can use the cache
-	with a read prefetch command, maybe in future, but this requires
-	some major overhead of SCSI-commands that risks the performance to
-	go down more than it gets improved. Tests with that are running.
-     Q: I have a IBM SCSI-2 Fast/Wide adapter, it boots in some way and hangs.
-     A: Yes, that is understood, as for sure, your SCSI-2 Fast/Wide adapter
-        was in such a case recognized as integrated SCSI-adapter or something 
-	else, but not as the correct adapter. As the I/O-ports get assigned 
-	wrongly by that reason, the system should crash in most cases. You 
-	should upgrade to the latest release of the SCSI-driver. The 
-	recommended version is 3.2 or later. Here, the F/W support is in
-	a stable and reliable condition. Wide-addressing is in addition 
-	supported.
-     Q: I get a Ooops message and something like "killing interrupt".
-     A: The reason for this is that the IBM SCSI-subsystem only sends a 
-        termination status back, if some error appeared. In former releases
-	of the driver, it was not checked, if the termination status block
-	is NULL. From version 3.2, it is taken care of this.
-     Q: I have a F/W adapter and the driver sees my internal SCSI-devices,
-        but ignores the external ones.
-     A: Select combined busmode in the IBM config-program and check for that
-        no SCSI-id on the external devices appears on internal devices.
-        Reboot afterwards. Dual busmode is supported, but works only for the
-	internal bus, yet. External bus is still ignored. Take care for your
-	SCSI-ids. If combined bus-mode is activated, on some adapters, 
-	the wide-addressing is not possible, so devices with ids between 8 
-	and 15 get ignored by the driver & adapter!
-     Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck.
-        A COMMAND ERROR is reported and characters on the screen are missing.
-	Warm reboot is not possible. Things look like quite weired.
-     A: Check the processor type of your 9595. If you have an 80486 or 486DX-2
-        processor complex on your mainboard and you compiled a kernel that
-	supports 80386 processors, it is possible, that the kernel cannot
-	keep track of the PS/2 interrupt handling and stops on an NMI. Just
-	compile a kernel for the correct processor type of your PS/2 and
-	everything should be fine. This is necessary even if one assumes,
-	that some 80486 system should be downward compatible to 80386
-	software.
-     Q: Some commands hang and interrupts block the machine. After some
-        timeout, the syslog reports that it tries to call abort, but the
-	machine is frozen.
-     A: This can be a busy wait bug in the interrupt handler of driver 
-        version 3.2. You should at least upgrade to 3.2c if you use 
-	kernel < 2.4.0 and driver version 4.0 if you use kernel 2.4.0 or 
-	later (including all test releases).
-     Q: I have a PS/2 model 80 and more than 16 MBytes of RAM. The driver
-        completely refuses to work, reports NMIs, COMMAND ERRORs or other
-	ambiguous stuff. When reducing the RAM size down below 16 MB, 
-	everything is running smoothly.
-     A: No real answer, yet. In any case, one should force the kernel to
-        present SCBs only below the 16 MBytes barrier. Maybe this solves the
-	problem. Not yet tried, but guessing that it could work. To get this,
-	set unchecked_isa_dma argument of ibmmca.h from 0 to 1.
-
-   5.3 Bugreports
-   --------------
-   If you really find bugs in the sourcecode or the driver will successfully
-   refuse to work on your machine, you should send a bug report to me. The
-   best for this is to follow the instructions on the WWW-page for this
-   driver. Fill out the bug-report form, placed on the WWW-page and ship it,
-   so the bugs can be taken into account with maximum efforts. But, please
-   do not send bug reports about this driver to Linus Torvalds or Leonard
-   Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
-   SCSI-drivers and won't have the time left to look inside every single
-   driver to fix a bug and especially DO NOT send modified code to Linus
-   Torvalds or Alan J. Cox which has not been checked here!!! They are both
-   quite burried in E-mail (as me, sometimes, too) and one should first check
-   for problems on my local teststand. Recently, I got a lot of 
-   bugreports for errors in the ibmmca.c code, which I could not imagine, but
-   a look inside some Linux-distribution showed me quite often some modified
-   code, which did no longer work on most other machines than the one of the
-   modifier. Ok, so now that there is maintenance service available for this
-   driver, please use this address first in order to keep the level of
-   confusion low. Thank you!
-   
-   When you get a SCSI-error message that panics your system, a list of
-   register-entries of the SCSI-subsystem is shown (from Version 3.1d). With 
-   this list, it is very easy for the maintainer to localize the problem in 
-   the driver or in the configuration of the user. Please write down all the 
-   values from this report and send them to the maintainer. This would really 
-   help a lot and makes life easier concerning misunderstandings.
-   
-   Use the bug-report form (see 5.4 for its address) to send all the bug-
-   stuff to the maintainer or write e-mail with the values from the table. 
-   
-   5.4 Support WWW-page
-   --------------------
-   The address of the IBM SCSI-subsystem supporting WWW-page is:
-   
-        http://www.uni-mainz.de/~langm000/linux.html
-	
-   Here you can find info about the background of this driver, patches,
-   troubleshooting support, news and a bugreport form. Please check that
-   WWW-page regularly for latest hints. If ever this URL changes, please 
-   refer to the MAINTAINERS file in order to get the latest address.
-   
-   For the bugreport, please fill out the formular on the corresponding
-   WWW-page. Read the dedicated instructions and write as much as you
-   know about your problem. If you do not like such formulars, please send
-   some e-mail directly, but at least with the same information as required by
-   the formular.
-   
-   If you have extensive bugreports, including Ooops messages and 
-   screen-shots, please feel free to send it directly to the address
-   of the maintainer, too. The current address of the maintainer is:
-   
-            Michael Lang <langa2@kph.uni-mainz.de>
-   
-   6 References
-   ------------
-   IBM Corp., "Update for the PS/2 Hardware Interface Technical Reference, 
-   Common Interfaces", Armonk, September 1991, PN 04G3281, 
-   (available in the U.S. for $21.75 at 1-800-IBM-PCTB or in Germany for
-   around 40,-DM at "Hallo IBM").
-  
-   IBM Corp., "Personal System/2 Micro Channel SCSI
-   Adapter with Cache Technical Reference", Armonk, March 1990, PN 68X2365.
-
-   IBM Corp., "Personal System/2 Micro Channel SCSI
-   Adapter Technical Reference", Armonk, March 1990, PN 68X2397.
-
-   IBM Corp., "SCSI-2 Fast/Wide Adapter/A Technical Reference - Dual Bus",
-   Armonk, March 1994, PN 83G7545.
- 
-   Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
-   Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
-   Addison Wesley, 1996.
-   
-   Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
-   Hill - North Carolina, 1995
-   
-   Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
-   1993
-   
-   Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
-   Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
-   
-   7 Credits to
-   ------------
-   7.1 People
-   ----------
-   Klaus Grimm
-                who already a long time ago gave me the old code from the
-		SCSI-driver in order to get it running for some old machine
-		in our institute.
-   Martin Kolinek
-                who wrote the first release of the IBM SCSI-subsystem driver.
-   Chris Beauregard
-                who for a long time maintained MCA-Linux and the SCSI-driver
-		in the beginning. Chris, wherever you are: Cheers to you!
-   Klaus Kudielka
-                with whom in the 2.1.x times, I had a quite fruitful
-                cooperation to get the driver running as a module and to get
-		it running with multiple SCSI-adapters.
-   David Weinehall
-                for his excellent maintenance of the MCA-stuff and the quite 
-		detailed bug reports and ideas for this driver (and his 
-		patience ;-)).
-   Alan J. Cox  
-                for his bugreports and his bold activities in cross-checking
-		the driver-code with his teststand.
-		
-   7.2 Sponsors & Supporters
-   -------------------------
-   "Hallo IBM",
-   IBM-Deutschland GmbH
-                the service of IBM-Deutschland for customers. Their E-Mail
-		service is unbeatable. Whatever old stuff I asked for, I 
-		always got some helpful answers.
-   Karl-Otto Reimers,
-   IBM Klub - Sparte IBM Geschichte, Sindelfingen
-                for sending me a copy of the w/Cache manual from the 
-		IBM-Deutschland archives.
-   Harald Staiger
-                for his extensive hardware donations which allows me today
-		still to test the driver in various constellations.
-   Erich Fritscher
-                for his very kind sponsoring.
-   Louis Ohland,
-   Charles Lasitter
-                for support by shipping me an IBM SCSI-2 Fast/Wide manual.
-                In addition, the contribution of various hardware is quite 
-                decessive and will make it possible to add FWSR (RAID)
-                adapter support to the driver in the near future! So,
-                complaints about no RAID support won't remain forever.
-                Yes, folks, that is no joke, RAID support is going to rise!
-   Erik Weber
-                for the great deal we made about a model 9595 and the nice
-                surrounding equipment and the cool trip to Mannheim
-                second-hand computer market. In addition, I would like
-		to thank him for his exhaustive SCSI-driver testing on his 
-		95er PS/2 park.
-   Anthony Hogbin
-                for his direct shipment of a SCSI F/W adapter, which allowed
-                me immediately on the first stage to try it on model 8557
-                together with onboard SCSI adapter and some SCSI w/Cache.
-   Andreas Hotz
-                for his support by memory and an IBM SCSI-adapter. Collecting
-                all this together now allows me to try really things with
-                the driver at maximum load and variety on various models in
-                a very quick and efficient way.
-   Peter Jennewein
-                for his model 30, which serves me as part of my teststand
-		and his cool remark about how you make an ordinary diskette
-		drive working and how to connect it to an IBM-diskette port.
-   Johannes Gutenberg-Universitaet, Mainz &
-   Institut fuer Kernphysik, Mainz Microtron (MAMI)
-                for the offered space, the link, placed on the central
-                homepage and the space to store and offer the driver and 
-		related material and the free working times, which allow
-                me to answer all your e-mail.
-                   
-   8 Trademarks
-   ------------
-   IBM, PS/2, OS/2, Microchannel are registered trademarks of International 
-   Business Machines Corporation
-   
-   MS-DOS is a registered trademark of Microsoft Corporation
-   
-   Microware, OS-9 are registered trademarks of Microware Systems
-   
-   9 Disclaimer
-   ------------
-   Beside the GNU General Public License and the dependant disclaimers and disclaimers
-   concerning the Linux-kernel in special, this SCSI-driver comes without any
-   warranty. Its functionality is tested as good as possible on certain 
-   machines and combinations of computer hardware, which does not exclude,
-   that dataloss or severe damage of hardware is possible while using this
-   part of software on some arbitrary computer hardware or in combination 
-   with other software packages. It is highly recommended to make backup
-   copies of your data before using this software. Furthermore, personal
-   injuries by hardware defects, that could be caused by this SCSI-driver are
-   not excluded and it is highly recommended to handle this driver with a
-   maximum of carefulness.
-   
-   This driver supports hardware, produced by International Business Machines
-   Corporation (IBM).
-   
-------
-Michael Lang 
-(langa2@kph.uni-mainz.de)
diff -Nru a/drivers/scsi/README.in2000 b/drivers/scsi/README.in2000
--- a/drivers/scsi/README.in2000	Sun Nov 17 20:30:13 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,202 +0,0 @@
-
-UPDATE NEWS: version 1.33 - 26 Aug 98
-
-   Interrupt management in this driver has become, over
-   time, increasingly odd and difficult to explain - this
-   has been mostly due to my own mental inadequacies. In
-   recent kernels, it has failed to function at all when
-   compiled for SMP. I've fixed that problem, and after
-   taking a fresh look at interrupts in general, greatly
-   reduced the number of places where they're fiddled
-   with. Done some heavy testing and it looks very good.
-   The driver now makes use of the __initfunc() and
-   __initdata macros to save about 4k of kernel memory.
-   Once again, the same code works for both 2.0.xx and
-   2.1.xx kernels.
-
-UPDATE NEWS: version 1.32 - 28 Mar 98
-
-   Removed the check for legal IN2000 hardware versions:
-   It appears that the driver works fine with serial
-   EPROMs (the 8-pin chip that defines hardware rev) as
-   old as 2.1, so we'll assume that all cards are OK.
-
-UPDATE NEWS: version 1.31 - 6 Jul 97
-
-   Fixed a bug that caused incorrect SCSI status bytes to be
-   returned from commands sent to LUN's greater than 0. This
-   means that CDROM changers work now! Fixed a bug in the
-   handling of command-line arguments when loaded as a module.
-   Also put all the header data in in2000.h where it belongs.
-   There are no longer any differences between this driver in
-   the 2.1.xx source tree and the 2.0.xx tree, as of 2.0.31
-   and 2.1.45 (or is it .46?) - this makes things much easier
-   for me...
-
-UPDATE NEWS: version 1.30 - 14 Oct 96
-
-   Fixed a bug in the code that sets the transfer direction
-   bit (DESTID_DPD in the WD_DESTINATION_ID register). There
-   are quite a few SCSI commands that do a write-to-device;
-   now we deal with all of them correctly. Thanks to Joerg
-   Dorchain for catching this one.
-
-UPDATE NEWS: version 1.29 - 24 Sep 96
-
-   The memory-mapped hardware on the card is now accessed via
-   the 'readb()' and 'readl()' macros - required by the new
-   memory management scheme in the 2.1.x kernel series.
-   As suggested by Andries Brouwer, 'bios_param()' no longer
-   forces an artificial 1023 track limit on drives. Also
-   removed some kludge-code left over from struggles with
-   older (buggy) compilers.
-
-UPDATE NEWS: version 1.28 - 07 May 96
-
-   Tightened up the "interrupts enabled/disabled" discipline
-   in 'in2000_queuecommand()' and maybe 1 or 2 other places.
-   I _think_ it may have been a little too lax, causing an
-   occasional crash during full moon. A fully functional
-   /proc interface is now in place - if you want to play
-   with it, start by doing 'cat /proc/scsi/in2000/0'. You
-   can also use it to change a few run-time parameters on
-   the fly, but it's mostly for debugging. The curious
-   should take a good look at 'in2000_proc_info()' in the
-   in2000.c file to get an understanding of what it's all
-   about; I figure that people who are really into it will
-   want to add features suited to their own needs...
-   Also, sync is now DISABLED by default.
-
-UPDATE NEWS: version 1.27 - 10 Apr 96
-
-   Fixed a well-hidden bug in the adaptive-disconnect code
-   that would show up every now and then during extreme
-   heavy loads involving 2 or more simultaneously active
-   devices. Thanks to Joe Mack for keeping my nose to the
-   grindstone on this one.
-
-UPDATE NEWS: version 1.26 - 07 Mar 96
-
-   1.25 had a nasty bug that bit people with swap partitions
-   and tape drives. Also, in my attempt to guess my way
-   through Intel assembly language, I made an error in the
-   inline code for IO writes. Made a few other changes and
-   repairs - this version (fingers crossed) should work well.
-
-UPDATE NEWS: version 1.25 - 05 Mar 96
-
-   Kernel 1.3.70 interrupt mods added; old kernels still OK.
-   Big help from Bill Earnest and David Willmore on speed
-   testing and optimizing: I think there's a real improvement
-   in this area.
-   New! User-friendly command-line interface for LILO and
-   module loading - the old method is gone, so you'll need
-   to read the comments for 'setup_strings' near the top
-   of in2000.c. For people with CDROM's or other devices
-   that have a tough time with sync negotiation, you can
-   now selectively disable sync on individual devices -
-   search for the 'nosync' keyword in the command-line
-   comments. Some of you disable the BIOS on the card, which
-   caused the auto-detect function to fail; there is now a
-   command-line option to force detection of a ROM-less card.
-
-UPDATE NEWS: version 1.24a - 24 Feb 96
-
-   There was a bug in the synchronous transfer code. Only
-   a few people downloaded before I caught it - could have
-   been worse.
-
-UPDATE NEWS: version 1.24 - 23 Feb 96
-
-   Lots of good changes. Advice from Bill Earnest resulted
-   in much better detection of cards, more efficient usage
-   of the fifo, and (hopefully) faster data transfers. The
-   jury is still out on speed - I hope it's improved some.
-   One nifty new feature is a cool way of doing disconnect/
-   reselect. The driver defaults to what I'm calling
-   'adaptive disconnect' - meaning that each command is
-   evaluated individually as to whether or not it should be
-   run with the option to disconnect/reselect (if the device
-   chooses), or as a "SCSI-bus-hog". When several devices
-   are operating simultaneously, disconnects are usually an
-   advantage. In a single device system, or if only 1 device
-   is being accessed, transfers usually go faster if disconnects
-   are not allowed.
-
-
-
-The default arguments (you get these when you don't give an 'in2000'
-command-line argument, or you give a blank argument) will cause
-the driver to do adaptive disconnect, synchronous transfers, and a
-minimum of debug messages. If you want to fool with the options,
-search for 'setup_strings' near the top of the in2000.c file and
-check the 'hostdata->args' section in in2000.h - but be warned! Not
-everything is working yet (some things will never work, probably).
-I believe that disabling disconnects (DIS_NEVER) will allow you
-to choose a LEVEL2 value higher than 'L2_BASIC', but I haven't
-spent a lot of time testing this. You might try 'ENABLE_CLUSTERING'
-to see what happens: my tests showed little difference either way.
-There's also a define called 'DEFAULT_SX_PER'; this sets the data
-transfer speed for the asynchronous mode. I've put it at 500 ns
-despite the fact that the card could handle settings of 376 or
-252, because higher speeds may be a problem with poor quality
-cables or improper termination; 500 ns is a compromise. You can
-choose your own default through the command-line with the
-'period' keyword.
-
-
-------------------------------------------------
-***********  DIP switch settings  **************
-------------------------------------------------
-
-   sw1-1 sw1-2    BIOS address (hex)
-   -----------------------------------------
-    off   off     C8000 - CBFF0
-    on    off     D8000 - DBFF0
-    off   on      D0000 - D3FF0
-    on    on      BIOS disabled
-
-   sw1-3 sw1-4    IO port address (hex)
-   ------------------------------------
-    off   off     220 - 22F
-    on    off     200 - 20F
-    off   on      110 - 11F
-    on    on      100 - 10F
-
-   sw1-5 sw1-6 sw1-7    Interrupt
-   ------------------------------
-    off   off   off     15
-    off   on    off     14
-    off   off   on      11
-    off   on    on      10
-    on    -     -       disabled
-
-   sw1-8 function depends on BIOS version. In earlier versions this
-   controlled synchronous data transfer support for MSDOS:
-      off = disabled
-      on  = enabled
-   In later ROMs (starting with 01.3 in April 1994) sw1-8 controls
-   the "greater than 2 disk drive" feature that first appeared in
-   MSDOS 5.0 (ignored by Linux):
-      off = 2 drives maximum
-      on  = 7 drives maximum
-
-   sw1-9    Floppy controller
-   --------------------------
-    off     disabled
-    on      enabled
-
-------------------------------------------------
-
-   I should mention that Drew Eckhardt's 'Generic NCR5380' sources
-   were my main inspiration, with lots of reference to the IN2000
-   driver currently distributed in the kernel source. I also owe
-   much to a driver written by Hamish Macdonald for Linux-m68k(!).
-   And to Eric Wright for being an ALPHA guinea pig. And to Bill
-   Earnest for 2 tons of great input and information. And to David
-   Willmore for extensive 'bonnie' testing. And to Joe Mack for
-   continual testing and feedback.
-
-
-            John Shifflett    jshiffle@netcom.com
-
diff -Nru a/drivers/scsi/README.ncr53c7xx b/drivers/scsi/README.ncr53c7xx
--- a/drivers/scsi/README.ncr53c7xx	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,40 +0,0 @@
-README for WarpEngine/A4000T/A4091 SCSI kernels.
-
-Use the following options to disable options in the SCSI driver.
-
-Using amiboot for example.....
-
-To disable Synchronous Negotiation....
-
-	amiboot -k kernel 53c7xx=nosync:0	
-
-To disable Disconnection....
-	
-	amiboot -k kernel 53c7xx=nodisconnect:0
-
-To disable certain SCSI devices...
-
-	amiboot -k kernel 53c7xx=validids:0x3F
-
-	this allows only device ID's 0,1,2,3,4 and 5 for linux to handle.
-	(this is a bitmasked field - i.e. each bit represents a SCSI ID)
-
-These commands work on a per controller basis and use the option 'next' to
-move to the next controller in the system.
-
-e.g.
-	amiboot -k kernel 53c7xx=nodisconnect:0,next,nosync:0
-
-	this uses No Disconnection on the first controller and Asynchronous
-	SCSI on the second controller.
-
-Known Issues:
-
-Two devices are known not to function with the default settings of using
-synchronous SCSI. These are the Archive Viper 150 Tape Drive and the 
-SyQuest SQ555 removeable hard drive. When using these devices on a controller
-use the 'nosync:0' option.
-
-Please try these options and post any problems/successes to me.
-
-Alan Hourihane <alanh@fairlite.demon.co.uk>
diff -Nru a/drivers/scsi/README.ncr53c8xx b/drivers/scsi/README.ncr53c8xx
--- a/drivers/scsi/README.ncr53c8xx	Sun Nov 17 20:30:02 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1854 +0,0 @@
-The Linux NCR53C8XX/SYM53C8XX drivers README file
-
-Written by Gerard Roudier <groudier@free.fr>
-21 Rue Carnot
-95170 DEUIL LA BARRE - FRANCE
-
-29 May 1999
-===============================================================================
-
-1.  Introduction
-2.  Supported chips and SCSI features
-3.  Advantages of the enhanced 896 driver
-      3.1 Optimized SCSI SCRIPTS
-      3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
-4.  Memory mapped I/O versus normal I/O
-5.  Tagged command queueing
-6.  Parity checking
-7.  Profiling information
-8.  Control commands
-      8.1  Set minimum synchronous period
-      8.2  Set wide size
-      8.3  Set maximum number of concurrent tagged commands
-      8.4  Set order type for tagged command
-      8.5  Set debug mode
-      8.6  Clear profile counters
-      8.7  Set flag (no_disc)
-      8.8  Set verbose level
-      8.9  Reset all logical units of a target
-      8.10 Abort all tasks of all logical units of a target
-9.  Configuration parameters
-10. Boot setup commands
-      10.1 Syntax
-      10.2 Available arguments
-             10.2.1  Master parity checking
-             10.2.2  Scsi parity checking
-             10.2.3  Scsi disconnections
-             10.2.4  Special features
-             10.2.5  Ultra SCSI support
-             10.2.6  Default number of tagged commands
-             10.2.7  Default synchronous period factor
-             10.2.8  Negotiate synchronous with all devices
-             10.2.9  Verbosity level
-             10.2.10 Debug mode
-             10.2.11 Burst max
-             10.2.12 LED support
-             10.2.13 Max wide
-             10.2.14 Differential mode
-             10.2.15 IRQ mode
-             10.2.16 Reverse probe
-             10.2.17 Fix up PCI configuration space
-             10.2.18 Serial NVRAM
-             10.2.19 Check SCSI BUS 
-             10.2.20 Exclude a host from being attached
-             10.2.21 Suggest a default SCSI id for hosts
-             10.2.22 Enable use of IMMEDIATE ARBITRATION
-      10.3 Advised boot setup commands
-      10.4 PCI configuration fix-up boot option
-      10.5 Serial NVRAM support boot option
-      10.6 SCSI BUS checking boot option
-      10.7 IMMEDIATE ARBITRATION boot option
-11. Some constants and flags of the ncr53c8xx.h header file
-12. Installation
-13. Architecture dependent features
-14. Known problems
-      14.1 Tagged commands with Iomega Jaz device
-      14.2 Device names change when another controller is added
-      14.3 Using only 8 bit devices with a WIDE SCSI controller.
-      14.4 Possible data corruption during a Memory Write and Invalidate
-      14.5 IRQ sharing problems
-15. SCSI problem troubleshooting
-      15.1 Problem tracking
-      15.2 Understanding hardware error reports
-16. Synchonous transfer negotiation tables
-      16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
-      16.2 Synchronous timings for fast SCSI-2 53C8XX controllers
-17. Serial NVRAM support (by Richard Waltham)
-      17.1 Features
-      17.2 Symbios NVRAM layout
-      17.3 Tekram  NVRAM layout
-18. Support for Big Endian
-      18.1 Big Endian CPU
-      18.2 NCR chip in Big Endian mode of operations
-
-===============================================================================
-
-1. Introduction
-
-The initial Linux ncr53c8xx driver has been a port of the ncr driver from 
-FreeBSD that has been achieved in November 1995 by:
-          Gerard Roudier              <groudier@free.fr>
-
-The original driver has been written for 386bsd and FreeBSD by:
-          Wolfgang Stanglmeier        <wolf@cologne.de>
-          Stefan Esser                <se@mi.Uni-Koeln.de>
-
-It is now available as a bundle of 2 drivers:
-
-- ncr53c8xx generic driver that supports all the SYM53C8XX family including 
-  the ealiest 810 rev. 1, the latest 896 (2 channel LVD SCSI controller) and
-  the new 895A (1 channel LVD SCSI controller).
-- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest 
-  chips in order to gain advantage of new features, as LOAD/STORE intructions 
-  available since the 810A and hardware phase mismatch available with the 
-  896 and the 895A.
-
-You can find technical information about the NCR 8xx family in the
-PCI-HOWTO written by Michael Will and in the SCSI-HOWTO written by
-Drew Eckhardt.
-
-Information about new chips is available at LSILOGIC web server:
-
-          http://www.lsilogic.com/
-
-SCSI standard documentations are available at SYMBIOS ftp server:
-
-          ftp://ftp.symbios.com/
-
-Usefull SCSI tools written by Eric Youngdale are available at tsx-11:
-
-          ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz
-          ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz
-
-These tools are not ALPHA but quite clean and work quite well.
-It is essential you have the 'scsiinfo' package.
-
-This short documentation describes the features of the generic and enhanced
-drivers, configuration parameters and control commands available through 
-the proc SCSI file system read / write operations.
-
-This driver has been tested OK with linux/i386, Linux/Alpha and Linux/PPC.
-
-Latest driver version and patches are available at:
-
-          ftp://ftp.tux.org/pub/people/gerard-roudier
-or
-          ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers
-
-I am not a native speaker of English and there are probably lots of
-mistakes in this README file. Any help will be welcome.
-
-
-2. Supported chips and SCSI features
-
-The following features are supported for all chips:
-
-	Synchronous negotiation
-	Disconnection
-	Tagged command queuing
-	SCSI parity checking
-	Master parity checking
-
-"Wide negotiation" is supported for chips that allow it.  The
-following table shows some characteristics of NCR 8xx family chips 
-and what drivers support them.
-
-                                                  Supported by   Supported by
-       On board                                   the generic    the enhanced 
-Chip   SDMS BIOS   Wide   SCSI std.   Max. sync   driver         driver
-----   ---------   ----   ---------   ----------  ------------   -------------
-810        N         N      FAST10    10 MB/s        Y             N
-810A       N         N      FAST10    10 MB/s        Y             Y
-815        Y         N      FAST10    10 MB/s        Y             N
-825        Y         Y      FAST10    20 MB/s        Y             N
-825A       Y         Y      FAST10    20 MB/s        Y             Y
-860        N         N      FAST20    20 MB/s        Y             Y
-875        Y         Y      FAST20    40 MB/s        Y             Y
-876        Y         Y      FAST20    40 MB/s        Y             Y
-895        Y         Y      FAST40    80 MB/s        Y             Y
-895A       Y         Y      FAST40    80 MB/s        Y             Y
-896        Y         Y      FAST40    80 MB/s        Y             Y
-897        Y         Y      FAST40    80 MB/s        Y             Y
-1510D      Y         Y      FAST40    80 MB/s        Y             Y
-1010       Y         Y      FAST80   160 MB/s        N             Y
-1010_66*   Y         Y      FAST80   160 MB/s        N             Y
-
-* Chip supports 33MHz and 66MHz PCI buses.
-
-
-Summary of other supported features:
-
-Module:                allow to load the driver
-Memory mapped I/O:     increases performance
-Profiling information: read operations from the proc SCSI file system
-Control commands:      write operations to the proc SCSI file system
-Debugging information: written to syslog (expert only)
-Scatter / gather
-Shared interrupt
-Boot setup commands
-Serial NVRAM:          Symbios and Tekram formats
-
-
-3. Advantages of the enhanced 896 driver
-
-3.1 Optimized SCSI SCRIPTS.
-
-The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions 
-named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register 
-to/from memory much faster that the MOVE MEMORY instruction that is supported 
-by the 53c7xx and 53c8xx family.
-The LOAD/STORE instructions support absolute and DSA relative addressing 
-modes.  The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead 
-of MOVE MEMORY instructions.
-
-3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller)
-
-The 896 and the 895A allows handling of the phase mismatch context from 
-SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor 
-until the C code has saved the context of the transfer).
-Implementing this without using LOAD/STORE instructions would be painfull 
-and I did'nt even want to try it.
-
-The 896 chip supports 64 bit PCI transactions and addressing, while the 
-895A supports 32 bit PCI transactions and 64 bit addressing.
-The SCRIPTS processor of these chips is not true 64 bit, but uses segment 
-registers for bit 32-63. Another interesting feature is that LOAD/STORE 
-instructions that address the on-chip RAM (8k) remain internal to the chip.
-
-Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not 
-support the following chips:
-- SYM53C810 revision < 0x10 (16)
-- SYM53C815 all revisions
-- SYM53C825 revision < 0x10 (16)
-
-4. Memory mapped I/O versus normal I/O
-
-Memory mapped I/O has less latency than normal I/O.  Since
-linux-1.3.x, memory mapped I/O is used rather than normal I/O.  Memory
-mapped I/O seems to work fine on most hardware configurations, but
-some poorly designed motherboards may break this feature.
-
-The configuration option CONFIG_SCSI_NCR53C8XX_IOMAPPED forces the
-driver to use normal I/O in all cases.
-
-
-5. Tagged command queueing
-
-Queuing more than 1 command at a time to a device allows it to perform 
-optimizations based on actual head positions and its mechanical 
-characteristics. This feature may also reduce average command latency.
-In order to really gain advantage of this feature, devices must have 
-a reasonnable cache size (No miracle is to be expected for a low-end 
-hard disk with 128 KB or less).
-Some kown SCSI devices do not properly support tagged command queuing.
-Generally, firmware revisions that fix this kind of problems are available 
-at respective vendor web/ftp sites.
-All I can say is that the hard disks I use on my machines behave well with 
-this driver with tagged command queuing enabled:
-
-- IBM S12 0662
-- Conner 1080S
-- Quantum Atlas I
-- Quantum Atlas II
-
-If your controller has NVRAM, you can configure this feature per target 
-from the user setup tool. The Tekram Setup program allows to tune the 
-maximum number of queued commands up to 32. The Symbios Setup only allows 
-to enable or disable this feature.
-
-The maximum number of simultaneous tagged commands queued to a device
-is currently set to 8 by default.  This value is suitable for most SCSI
-disks.  With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
-<= 10 ms), using a larger value may give better performances.
-
-The sym53c8xx driver supports up to 255 commands per device, and the 
-generic ncr53c8xx driver supports up to 64, but using more than 32 is 
-generally not worth-while, unless you are using a very large disk or disk 
-array. It is noticeable that most of recent hard disks seem not to accept 
-more than 64 simultaneous commands. So, using more than 64 queued commands 
-is probably just resource wasting.
-
-If your controller does not have NVRAM or if it is managed by the SDMS 
-BIOS/SETUP, you can configure tagged queueing feature and device queue 
-depths from the boot command-line. For example:
-
-  ncr53c8xx=tags:4/t2t3q15-t4q7/t1u0q32
-
-will set tagged commands queue depths as follow:
-
-- target 2  all luns  on controller 0 --> 15
-- target 3  all luns  on controller 0 --> 15
-- target 4  all luns  on controller 0 -->  7
-- target 1  lun 0     on controller 1 --> 32
-- all other target/lun                -->  4
-
-In some special conditions, some SCSI disk firmwares may return a
-QUEUE FULL status for a SCSI command. This behaviour is managed by the
-driver using the following heuristic:
-
-- Each time a QUEUE FULL status is returned, tagged queue depth is reduced 
-  to the actual number of disconnected commands. 
-
-- Every 1000 successfully completed SCSI commands, if allowed by the
-  current limit, the maximum number of queueable commands is incremented.
-
-Since QUEUE FULL status reception and handling is resource wasting, the 
-driver notifies by default this problem to user by indicating the actual 
-number of commands used and their status, as well as its decision on the 
-device queue depth change.
-The heuristic used by the driver in handling QUEUE FULL ensures that the 
-impact on performances is not too bad. You can get rid of the messages by 
-setting verbose level to zero, as follow:
-
-1st method: boot your system using 'ncr53c8xx=verb:0' option.
-2nd method: apply "setverbose 0" control command to the proc fs entry 
-            corresponding to your controller after boot-up.
-
-6. Parity checking
-
-The driver supports SCSI parity checking and PCI bus master parity
-checking.  These features must be enabled in order to ensure safe data
-transfers.  However, some flawed devices or mother boards will have
-problems with parity. You can disable either PCI parity or SCSI parity 
-checking by entering appropriate options from the boot command line.
-(See 10: Boot setup commands).
-
-7. Profiling information
-
-Profiling information is available through the proc SCSI file system.
-Since gathering profiling information may impact performances, this 
-feature is disabled by default and requires a compilation configuration 
-option to be set to Y.
-
-The device associated with a host has the following pathname:
-
-          /proc/scsi/ncr53c8xx/N     (N=0,1,2 ....)
-
-Generally, only 1 board is used on hardware configuration, and that device is:
-          /proc/scsi/ncr53c8xx/0
-
-However, if the driver has been made as module, the number of the
-hosts is incremented each time the driver is loaded.
-
-In order to display profiling information, just enter:
-
-         cat /proc/scsi/ncr53c8xx/0
-
-and you will get something like the following text:
-
--------------------------------------------------------
-General information:
-  Chip NCR53C810, device id 0x1, revision id 0x2
-  IO port address 0x6000, IRQ number 10
-  Using memory mapped IO at virtual address 0x282c000
-  Synchronous transfer period 25, max commands per lun 4
-Profiling information:
-  num_trans    = 18014
-  num_kbytes   = 671314
-  num_disc     = 25763
-  num_break    = 1673
-  num_int      = 1685
-  num_fly      = 18038
-  ms_setup     = 4940
-  ms_data      = 369940
-  ms_disc      = 183090
-  ms_post      = 1320
--------------------------------------------------------
-
-General information is easy to understand. The device ID and the
-revision ID identify the SCSI chip as follows:
-
-Chip    Device id     Revision Id
-----    ---------     -----------
-810       0x1            <  0x10
-810A      0x1            >= 0x10
-815       0x4
-825       0x3            <  0x10
-860       0x6
-825A      0x3            >= 0x10
-875       0xf
-895       0xc
-
-The profiling information is updated upon completion of SCSI commands.
-A data structure is allocated and zeroed when the host adapter is
-attached. So, if the driver is a module, the profile counters are
-cleared each time the driver is loaded.  The "clearprof" command
-allows you to clear these counters at any time.
-
-The following counters are available:
-
-("num" prefix means "number of",
-"ms" means milli-seconds)
-
-num_trans
-	Number of completed commands
-	Example above: 18014 completed commands
-
-num_kbytes
-	Number of kbytes transferred
-	Example above: 671 MB transferred
-
-num_disc
-	Number of SCSI disconnections
-	Example above: 25763 SCSI disconnections
-
-num_break
-	number of script interruptions (phase mismatch)
-	Example above: 1673 script interruptions
-
-num_int
-	Number of interrupts other than "on the fly"
-	Example above: 1685 interruptions not "on the fly"
-
-num_fly
-	Number of interrupts "on the fly"
-	Example above: 18038 interruptions "on the fly"
-
-ms_setup
-	Elapsed time for SCSI commands setups
-	Example above: 4.94 seconds
-
-ms_data
-	Elapsed time for data transfers
-	Example above: 369.94 seconds spent for data transfer
-
-ms_disc
-	Elapsed time for SCSI disconnections
-	Example above: 183.09 seconds spent disconnected
-
-ms_post
-	Elapsed time for command post processing
-	(time from SCSI status get to command completion call)
-	Example above: 1.32 seconds spent for post processing
-
-Due to the 1/100 second tick of the system clock, "ms_post" time may
-be wrong.
-
-In the example above, we got 18038 interrupts "on the fly" and only
-1673 script breaks generally due to disconnections inside a segment 
-of the scatter list.
-
-
-8. Control commands
-
-Control commands can be sent to the driver with write operations to
-the proc SCSI file system. The generic command syntax is the
-following:
-
-      echo "<verb> <parameters>" >/proc/scsi/ncr53c8xx/0
-      (assumes controller number is 0)
-
-Using "all" for "<target>" parameter with the commands below will
-apply to all targets of the SCSI chain (except the controller).
-
-Available commands:
-
-8.1 Set minimum synchronous period factor
-
-    setsync <target> <period factor>
-
-    target:    target number
-    period:    minimum synchronous period.
-               Maximum speed = 1000/(4*period factor) except for special
-               cases below.
-
-    Specify a period of 255, to force asynchronous transfer mode.
-
-      10 means 25 nano-seconds synchronous period
-      11 means 30 nano-seconds synchronous period
-      12 means 50 nano-seconds synchronous period
-
-8.2 Set wide size
-
-    setwide <target> <size>
-
-    target:    target number
-    size:      0=8 bits, 1=16bits
-
-8.3 Set maximum number of concurrent tagged commands
- 
-    settags <target> <tags>
-
-    target:    target number
-    tags:      number of concurrent tagged commands
-               must not be greater than SCSI_NCR_MAX_TAGS (default: 8)
-
-8.4 Set order type for tagged command
-
-    setorder <order>
-
-    order:     3 possible values:
-               simple: use SIMPLE TAG for all operations (read and write)
-               ordered: use ORDERED TAG for all operations
-               default: use default tag type,
-                        SIMPLE  TAG for read  operations
-                        ORDERED TAG for write operations
-
-
-8.5 Set debug mode
-
-    setdebug <list of debug flags>
-
-    Available debug flags:
-        alloc:   print info about memory allocations (ccb, lcb)
-        queue:   print info about insertions into the command start queue
-        result:  print sense data on CHECK CONDITION status
-        scatter: print info about the scatter process
-        scripts: print info about the script binding process
-	tiny:    print minimal debugging information
-	timing:  print timing information of the NCR chip
-	nego:    print information about SCSI negotiations
-	phase:   print information on script interruptions
-
-    Use "setdebug" with no argument to reset debug flags.
-
-
-8.6 Clear profile counters
-
-    clearprof
-
-    The profile counters are automatically cleared when the amount of
-    data transferred reaches 1000 GB in order to avoid overflow.
-    The "clearprof" command allows you to clear these counters at any time.
-
-
-8.7 Set flag (no_disc)
- 
-    setflag <target> <flag>
-
-    target:    target number
-
-    For the moment, only one flag is available:
-
-        no_disc:   not allow target to disconnect.
-
-    Do not specify any flag in order to reset the flag. For example:
-    - setflag 4
-      will reset no_disc flag for target 4, so will allow it disconnections.
-    - setflag all
-      will allow disconnection for all devices on the SCSI bus.
-
-
-8.8 Set verbose level
-
-    setverbose #level
-
-    The driver default verbose level is 1. This command allows to change 
-    th driver verbose level after boot-up.
-
-8.9 Reset all logical units of a target
-
-    resetdev <target>
-
-    target:    target number
-    The driver will try to send a BUS DEVICE RESET message to the target.
-    (Only supported by the SYM53C8XX driver and provided for test purpose)
-
-8.10 Abort all tasks of all logical units of a target
-
-    cleardev <target>
-
-    target:    target number
-    The driver will try to send a ABORT message to all the logical units 
-    of the target.
-    (Only supported by the SYM53C8XX driver and provided for test purpose)
-
-
-9. Configuration parameters
-
-If the firmware of all your devices is perfect enough, all the
-features supported by the driver can be enabled at start-up.  However,
-if only one has a flaw for some SCSI feature, you can disable the
-support by the driver of this feature at linux start-up and enable
-this feature after boot-up only for devices that support it safely.
-
-CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT  (default answer: n)
-    This option must be set for profiling information to be gathered 
-    and printed out through the proc file system. This features may 
-    impact performances.
-
-CONFIG_SCSI_NCR53C8XX_IOMAPPED       (default answer: n)
-    Answer "y" if you suspect your mother board to not allow memory mapped I/O.
-    May slow down performance a little.  This option is required by
-    Linux/PPC and is used no matter what you select here.  Linux/PPC
-    suffers no performance loss with this option since all IO is memory
-    mapped anyway.
-
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS    (default answer: 8)
-    Default tagged command queue depth.
-
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS         (default answer: 8)
-    This option allows you to specify the maximum number of tagged commands 
-    that can be queued to a device. The maximum supported value is 32.
-
-CONFIG_SCSI_NCR53C8XX_SYNC            (default answer: 5)
-    This option allows you to specify the frequency in MHz the driver 
-    will use at boot time for synchronous data transfer negotiations.
-    This frequency can be changed later with the "setsync" control command.
-    0 means "asynchronous data transfers".
-
-CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO (default answer: n)
-    Force synchronous negotiation for all SCSI-2 devices.
-    Some SCSI-2 devices do not report this feature in byte 7 of inquiry 
-    response but do support it properly (TAMARACK scanners for example).
-
-CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT   (default and only reasonnable answer: n)
-    If you suspect a device of yours does not properly support disconnections,
-    you can answer "y". Then, all SCSI devices will never disconnect the bus 
-    even while performing long SCSI operations.
-
-CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
-    Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 
-    bit as a flag indicating singled-ended/differential interface.
-    If all the boards of your system are genuine SYMBIOS boards or use
-    BIOS and drivers from SYMBIOS, you would want to enable this option.
-    This option must NOT be enabled if your system has at least one 53C8XX 
-    based scsi board with a vendor-specific BIOS.
-    For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers 
-    use a vendor-specific BIOS and are known to not use SYMBIOS compatible 
-    GPIO wiring. So, this option must not be enabled if your system has 
-    such a board installed.
-
-CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-    Enable support for reading the serial NVRAM data on Symbios and
-    some Symbios compatible cards, and Tekram DC390W/U/F cards. Useful for
-    systems with more than one Symbios compatible controller where at least
-    one has a serial NVRAM, or for a system with a mixture of Symbios and
-    Tekram cards. Enables setting the boot order of host adaptors
-    to something other than the default order or "reverse probe" order. 
-    Also enables Symbios and Tekram cards to be distinguished so
-    CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in a system with a
-    mixture of Symbios and Tekram cards so the Symbios cards can make use of
-    the full range of Symbios features, differential, led pin, without
-    causing problems for the Tekram card(s).
-
-10. Boot setup commands
-
-10.1 Syntax
-
-Setup commands can be passed to the driver either at boot time or as a 
-string variable using 'insmod'.
-
-A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the 
-driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects 
-an optionnal list of integers separated with comma followed by an optional 
-list of  comma-separated strings. Example of boot setup command under lilo 
-prompt:
-
-lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200
-
-- enable tagged commands, up to 4 tagged commands queued.
-- set synchronous negotiation speed to 10 Mega-transfers / second.
-- set DEBUG_NEGO flag.
-
-Since comma seems not to be allowed when defining a string variable using  
-'insmod', the driver also accepts <space> as option separator. 
-The following command will install driver module with the same options as 
-above.
-
-    insmod ncr53c8xx.o ncr53c8xx="tags:4 sync:10 debug:0x200"
-
-For the moment, the integer list of arguments is discarded by the driver. 
-It will be used in the future in order to allow a per controller setup.
-
-Each string argument must be specified as "keyword:value". Only lower-case 
-characters and digits are allowed.
-
-In a system that contains multiple 53C8xx adapters insmod will install the 
-specified driver on each adapter. To exclude a chip use the 'excl' keyword.
-
-The sequence of commands, 
-
-    insmod sym53c8xx sym53c8xx=excl:0x1400
-    insmod ncr53c8xx
-
-installs the sym53c8xx driver on all adapters except the one at IO port 
-address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO 
-port address 0x1400.
-
-
-10.2 Available arguments
-
-10.2.1  Master parity checking
-        mpar:y     enabled
-        mpar:n     disabled
-
-10.2.2  Scsi parity checking
-        spar:y     enabled
-        spar:n     disabled
-
-10.2.3  Scsi disconnections
-        disc:y     enabled
-        disc:n     disabled
- 
-10.2.4  Special features
-   Only apply to 810A, 825A, 860, 875 and 895 controllers.
-   Have no effect with other ones.
-        specf:y    (or 1) enabled
-        specf:n    (or 0) disabled
-        specf:3           enabled except Memory Write And Invalidate
-   The default driver setup is 'specf:3'. As a consequence, option 'specf:y' 
-   must be specified in the boot setup command to enable Memory Write And 
-   Invalidate.
-
-10.2.5  Ultra SCSI support
-   Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers.
-   Have no effect with other ones.
-        ultra:n    All ultra speeds enabled
-        ultra:2    Ultra2 enabled
-        ultra:1    Ultra enabled
-        ultra:0    Ultra speeds disabled
-
-10.2.6  Default number of tagged commands
-        tags:0     (or tags:1 ) tagged command queuing disabled
-        tags:#tags (#tags  > 1) tagged command queuing enabled
-  #tags will be truncated to the max queued commands configuration parameter.
-  This option also allows to specify a command queue depth for each device 
-  that support tagged command queueing.
-  Example:
-      ncr53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
-               will set devices queue depth as follow:
-      - controller #0 target #2 and target #3                  -> 16 commands,
-      - controller #0 target #5                                -> 24 commands,
-      - controller #1 target #1 logical unit #2                -> 32 commands,
-      - all other logical units (all targets, all controllers) -> 10 commands.
-
-10.2.7  Default synchronous period factor
-        sync:255     disabled (asynchronous transfer mode)
-        sync:#factor
-  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
-  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
-  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
-  #factor < 50     Fast    SCSI-2
-
-  In all cases, the driver will use the minimum transfer period supported by 
-  controllers according to NCR53C8XX chip type.
-
-10.2.8  Negotiate synchronous with all devices
-        (force sync nego)
-        fsn:y      enabled
-        fsn:n      disabled
-
-10.2.9  Verbosity level
-        verb:0     minimal
-        verb:1     normal
-        verb:2     too much
-
-10.2.10 Debug mode
-        debug:0	 clear debug flags
-        debug:#x   set debug flags
-  #x is an integer value combining the following power-of-2 values:
-  DEBUG_ALLOC       0x1
-  DEBUG_PHASE       0x2
-  DEBUG_POLL        0x4
-  DEBUG_QUEUE       0x8
-  DEBUG_RESULT     0x10
-  DEBUG_SCATTER    0x20
-  DEBUG_SCRIPT     0x40
-  DEBUG_TINY       0x80
-  DEBUG_TIMING    0x100
-  DEBUG_NEGO      0x200
-  DEBUG_TAGS      0x400
-  DEBUG_FREEZE    0x800
-  DEBUG_RESTART  0x1000
-
-  You can play safely with DEBUG_NEGO. However, some of these flags may 
-  generate bunches of syslog messages. 
-
-10.2.11 Burst max
-        burst:0    burst disabled
-        burst:255  get burst length from initial IO register settings.
-        burst:#x   burst enabled (1<<#x burst transfers max)
-  #x is an integer value which is log base 2 of the burst transfers max.
-  The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7).
-  Other chips only support up to 16 (#x = 4).
-  This is a maximum value. The driver set the burst length according to chip 
-  and revision ids. By default the driver uses the maximum value supported 
-  by the chip.
-
-10.2.12 LED support
-        led:1      enable  LED support
-        led:0      disable LED support
-  Donnot enable LED support if your scsi board does not use SDMS BIOS.
-  (See 'Configuration parameters')
-
-10.2.13 Max wide
-        wide:1      wide scsi enabled
-        wide:0      wide scsi disabled
-  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
-  If you have connected a wide device with a 50 pins to 68 pins cable 
-  converter, any accepted wide negotiation will break further data transfers.
-  In such a case, using "wide:0" in the bootup command will be helpfull. 
-
-10.2.14 Differential mode
-        diff:0	never set up diff mode
-        diff:1	set up diff mode if BIOS set it
-        diff:2	always set up diff mode
-        diff:3	set diff mode if GPIO3 is not set
-
-10.2.15 IRQ mode
-        irqm:0     always open drain
-        irqm:1     same as initial settings (assumed BIOS settings)
-        irqm:2     always totem pole
-        irqm:0x10  driver will not use SA_SHIRQ flag when requesting irq
-        irqm:0x20  driver will not use SA_INTERRUPT flag when requesting irq
-
-    (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
-
-10.2.16 Reverse probe
-        revprob:n   probe chip ids from the PCI configuration in this order:
-                    810, 815, 820, 860, 875, 885, 895, 896
-        revprob:y   probe chip ids in the reverse order.
-
-10.2.17 Fix up PCI configuration space
-        pcifix:<option bits>
-
-    Available option bits:
-        0x0:   No attempt to fix PCI configuration space registers values.
-        0x1:   Set PCI cache-line size register if not set.
-        0x2:   Set write and invalidate bit in PCI command register.
-        0x4:   Increase if necessary PCI latency timer according to burst max.
-
-    Use 'pcifix:7' in order to allow the driver to fix up all PCI features.
-
-10.2.18 Serial NVRAM
-        nvram:n     do not look for serial NVRAM
-        nvram:y     test controllers for onboard serial NVRAM
-        (alternate binary form)
-        mvram=<bits options>
-        0x01   look for NVRAM  (equivalent to nvram=y)
-        0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-        0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-        0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-        0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-10.2.19 Check SCSI BUS 
-        buschk:<option bits>
-
-    Available option bits:
-        0x0:   No check.
-        0x1:   Check and donnot attach the controller on error.  
-        0x2:   Check and just warn on error.
-        0x4:   Disable SCSI bus integrity checking.
-
-10.2.20 Exclude a host from being attached
-        excl=<io_address>
-
-    Prevent host at a given io address from being attached.
-    For example 'ncr53c8xx=excl:0xb400,excl:0xc000' indicate to the 
-    ncr53c8xx driver not to attach hosts at address 0xb400 and 0xc000.
-
-10.2.21 Suggest a default SCSI id for hosts
-        hostid:255	no id suggested.
-        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
-
-    If a host SCSI id is available from the NVRAM, the driver will ignore 
-    any value suggested as boot option. Otherwise, if a suggested value 
-    different from 255 has been supplied, it will use it. Otherwise, it will 
-    try to deduce the value previously set in the hardware and use value 
-    7 if the hardware value is zero.
-
-10.2.22 Enable use of IMMEDIATE ARBITRATION
-        (only supported by the sym53c8xx driver. See 10.7 for more details)
-        iarb:0    donnot use this feature.
-        iarb:#x   use this feature according to bit fields as follow:
-
-    bit 0 (1) : enable IARB each time the initiator has been reselected 
-                when it arbitrated for the SCSI BUS.
-    (#x >> 4) : maximum number of successive settings of IARB if the initiator 
-                win arbitration and it has other commands to send to a device.
-
-Boot fail safe
-    safe:y	load the following assumed fail safe initial setup
-
-  master parity			disabled		mpar:n
-  scsi parity			enabled			spar:y
-  disconnections		not allowed		disc:n
-  special features		disabled		specf:n
-  ultra scsi			disabled		ultra:n
-  force sync negotiation	disabled		fsn:n
-  reverse probe			disabled		revprob:n
-  PCI fix up                    disabled                pcifix:0
-  serial NVRAM                  enabled                 nvram:y
-  verbosity level		2			verb:2
-  tagged command queuing	disabled		tags:0
-  synchronous negotiation	disabled		sync:255
-  debug flags			none			debug:0
-  burst length			from BIOS settings	burst:255
-  LED support			disabled		led:0
-  wide support			disabled		wide:0
-  settle time			10 seconds		settle:10
-  differential support		from BIOS settings	diff:1
-  irq mode			from BIOS settings	irqm:1
-  SCSI BUS check		donnot attach on error	buschk:1
-  immediate arbitration		disabled		iarb:0
-
-10.3 Advised boot setup commands
-
-If the driver has been configured with default options, the equivalent 
-boot setup is:
-
-   ncr53c8xx=mpar:y,spar:y,disc:y,specf:3,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\
-             tags:0,sync:50,debug:0,burst:7,led:0,wide:1,settle:2,diff:0,irqm:0
-
-For an installation diskette or a safe but not fast system,
-boot setup can be:
-
-    ncr53c8xx=safe:y,mpar:y,disc:y
-    ncr53c8xx=safe:y,disc:y
-    ncr53c8xx=safe:y,mpar:y
-    ncr53c8xx=safe:y
-
-My personnal system works flawlessly with the following equivalent setup:
-
-   ncr53c8xx=mpar:y,spar:y,disc:y,specf:1,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\
-             tags:32,sync:12,debug:0,burst:7,led:1,wide:1,settle:2,diff:0,irqm:0
-
-The driver prints its actual setup when verbosity level is 2. You can try 
-"ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" 
-to your boot setup command in order to check the actual setup the driver is 
-using.
-
-10.4 PCI configuration fix-up boot option
-
-pcifix:<option bits>
-
-Available option bits:
-    0x1:     Set PCI cache-line size register if not set.
-    0x2:     Set write and invalidate bit in PCI command register.
-
-Use 'pcifix:3' in order to allow the driver to fix both PCI features.
-
-These options only apply to new SYMBIOS chips 810A, 825A, 860, 875 
-and 895 and are only supported for Pentium and 486 class processors.
-Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
-and PCI write and invalidate commands. These features require the 
-cache line size register to be properly set in the PCI configuration 
-space of the chips. On the other hand, chips will use PCI write and 
-invalidate commands only if the corresponding bit is set to 1 in the 
-PCI command register.
-
-Not all PCI bioses set the PCI cache line register and the PCI write and 
-invalidate bit in the PCI configuration space of 53C8XX chips.
-Optimized PCI accesses may be broken for some PCI/memory controllers or 
-make problems with some PCI boards.
-
-This fix-up worked flawlessly on my previous system.
-(MB Triton HX / 53C875 / 53C810A)
-I use these options at my own risks as you will do if you decide to 
-use them too.
-
-
-10.5 Serial NVRAM support boot option
-
-nvram:n     do not look for serial NVRAM
-nvram:y     test controllers for onboard serial NVRAM
-
-This option can also been entered as an hexadecimal value that allows 
-to control what information the driver will get from the NVRAM and what 
-information it will ignore.
-For details see '17. Serial NVRAM support'.
-
-When this option is enabled, the driver tries to detect all boards using 
-a Serial NVRAM. This memory is used to hold user set up parameters.
-
-The parameters the driver is able to get from the NVRAM depend on the 
-data format used, as follow:
-
-                                 Tekram format      Symbios format
-General and host parameters
-    Boot order                         N                   Y
-    Host SCSI ID                       Y                   Y
-    SCSI parity checking               Y                   Y
-    Verbose boot messages              N                   Y
-SCSI devices parameters
-    Synchronous transfer speed         Y                   Y
-    Wide 16 / Narrow                   Y                   Y
-    Tagged Command Queuing enabled     Y                   Y
-    Disconnections enabled             Y                   Y
-    Scan at boot time                  N                   Y
-
-In order to speed up the system boot, for each device configured without 
-the "scan at boot time" option, the driver forces an error on the 
-first TEST UNIT READY command received for this device.
-
-Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
-hard disks. In such a situation you cannot configure the NVRAM with 
-optimized parameters value.
-
-The 'nvram' boot option can be entered in hexadecimal form in order 
-to ignore some options configured in the NVRAM, as follow:
-
-mvram=<bits options>
-      0x01   look for NVRAM  (equivalent to nvram=y)
-      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-Option 0x80 is only supported by the sym53c8xx driver and is disabled by 
-default. Result is that, by default (option not set), the sym53c8xx driver 
-will not attach controllers set to OFF in the NVRAM.
-
-The ncr53c8xx always tries to attach all the controllers. Option 0x80 has 
-not been added to the ncr53c8xx driver, since it has been reported to 
-confuse users who use this driver since a long time. If you desire a 
-controller not to be attached by the ncr53c8xx driver at Linux boot, you 
-must use the 'excl' driver boot option.
-
-10.6 SCSI BUS checking boot option.
-
-When this option is set to a non-zero value, the driver checks SCSI lines 
-logic state, 100 micro-seconds after having asserted the SCSI RESET line.
-The driver just reads SCSI lines and checks all lines read FALSE except RESET.
-Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI 
-RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
-Unfortunately, the following common SCSI BUS problems are not detected:
-- Only 1 terminator installed.
-- Misplaced terminators.
-- Bad quality terminators.
-On the other hand, either bad cabling, broken devices, not conformant 
-devices, ... may cause a SCSI signal to be wrong when te driver reads it.
-
-10.7 IMMEDIATE ARBITRATION boot option
-
-This option is only supported by the SYM53C8XX driver (not by the NCR53C8XX).
-
-SYMBIOS 53C8XX chips are able to arbitrate for the SCSI BUS as soon as they 
-have detected an expected disconnection (BUS FREE PHASE). For this process 
-to be started, bit 1 of SCNTL1 IO register must be set when the chip is 
-connected to the SCSI BUS.
-
-When this feature has been enabled for the current connection, the chip has 
-every chance to win arbitration if only devices with lower priority are 
-competing for the SCSI BUS. By the way, when the chip is using SCSI id 7, 
-then it will for sure win the next SCSI BUS arbitration.
-
-Since, there is no way to know what devices are trying to arbitrate for the 
-BUS, using this feature can be extremally unfair. So, you are not advised 
-to enable it, or at most enable this feature for the case the chip lost 
-the previous arbitration (boot option 'iarb:1').
-
-This feature has the following advantages:
-
-a) Allow the initiator with ID 7 to win arbitration when it wants so.
-b) Overlap at least 4 micro-seconds of arbitration time with the execution 
-   of SCRIPTS that deal with the end of the current connection and that 
-   starts the next job.
-
-Hmmm... But (a) may just prevent other devices from reselecting the initiator, 
-and delay data transfers or status/completions, and (b) may just waste 
-SCSI BUS bandwidth if the SCRIPTS execution lasts more than 4 micro-seconds.
-
-The use of IARB needs the SCSI_NCR_IARB_SUPPORT option to have been defined 
-at compile time and the 'iarb' boot option to have been set to a non zero 
-value at boot time. It is not that useful for real work, but can be used 
-to stress SCSI devices or for some applications that can gain advantage of 
-it. By the way, if you experience badnesses like 'unexpected disconnections', 
-'bad reselections', etc... when using IARB on heavy IO load, you should not 
-be surprised, because force-feeding anything and blocking its arse at the 
-same time cannot work for a long time. :-))
-
-
-11. Some constants and flags of the ncr53c8xx.h header file
-
-Some of these are defined from the configuration parameters.  To
-change other "defines", you must edit the header file.  Do that only
-if you know what you are doing.
-
-SCSI_NCR_SETUP_SPECIAL_FEATURES	(default: defined)
-	If defined, the driver will enable some special features according  
-	to chip and revision id.
-        For 810A, 860, 825A, 875 and 895 scsi chips, this option enables 
-	support of features that reduce load of PCI bus and memory accesses 
-	during  scsi transfer processing: burst op-code fetch, read multiple, 
-        read line, prefetch, cache line, write and invalidate, 
-        burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only).
-	Can be changed by the following boot setup command:
-		ncr53c8xx=specf:n
-
-SCSI_NCR_IOMAPPED		(default: not defined)
-	If defined, normal I/O is forced.
-
-SCSI_NCR_SHARE_IRQ		(default: defined)
-	If defined, request shared IRQ.
-	
-SCSI_NCR_MAX_TAGS		(default: 8)
-	Maximum number of simultaneous tagged commands to a device.
-	Can be changed by "settags <target> <maxtags>"
-
-SCSI_NCR_SETUP_DEFAULT_SYNC     (default: 50)
-	Transfer period factor the driver will use at boot time for synchronous 
-	negotiation. 0 means asynchronous.
-	Can be changed by "setsync <target> <period factor>"
-
-SCSI_NCR_SETUP_DEFAULT_TAGS     (default: 8)
-	Default number of simultaneous tagged commands to a device.
-	< 1 means tagged command queuing disabled at start-up.
-
-SCSI_NCR_ALWAYS_SIMPLE_TAG	(default: defined)
-	Use SIMPLE TAG for read and write commands.
-	Can be changed by "setorder <ordered|simple|default>"
-
-SCSI_NCR_SETUP_DISCONNECTION	(default: defined)
-	If defined, targets are allowed to disconnect.
-
-SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(default: not defined)
-	If defined, synchronous negotiation is tried for all SCSI-2 devices.
-	Can be changed by "setsync <target> <period>"
-
-SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
-	If defined, master parity checking is enabled.
-
-SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
-	If defined, SCSI parity checking is enabled.
-
-SCSI_NCR_PROFILE_SUPPORT	(default: not defined)
-	If defined, profiling information is gathered.
-
-SCSI_NCR_MAX_SCATTER		(default: 128)
-	Scatter list size of the driver ccb.
-
-SCSI_NCR_MAX_TARGET		(default: 16)
-	Max number of targets per host.
-
-SCSI_NCR_MAX_HOST		(default: 2)
-	Max number of host controllers.
-
-SCSI_NCR_SETTLE_TIME		(default: 2)
-	Number of seconds the driver will wait after reset.
-
-SCSI_NCR_TIMEOUT_ALERT		(default: 3)
-	If a pending command will time out after this amount of seconds,
-	an ordered tag is used for the next command.
-	Avoids timeouts for unordered tagged commands.
-
-SCSI_NCR_CAN_QUEUE		(default: 7*SCSI_NCR_MAX_TAGS)
-	Max number of commands that can be queued to a host.
-
-SCSI_NCR_CMD_PER_LUN		(default: SCSI_NCR_MAX_TAGS)
-	Max number of commands queued to a host for a device.
-
-SCSI_NCR_SG_TABLESIZE		(default: SCSI_NCR_MAX_SCATTER-1)
-	Max size of the Linux scatter/gather list.
-
-SCSI_NCR_MAX_LUN	(default: 8)
-	Max number of LUNs per target.
-
-
-12. Installation
-
-This driver is part of the linux kernel distribution.
-Driver files are located in the sub-directory "drivers/scsi" of the 
-kernel source tree.
-
-Driver files:
-
-	README.ncr53c8xx	: this file
-	ChangeLog.ncr53c8xx	: change log
-	ncr53c8xx.h		: definitions
-	ncr53c8xx.c		: the driver code
-
-New driver versions are made available separately in order to allow testing 
-changes and new features prior to including them into the linux kernel 
-distribution. The following URL provides informations on latest avalaible 
-patches: 
-
-      ftp://ftp.tux.org/pub/people/gerard-roudier/README
-
-
-13. Architecture dependent features.
-
-<Not yet written>
-
-
-14. Known problems
-
-14.1 Tagged commands with Iomega Jaz device
-
-I have not tried this device, however it has been reported to me the
-following: This device is capable of Tagged command queuing. However
-while spinning up, it rejects Tagged commands. This behaviour is
-conforms to 6.8.2 of SCSI-2 specifications. The current behaviour of
-the driver in that situation is not satisfying. So do not enable
-Tagged command queuing for devices that are able to spin down.  The
-other problem that may appear is timeouts. The only way to avoid
-timeouts seems to edit linux/drivers/scsi/sd.c and to increase the
-current timeout values.
-
-14.2 Device names change when another controller is added.
-
-When you add a new NCR53C8XX chip based controller to a system that already 
-has one or more controllers of this family, it may happen that the order 
-the driver registers them to the kernel causes problems due to device 
-name changes.
-When at least one controller uses NvRAM, SDMS BIOS version 4 allows you to 
-define the order the BIOS will scan the scsi boards. The driver attaches 
-controllers according to BIOS information if NvRAM detect option is set.
-
-If your controllers do not have NvRAM, you can:
-
-- Ask the driver to probe chip ids in reverse order from the boot command
-  line: ncr53c8xx=revprob:y
-- Make appropriate changes in the fstab.
-- Use the 'scsidev' tool from Eric Youngdale.
-
-14.3 Using only 8 bit devices with a WIDE SCSI controller.
-
-When only 8 bit NARROW devices are connected to a 16 bit WIDE SCSI controller, 
-you must ensure that lines of the wide part of the SCSI BUS are pulled-up.
-This can be achieved by ENABLING the WIDE TERMINATOR portion of the SCSI 
-controller card.
-The TYAN 1365 documentation revision 1.2 is not correct about such settings.
-(page 10, figure 3.3).
-
-14.4 Possible data corruption during a Memory Write and Invalidate
-
-This problem is described in SYMBIOS DEL 397, Part Number 69-039241, ITEM 4.
-
-In some complex situations, 53C875 chips revision <= 3 may start a PCI 
-Write and Invalidate Command at a not cache-line-aligned 4 DWORDS boundary.
-This is only possible when Cache Line Size is 8 DWORDS or greater.
-Pentium systems use a 8 DWORDS cache line size and so are concerned by 
-this chip bug, unlike i486 systems that use a 4 DWORDS cache line size.
-
-When this situation occurs, the chip may complete the Write and Invalidate 
-command after having only filled part of the last cache line involved in 
-the transfer, leaving to data corruption the remainder of this cache line.
-
-Not using Write And Invalidate obviously gets rid of this chip bug, and so 
-it is now the default setting of the driver.
-However, for people like me who want to enable this feature, I have added 
-part of a work-around suggested by SYMBIOS. This work-around resets the 
-addressing logic when the DATA IN phase is entered and so prevents the bug 
-from being triggered for the first SCSI MOVE of the phase. This work-around 
-should be enough according to the following:
-
-The only driver internal data structure that is greater than 8 DWORDS  and 
-that is moved by the SCRIPTS processor is the 'CCB header' that contains 
-the context of the SCSI transfer. This data structure is aligned on 8 DWORDS 
-boundary (Pentium Cache Line Size), and so is immune to this chip bug, at 
-least on Pentium systems.
-But the conditions of this bug can be met when a SCSI read command is 
-performed using a buffer that is 4 DWORDS but not cache-line aligned.
-This cannot happen under Linux when scatter/gather lists are used since 
-they only refer to system buffers that are well aligned. So, a work around 
-may only be needed under Linux when a scatter/gather list is not used and 
-when the SCSI DATA IN phase is reentered after a phase mismatch.
-
-14.5 IRQ sharing problems
-
-When an IRQ is shared by devices that are handled by different drivers, it 
-may happen that one driver complains about the request of the IRQ having 
-failed. Inder Linux-2.0, this may be due to one driver having requested the 
-IRQ using the SA_INTERRUPT flag but some other having requested the same IRQ 
-without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by 
-one driver not having requested the IRQ with the SA_SHIRQ flag.
-
-By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the 
-SA_INTERRUPT and the SA_SHIRQ flag under Linux-2.0 and with only the SA_SHIRQ 
-flag under Linux-2.2.
-
-Under Linux-2.0, you can disable use of SA_INTERRUPT flag from the boot 
-command line by using the following option:
-
-     ncr53c8xx=irqm:0x20   (for the generic ncr53c8xx driver)
-     sym53c8xx=irqm:0x20   (for the sym53c8xx driver)
-
-If this does not fix the problem, then you may want to check how all other 
-drivers are requesting the IRQ and report the problem. Note that if at least 
-a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ), 
-then the request of the IRQ obviously will not succeed for all the drivers.
-
-15. SCSI problem troubleshooting
-
-15.1 Problem tracking
-
-Most SCSI problems are due to a non conformant SCSI bus or to buggy
-devices.  If infortunately you have SCSI problems, you can check the
-following things:
-
-- SCSI bus cables
-- terminations at both end of the SCSI chain
-- linux syslog messages (some of them may help you)
-
-If you donnot find the source of problems, you can configure the
-driver with no features enabled.
-
-- only asynchronous data transfers
-- tagged commands disabled
-- disconnections not allowed
-
-Now, if your SCSI bus is ok, your system have every chance to work
-with this safe configuration but performances will not be optimal.
-
-If it still fails, then you can send your problem description to
-appropriate mailing lists or news-groups.  Send me a copy in order to
-be sure I will receive it.  Obviously, a bug in the driver code is
-possible.
-
-     My email address: Gerard Roudier <groudier@free.fr>
-
-Allowing disconnections is important if you use several devices on
-your SCSI bus but often causes problems with buggy devices.
-Synchronous data transfers increases throughput of fast devices like
-hard disks.  Good SCSI hard disks with a large cache gain advantage of
-tagged commands queuing.
-
-Try to enable one feature at a time with control commands.  For example:
-
-- echo "setsync all 25" >/proc/scsi/ncr53c8xx/0
-  Will enable fast synchronous data transfer negotiation for all targets.
-
-- echo "setflag 3" >/proc/scsi/ncr53c8xx/0
-  Will reset flags (no_disc) for target 3, and so will allow it to disconnect 
-  the SCSI Bus.
-
-- echo "settags 3 8" >/proc/scsi/ncr53c8xx/0
-  Will enable tagged command queuing for target 3 if that device supports it.
-
-Once you have found the device and the feature that cause problems, just 
-disable that feature for that device.
-
-15.2 Understanding hardware error reports
-
-When the driver detects an unexpected error condition, it may display a 
-message of the following pattern.
-
-sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000).
-sym53c876-0: script cmd = 19000000
-sym53c876-0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.
-
-Some fields in such a message may help you understand the cause of the 
-problem, as follows:
-
-sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000).
-............A.........B.C....D.E..F....G.H.......I.....J...K.......
-
-Field A : target number.
-  SCSI ID of the device the controller was talking with at the moment the 
-  error occurs.
-
-Field B : DSTAT io register (DMA STATUS)
-  Bit 0x40 : MDPE Master Data Parity Error
-             Data parity error detected on the PCI BUS.
-  Bit 0x20 : BF   Bus Fault
-             PCI bus fault condition detected
-  Bit 0x01 : IID  Illegal Instruction Detected
-             Set by the chip when it detects an Illegal Instruction format 
-             on some condition that makes an instruction illegal.
-  Bit 0x80 : DFE Dma Fifo Empty
-             Pure status bit that does not indicate an error.
-  If the reported DSTAT value contains a combination of MDPE (0x40), 
-  BF (0x20), then the cause may be likely due to a PCI BUS problem.
-
-Field C : SIST io register (SCSI Interrupt Status)
-  Bit 0x08 : SGE  SCSI GROSS ERROR
-             Indicates that the chip detected a severe error condition 
-             on the SCSI BUS that prevents the SCSI protocol from functionning
-             properly.
-  Bit 0x04 : UDC  Undexpected Disconnection
-             Indicates that the device released the SCSI BUS when the chip 
-             was not expecting this to happen. A device may behave so to 
-             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occurred.
-  Bit 0x02 : RST  SCSI BUS Reset
-             Generally SCSI targets donnot reset the SCSI BUS, although any 
-             device on the BUS can reset it at any time.
-  Bit 0x01 : PAR  Parity
-             SCSI parity error detected.
-  On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and 
-  PAR (0x01) may be detected by the chip. If your SCSI system sometimes 
-  encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI 
-  BUS problem is likely the cause of these errors.
-
-For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file 
-that contains some minimal comments on IO register bits.
-Field D : SOCL  Scsi Output Control Latch
-          This register reflects the state of the SCSI control lines the 
-          chip want to drive or compare against.
-Field E : SBCL  Scsi Bus Control Lines
-          Actual value of control lines on the SCSI BUS.
-Field F : SBDL  Scsi Bus Data Lines
-          Actual value of data lines on the SCSI BUS.
-Field G : SXFER  SCSI Transfer
-          Contains the setting of the Synchronous Period for output and 
-          the current Synchronous offset (offset 0 means asynchronous).
-Field H : SCNTL3 Scsi Control Register 3
-          Contains the setting of timing values for both asynchronous and 
-          synchronous data transfers. 
-
-Understanding Fields I, J, K and dumps requires to have good knowledge of 
-SCSI standards, chip cores functionnals and internal driver data structures.
-You are not required to decode and understand them, unless you want to help 
-maintain the driver code.
-
-16. Synchonous transfer negotiation tables
-
-Tables below have been created by calling the routine the driver uses
-for synchronisation negotiation timing calculation and chip setting.
-The first table corresponds to Ultra chips 53875 and 53C860 with 80 MHz 
-clock and 5 clock divisors.
-The second one has been calculated by setting the scsi clock to 40 Mhz 
-and using 4 clock divisors and so applies to all NCR53C8XX chips in fast 
-SCSI-2 mode.
-
-Periods are in nano-seconds and speeds are in Mega-transfers per second.
-1 Mega-transfers/second means 1 MB/s with 8 bits SCSI and 2 MB/s with 
-Wide16 SCSI.
-
-16.1 Synchronous timings for 53C895, 53C875 and 53C860 SCSI controllers
-
- ----------------------------------------------
- Negotiated                     NCR settings
- Factor   Period   Speed        Period   Speed
- ------   ------   ------       ------   ------
- 10       25       40.000       25       40.000   (53C895 only)
- 11       30.2     33.112       31.25    32.000   (53C895 only)
- 12       50       20.000       50       20.000
- 13       52       19.230       62       16.000
- 14       56       17.857       62       16.000
- 15       60       16.666       62       16.000
- 16       64       15.625       75       13.333
- 17       68       14.705       75       13.333
- 18       72       13.888       75       13.333
- 19       76       13.157       87       11.428
- 20       80       12.500       87       11.428
- 21       84       11.904       87       11.428
- 22       88       11.363       93       10.666
- 23       92       10.869       93       10.666
- 24       96       10.416      100       10.000
- 25      100       10.000      100       10.000
- 26      104        9.615      112        8.888
- 27      108        9.259      112        8.888
- 28      112        8.928      112        8.888
- 29      116        8.620      125        8.000
- 30      120        8.333      125        8.000
- 31      124        8.064      125        8.000
- 32      128        7.812      131        7.619
- 33      132        7.575      150        6.666
- 34      136        7.352      150        6.666
- 35      140        7.142      150        6.666
- 36      144        6.944      150        6.666
- 37      148        6.756      150        6.666
- 38      152        6.578      175        5.714
- 39      156        6.410      175        5.714
- 40      160        6.250      175        5.714
- 41      164        6.097      175        5.714
- 42      168        5.952      175        5.714
- 43      172        5.813      175        5.714
- 44      176        5.681      187        5.333
- 45      180        5.555      187        5.333
- 46      184        5.434      187        5.333
- 47      188        5.319      200        5.000
- 48      192        5.208      200        5.000
- 49      196        5.102      200        5.000
-
-
-16.2 Synchronous timings for fast SCSI-2 53C8XX controllers
-
- ----------------------------------------------
- Negotiated                     NCR settings
- Factor   Period   Speed        Period   Speed
- ------   ------   ------       ------   ------
- 25      100       10.000      100       10.000
- 26      104        9.615      125        8.000
- 27      108        9.259      125        8.000
- 28      112        8.928      125        8.000
- 29      116        8.620      125        8.000
- 30      120        8.333      125        8.000
- 31      124        8.064      125        8.000
- 32      128        7.812      131        7.619
- 33      132        7.575      150        6.666
- 34      136        7.352      150        6.666
- 35      140        7.142      150        6.666
- 36      144        6.944      150        6.666
- 37      148        6.756      150        6.666
- 38      152        6.578      175        5.714
- 39      156        6.410      175        5.714
- 40      160        6.250      175        5.714
- 41      164        6.097      175        5.714
- 42      168        5.952      175        5.714
- 43      172        5.813      175        5.714
- 44      176        5.681      187        5.333
- 45      180        5.555      187        5.333
- 46      184        5.434      187        5.333
- 47      188        5.319      200        5.000
- 48      192        5.208      200        5.000
- 49      196        5.102      200        5.000
-
-
-17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk)
-
-17.1 Features
-
-Enabling serial NVRAM support enables detection of the serial NVRAM included
-on Symbios and some Symbios compatible host adaptors, and Tekram boards. The 
-serial NVRAM is used by Symbios and Tekram to hold set up parameters for the 
-host adaptor and it's attached drives.
-
-The Symbios NVRAM also holds data on the boot order of host adaptors in a
-system with more than one host adaptor. This enables the order of scanning
-the cards for drives to be changed from the default used during host adaptor
-detection.
-
-This can be done to a limited extent at the moment using "reverse probe" but
-this only changes the order of detection of different types of cards. The
-NVRAM boot order settings can do this as well as change the order the same
-types of cards are scanned in, something "reverse probe" cannot do.
-
-Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
-and this is used to distinguish between Symbios compatible and Tekram host 
-adaptors. This is used to disable the Symbios compatible "diff" setting
-incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT 
-configuration parameter is set enabling both Symbios and Tekram boards to be 
-used together with the Symbios cards using all their features, including
-"diff" support. ("led pin" support for Symbios compatible cards can remain
-enabled when using Tekram cards. It does nothing useful for Tekram host
-adaptors but does not cause problems either.)
-
-
-17.2 Symbios NVRAM layout
-
-typical data at NVRAM address 0x100 (53c810a NVRAM)
------------------------------------------------------------
-00 00
-64 01
-8e 0b
-
-00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 
-
-04 00 0f 00 00 10 00 50 00 00 01 00 00 62 
-04 00 03 00 00 10 00 58 00 00 01 00 00 63 
-04 00 01 00 00 10 00 48 00 00 01 00 00 61 
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 
-
-0f 00 08 08 64 00 0a 00
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-fe fe
-00 00
-00 00
------------------------------------------------------------
-NVRAM layout details
-
-NVRAM Address 0x000-0x0ff not used
-              0x100-0x26f initialised data
-              0x270-0x7ff not used
-
-general layout
-
-        header  -   6 bytes,
-        data    - 356 bytes (checksum is byte sum of this data)
-        trailer -   6 bytes
-                  ---
-        total     368 bytes
-
-data area layout
-
-        controller set up  -  20 bytes
-        boot configuration -  56 bytes (4x14 bytes)
-        device set up      - 128 bytes (16x8 bytes)
-        unused (spare?)    - 152 bytes (19x8 bytes)
-                             ---
-        total                356 bytes
-
------------------------------------------------------------
-header
-
-00 00   - ?? start marker
-64 01   - byte count (lsb/msb excludes header/trailer)
-8e 0b   - checksum (lsb/msb excludes header/trailer)
------------------------------------------------------------
-controller set up
-
-00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
-                   |     |           |     |
-                   |     |           |      -- host ID
-                   |     |           |
-                   |     |            --Removable Media Support
-                   |     |               0x00 = none
-                   |     |               0x01 = Bootable Device
-                   |     |               0x02 = All with Media
-                   |     |
-                   |      --flag bits 2
-                   |        0x00000001= scan order hi->low
-                   |            (default 0x00 - scan low->hi)
-                    --flag bits 1
-                       0x00000001 scam enable
-                       0x00000010 parity enable
-                       0x00000100 verbose boot msgs
-
-remaining bytes unknown - they do not appear to change in my
-current set up for any of the controllers.
-
-default set up is identical for 53c810a and 53c875 NVRAM
-(Removable Media added Symbios BIOS version 4.09)
------------------------------------------------------------
-boot configuration
-
-boot order set by order of the devices in this table
-
-04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
-04 00 03 00 00 10 00 58 00 00 01 00 00 63    2nd controller
-04 00 01 00 00 10 00 48 00 00 01 00 00 61    3rd controller
-00 00 00 00 00 00 00 00 00 00 00 00 00 00    4th controller
-       |  |  |  |     |        |     |  |
-       |  |  |  |     |        |      ---- PCI io port adr
-       |  |  |  |     |         --0x01 init/scan at boot time
-       |  |  |  |      --PCI device/function number (0xdddddfff)
-       |  |   ----- ?? PCI vendor ID (lsb/msb)
-        ----PCI device ID (lsb/msb)
-
-?? use of this data is a guess but seems reasonable
-
-remaining bytes unknown - they do not appear to change in my
-current set up
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-device set up (up to 16 devices - includes controller)
-
-0f 00 08 08 64 00 0a 00 - id 0
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 - id 15
- |     |  |  |     |  |
- |     |  |  |      ----timeout (lsb/msb)
- |     |  |   --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
- |     |  |                  (0x30 20 Mtrans/sec- fast 20)
- |     |  |                  (0x64 10 Mtrans/sec- fast )
- |     |  |                  (0xc8  5 Mtrans/sec)
- |     |  |                  (0x00  asynchronous)
- |     |   -- ?? max sync offset (0x08 in NVRAM on 53c810a) 
- |     |                         (0x10 in NVRAM on 53c875)
- |      --device bus width (0x08 narrow)
- |                         (0x10 16 bit wide)
-  --flag bits
-    0x00000001 - disconnect enabled
-    0x00000010 - scan at boot time
-    0x00000100 - scan luns
-    0x00001000 - queue tags enabled
-
-remaining bytes unknown - they do not appear to change in my
-current set up
-
-?? use of this data is a guess but seems reasonable 
-(but it could be max bus width)
-
-default set up for 53c810a NVRAM
-default set up for 53c875 NVRAM - bus width     - 0x10
-                                - sync offset ? - 0x10
-                                - sync period   - 0x30
------------------------------------------------------------
-?? spare device space (32 bit bus ??)
-
-00 00 00 00 00 00 00 00  (19x8bytes)
-.
-.
-00 00 00 00 00 00 00 00
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-trailer
-
-fe fe   - ? end marker ?
-00 00
-00 00
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-
-
-
-17.3 Tekram NVRAM layout
-
-nvram 64x16 (1024 bit)
-
-Drive settings
-
-Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
-              (addr 0x0yyyy1 = 0x0000)
-
-    x x x x  x x x x  x x x x  x x x x
-               | | |      | |  | | | |
-               | | |      | |  | | |  ----- parity check   0 - off
-               | | |      | |  | | |                       1 - on
-               | | |      | |  | | |
-               | | |      | |  | |  ------- sync neg       0 - off
-               | | |      | |  | |                         1 - on
-               | | |      | |  | |
-               | | |      | |  |  --------- disconnect     0 - off
-               | | |      | |  |                           1 - on
-               | | |      | |  |
-               | | |      | |   ----------- start cmd      0 - off
-               | | |      | |                              1 - on
-               | | |      | |
-               | | |      |  -------------- tagged cmds    0 - off
-               | | |      |                                1 - on
-               | | |      | 
-               | | |       ---------------- wide neg       0 - off
-               | | |                                       1 - on
-               | | |
-                --------------------------- sync rate      0 - 10.0 Mtrans/sec
-                                                           1 -  8.0
-                                                           2 -  6.6
-                                                           3 -  5.7
-                                                           4 -  5.0
-                                                           5 -  4.0
-                                                           6 -  3.0
-                                                           7 -  2.0
-                                                           7 -  2.0
-                                                           8 - 20.0
-                                                           9 - 16.7
-                                                           a - 13.9
-                                                           b - 11.9
-
-Global settings
-
-Host flags 0 (addr 0x100000, 32) 
-
-    x x x x  x x x x  x x x x  x x x x
-    | | | |  | | | |           | | | |
-    | | | |  | | | |            ----------- host ID    0x00 - 0x0f
-    | | | |  | | | |
-    | | | |  | | |  ----------------------- support for    0 - off
-    | | | |  | | |                          > 2 drives     1 - on
-    | | | |  | | | 
-    | | | |  | |  ------------------------- support drives 0 - off
-    | | | |  | |                            > 1Gbytes      1 - on
-    | | | |  | |
-    | | | |  |  --------------------------- bus reset on   0 - off
-    | | | |  |                                power on     1 - on
-    | | | |  |
-    | | | |   ----------------------------- active neg     0 - off
-    | | | |                                                1 - on
-    | | | |
-    | | |  -------------------------------- imm seek       0 - off
-    | | |                                                  1 - on
-    | | |
-    | |  ---------------------------------- scan luns      0 - off
-    | |                                                    1 - on
-    | |
-     -------------------------------------- removable      0 - disable
-                                            as BIOS dev    1 - boot device
-                                                           2 - all
-
-Host flags 1 (addr 0x100001, 33)
-
-    x x x x  x x x x  x x x x  x x x x
-               | | |             | | | 
-               | | |              --------- boot delay     0 -   3 sec
-               | | |                                       1 -   5
-               | | |                                       2 -  10
-               | | |                                       3 -  20
-               | | |                                       4 -  30
-               | | |                                       5 -  60
-               | | |                                       6 - 120
-               | | |
-                --------------------------- max tag cmds   0 -  2
-                                                           1 -  4
-                                                           2 -  8
-                                                           3 - 16
-                                                           4 - 32
-
-Host flags 2 (addr 0x100010, 34)
-
-    x x x x  x x x x  x x x x  x x x x
-                                     |
-                                      ----- F2/F6 enable   0 - off ???
-                                                           1 - on  ???
-
-checksum (addr 0x111111)
-
-checksum = 0x1234 - (sum addr 0-63)
-
-----------------------------------------------------------------------------
-
-default nvram data:
-
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 
-
-0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc
-
-
-18. Support for Big Endian
-
-The PCI local bus has been primarily designed for x86 architecture.
-As a consequence, PCI devices generally expect DWORDS using little endian 
-byte ordering.
-
-18.1 Big Endian CPU
-
-In order to support NCR chips on a Big Endian architecture the driver has to 
-perform byte reordering each time it is needed. This feature has been 
-added to the driver by Cort <cort@cs.nmt.edu> and is available in driver 
-version 2.5 and later ones. For the moment Big Endian support has only 
-been tested on Linux/PPC (PowerPC).
-
-18.2 NCR chip in Big Endian mode of operations
-
-It can be read in SYMBIOS documentation that some chips support a special 
-Big Endian mode, on paper: 53C815, 53C825A, 53C875, 53C875N, 53C895.
-This mode of operations is not software-selectable, but needs pin named 
-BigLit to be pulled-up. Using this mode, most of byte reorderings should 
-be avoided when the driver is running on a Big Endian CPU.
-Driver version 2.5 is also, in theory, ready for this feature.
-
-===============================================================================
-End of NCR53C8XX driver README file
diff -Nru a/drivers/scsi/README.osst b/drivers/scsi/README.osst
--- a/drivers/scsi/README.osst	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,219 +0,0 @@
-README file for the osst driver
-===============================
-(w) Kurt Garloff <garloff@suse.de> 12/2000
-
-This file describes the osst driver as of version 0.8.x/0.9.x, the released
-version of the osst driver.
-It is intended to help advanced users to understand the role of osst and to
-get them started using (and maybe debugging) it.
-It won't address issues like "How do I compile a kernel?" or "How do I load
-a module?", as these are too basic.
-Once the OnStream got merged into the official kernel, the distro makers
-will provide the OnStream support for those who are not familiar with
-hacking their kernels.
-
-
-Purpose
--------
-The osst driver was developed, because the standard SCSI tape driver in
-Linux, st, does not support the OnStream SC-x0 SCSI tape. The st is not to
-blame for that, as the OnStream tape drives do not support the standard SCSI
-command set for Serial Access Storage Devices (SASDs), which basically
-corresponds to the QIC-157 spec.
-Nevertheless, the OnStream tapes are nice pieces of hardware and therefore
-the osst driver has been written to make these tape devs supported by Linux.
-The driver is free software. It's released under the GNU GPL and planned to
-be integrated into the mainstream kernel.
-
-
-Implementation
---------------
-The osst is a new high-level SCSI driver, just like st, sr, sd and sg. It
-can be compiled into the kernel or loaded as a module.
-As it represents a new device, it got assigned a new device node: /dev/osstX
-are character devices with major no 206 and minor numbers like the /dev/stX
-devices. If those are not present, you may create them by calling
-Makedevs.sh as root (see below).
-The driver started being a copy of st and as such, the osst devices'
-behavior looks very much the same as st to the userspace applications.
-
-
-History
--------
-In the first place, osst shared it's identity very much with st. That meant
-that it used the same kernel structures and the same device node as st.
-So you could only have either of them being present in the kernel. This has
-been fixed by registering an own device, now.
-st and osst can coexist, each only accessing the devices it can support by
-themselves.
-
-
-Installation
-------------
-osst got integrated into the linux kernel. Select it during kernel
-configuration as module or compile statically into the kernel.
-Compile your kernel and install the modules.
-
-Now, your osst driver is inside the kernel or available as a module,
-depending on your choice during kernel config. You may still need to create
-the device nodes by calling the Makedevs.sh script (see below) manually,
-unless you use a devfs kernel, where this won't be needed.
-
-To load your module, you may use the command 
-modprobe osst
-as root. dmesg should show you, whether your OnStream tapes have been
-recognized.
-
-If you want to have the module autoloaded on access to /dev/osst, you may
-add something like
-alias char-major-206 osst
-to your /etc/modules.conf (old name: conf.modules).
-
-You may find it convenient to create a symbolic link 
-ln -s nosst0 /dev/tape
-to make programs assuming a default name of /dev/tape more convenient to
-use.
-
-The device nodes for osst have to be created. Use the Makedevs.sh script
-attached to this file.
-
-
-Using it
---------
-You may use the OnStream tape driver with your standard backup software,
-which may be tar, cpio, amanda, arkeia, BRU, Lone Tar, ...
-by specifying /dev/(n)osst0 as the tape device to use or using the above
-symlink trick. The IOCTLs to control tape operation are also mostly
-supported and you may try the mt (or mt_st) program to jump between
-filemarks, eject the tape, ...
-
-There's one limitation: You need to use a block size of 32kB.
-
-(This limitation is worked on and will be fixed in version 0.8.8 of
- this driver.)
-
-If you just want to get started with standard software, here is an example
-for creating and restoring a full backup:
-# Backup
-tar cvf - / --exclude /proc | buffer -s 32k -m 24M -B -t -o /dev/nosst0
-# Restore
-buffer -s 32k -m 8M -B -t -i /dev/osst0 | tar xvf - -C /
-
-The buffer command has been used to buffer the data before it goes to the
-tape (or the file system) in order to smooth out the data stream and prevent
-the tape from needing to stop and rewind. The OnStream does have an internal
-buffer and a variable speed which help this, but especially on writing, the
-buffering still proves useful in most cases. It also pads the data to
-guarantees the block size of 32k. (Otherwise you may pass the -b64 option to
-tar.)
-Expect something like 1.8MB/s for the SC-x0 drives and 0.9MB/s for the DI-30.
-The USB drive will give you about 0.7MB/s.
-On a fast machine, you may profit from software data compression (z flag for
-tar).
-
-
-USB and IDE
------------
-Via the SCSI emulation layers usb-storage and ide-scsi, you can also use the
-osst driver to drive the USB-30 and the DI-30 drives. (Unfortunately, there
-is no such layer for the parallel port, otherwise the DP-30 would work as
-well.) For the USB support, you need the latest 2.4.0-test kernels and the 
-latest usb-storage driver from 
-http://www.linux-usb.org/
-http://sourceforge.net/cvs/?group_id=3581
-
-Note that the ide-tape driver as of 1.16f uses a slightly outdated on-tape
-format and therefore is not completely interoperable with osst tapes.
-
-The ADR-x0 line is fully SCSI-2 compliant and is supported by st, not osst.
-The on-tape format is supposed to be compatible with the one used by osst.
-
-
-Feedback and updates
---------------------
-The driver development is coordinated through a mailing list
-<osst@linux1.onstream.nl>
-a CVS repository and some web pages. 
-The tester's pages which contain recent news and updated drivers to download
-can be found on
-http://linux1.onstream.nl/test/
-
-If you find any problems, please have a look at the tester's page in order
-to see whether the problem is already known and solved. Otherwise, please
-report it to the mailing list. Your feedback is welcome. (This holds also
-for reports of successful usage, of course.) 
-In case of trouble, please do always provide the following info:
-* driver and kernel version used (see syslog)
-* driver messages (syslog)
-* SCSI config and OnStream Firmware (/proc/scsi/scsi)
-* description of error. Is it reproducible?
-* software and commands used
-
-You may subscribe to the mailing list, BTW, it's a majordomo list.
-
-
-Status
-------
-0.8.0 was the first widespread BETA release. Since then a lot of reports
-have been sent, but mostly reported success or only minor trouble.
-All the issues have been addressed.
-Check the web pages for more info about the current developments.
-0.9.x is the tree for the 2.3/2.4 kernel.
-
-
-Acknowledgments
-----------------
-The driver has been started by making a copy of Kai Makisara's st driver.
-Most of the development has been done by Willem Riede. The presence of the
-userspace program osg (onstreamsg) from Terry Hardie has been rather
-helpful. The same holds for Gadi Oxman's ide-tape support for the DI-30.
-I did add some patches to those drivers as well and coordinated things a
-little bit. 
-Note that most of them did mostly spend their spare time for the creation of
-this driver.
-The people from OnStream, especially Jack Bombeeck did support this project
-and always tried to answer HW or FW related questions. Furthermore, he
-pushed the FW developers to do the right things.
-SuSE did support this project by allowing me to work on it during my working
-time for them and by integrating the driver into their distro.
-
-More people did help by sending useful comments. Sorry to those who have
-been forgotten. Thanks to all the GNU/FSF and Linux developers who made this
-platform such an interesting, nice and stable platform.
-Thanks go to those who tested the drivers and did send useful reports. Your
-help is needed!
-
-
-Makedevs.sh
------------
-#!/bin/sh
-# Script to create OnStream SC-x0 device nodes (major 206)
-# Usage: Makedevs.sh [nos [path to dev]]
-# $Id: README.osst.kernel,v 1.4 2000/12/20 14:13:15 garloff Exp $
-major=206
-nrs=4
-dir=/dev
-test -z "$1" || nrs=$1
-test -z "$2" || dir=$2
-declare -i nr
-nr=0
-test -d $dir || mkdir -p $dir
-while test $nr -lt $nrs; do
-  mknod $dir/osst$nr c $major $nr
-  chown 0.disk $dir/osst$nr; chmod 660 $dir/osst$nr;
-  mknod $dir/nosst$nr c $major $[nr+128]
-  chown 0.disk $dir/nosst$nr; chmod 660 $dir/nosst$nr;
-  mknod $dir/osst${nr}l c $major $[nr+32]
-  chown 0.disk $dir/osst${nr}l; chmod 660 $dir/osst${nr}l;
-  mknod $dir/nosst${nr}l c $major $[nr+160]
-  chown 0.disk $dir/nosst${nr}l; chmod 660 $dir/nosst${nr}l;
-  mknod $dir/osst${nr}m c $major $[nr+64]
-  chown 0.disk $dir/osst${nr}m; chmod 660 $dir/osst${nr}m;
-  mknod $dir/nosst${nr}m c $major $[nr+192]
-  chown 0.disk $dir/nosst${nr}m; chmod 660 $dir/nosst${nr}m;
-  mknod $dir/osst${nr}a c $major $[nr+96]
-  chown 0.disk $dir/osst${nr}a; chmod 660 $dir/osst${nr}a;
-  mknod $dir/nosst${nr}a c $major $[nr+224]
-  chown 0.disk $dir/nosst${nr}a; chmod 660 $dir/nosst${nr}a;
-  let nr+=1
-done
diff -Nru a/drivers/scsi/README.ppa b/drivers/scsi/README.ppa
--- a/drivers/scsi/README.ppa	Sun Nov 17 20:30:16 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,16 +0,0 @@
--------- Terse where to get ZIP Drive help info --------
-
-General Iomega ZIP drive page for Linux:
-http://www.torque.net/~campbell/
-
-Driver achive for old drivers:
-http://www.torque.net/~campbell/ppa/
-
-Linux Parport page (parallel port)
-http://www.torque.net/parport/
-
-Email list for Linux Parport
-linux-parport@torque.net
-
-Email for problems with ZIP or ZIP Plus drivers
-campbell@torque.net
diff -Nru a/drivers/scsi/README.qlogicfas b/drivers/scsi/README.qlogicfas
--- a/drivers/scsi/README.qlogicfas	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,79 +0,0 @@
-
-This driver supports the Qlogic FASXXX family of chips.  This driver
-only works with the ISA, VLB, and PCMCIA versions of the Qlogic
-FastSCSI!  cards as well as any other card based on the FASXX chip
-(including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards).
-
-This driver does NOT support the PCI version.  Support for these PCI
-Qlogic boards:
-
-	* IQ-PCI
-	* IQ-PCI-10
-	* IQ-PCI-D
-
-is provided by the qlogicisp.c driver.  Check README.qlogicisp for
-details.
-
-Nor does it support the PCI-Basic, which is supported by the
-'am53c974' driver.
-
-PCMCIA SUPPORT
-
-This currently only works if the card is enabled first from DOS.  This
-means you will have to load your socket and card services, and
-QL41DOS.SYS and QL40ENBL.SYS.  These are a minimum, but loading the
-rest of the modules won't interfere with the operation.  The next
-thing to do is load the kernel without resetting the hardware, which
-can be a simple ctrl-alt-delete with a boot floppy, or by using
-loadlin with the kernel image accessible from DOS.  If you are using
-the Linux PCMCIA driver, you will have to adjust it or otherwise stop
-it from configuring the card.
-
-I am working with the PCMCIA group to make it more flexible, but that
-may take a while.
-
-ALL CARDS
-
-The top of the qlogic.c file has a number of defines that controls
-configuration.  As shipped, it provides a balance between speed and
-function.  If there are any problems, try setting SLOW_CABLE to 1, and
-then try changing USE_IRQ and TURBO_PDMA to zero.  If you are familiar
-with SCSI, there are other settings which can tune the bus.
-
-It may be a good idea to enable RESET_AT_START, especially if the
-devices may not have been just powered up, or if you are restarting
-after a crash, since they may be busy trying to complete the last
-command or something.  It comes up faster if this is set to zero, and
-if you have reliable hardware and connections it may be more useful to
-not reset things.
-
-SOME TROUBLESHOOTING TIPS
-
-Make sure it works properly under DOS.  You should also do an initial FDISK
-on a new drive if you want partitions.
-
-Don't enable all the speedups first.  If anything is wrong, they will make
-any problem worse.
-
-IMPORTANT
-
-The best way to test if your cables, termination, etc. are good is to
-copy a very big file (e.g. a doublespace container file, or a very
-large executable or archive).  It should be at least 5 megabytes, but
-you can do multiple tests on smaller files.  Then do a COMP to verify
-that the file copied properly.  (Turn off all caching when doing these
-tests, otherwise you will test your RAM and not the files).  Then do
-10 COMPs, comparing the same file on the SCSI hard drive, i.e. "COMP
-realbig.doc realbig.doc".  Then do it after the computer gets warm.
-
-I noticed my system which seems to work 100% would fail this test if
-the computer was left on for a few hours.  It was worse with longer
-cables, and more devices on the SCSI bus.  What seems to happen is
-that it gets a false ACK causing an extra byte to be inserted into the
-stream (and this is not detected).  This can be caused by bad
-termination (the ACK can be reflected), or by noise when the chips
-work less well because of the heat, or when cables get too long for
-the speed.
-
-Remember, if it doesn't work under DOS, it probably won't work under
-Linux.
diff -Nru a/drivers/scsi/README.qlogicisp b/drivers/scsi/README.qlogicisp
--- a/drivers/scsi/README.qlogicisp	Sun Nov 17 20:30:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-Notes for the QLogic ISP1020 PCI SCSI Driver:
-
-This driver works well in practice, but does not support disconnect/
-reconnect, which makes using it with tape drives impractical.
-
-It should work for most host adaptors with the ISP1020 chip.  The
-QLogic Corporation produces several PCI SCSI adapters which should
-work:
-
-	* IQ-PCI
-	* IQ-PCI-10
-	* IQ-PCI-D
-
-This driver may work with boards containing the ISP1020A or ISP1040A
-chips, but that has not been tested.
-
-This driver will NOT work with:
-
-	* ISA or VL Bus Qlogic cards (they use the 'qlogicfas' driver)
-	* PCI-basic (it uses the 'am53c974' driver)
-
-Much thanks to QLogic's tech support for providing the latest ISP1020
-firmware, and for taking the time to review my code.
-
-Erik Moe
-ehm@cris.com
-
-Revised:
-Michael A. Griffith
-grif@cs.ucr.edu
-
-
-
-
diff -Nru a/drivers/scsi/README.st b/drivers/scsi/README.st
--- a/drivers/scsi/README.st	Sun Nov 17 20:30:04 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,447 +0,0 @@
-This file contains brief information about the SCSI tape driver.
-The driver is currently maintained by Kai M{kisara (email
-Kai.Makisara@metla.fi)
-
-Last modified: Fri Jul 26 16:01:39 2002 by makisara
-
-
-BASICS
-
-The driver is generic, i.e., it does not contain any code tailored
-to any specific tape drive. The tape parameters can be specified with
-one of the following three methods:
-
-1. Each user can specify the tape parameters he/she wants to use
-directly with ioctls. This is administratively a very simple and
-flexible method and applicable to single-user workstations. However,
-in a multiuser environment the next user finds the tape parameters in
-state the previous user left them.
-
-2. The system manager (root) can define default values for some tape
-parameters, like block size and density using the MTSETDRVBUFFER ioctl.
-These parameters can be programmed to come into effect either when a
-new tape is loaded into the drive or if writing begins at the
-beginning of the tape. The second method is applicable if the tape
-drive performs auto-detection of the tape format well (like some
-QIC-drives). The result is that any tape can be read, writing can be
-continued using existing format, and the default format is used if
-the tape is rewritten from the beginning (or a new tape is written
-for the first time). The first method is applicable if the drive
-does not perform auto-detection well enough and there is a single
-"sensible" mode for the device. An example is a DAT drive that is
-used only in variable block mode (I don't know if this is sensible
-or not :-).
-
-The user can override the parameters defined by the system
-manager. The changes persist until the defaults again come into
-effect.
-
-3. Up to four modes can be defined and selected using the minor number
-(bits 5 and 6). Mode 0 corresponds to the defaults discussed
-above. Additional modes are dormant until they are defined by the
-system manager (root). When specification of a new mode is started,
-the configuration of mode 0 is used to provide a starting point for
-definition of the new mode.
-
-Using the modes allows the system manager to give the users choices
-over some of the buffering parameters not directly accessible to the
-users (buffered and asynchronous writes). The modes also allow choices
-between formats in multi-tape operations (the explicitly overridden
-parameters are reset when a new tape is loaded).
-
-If more than one mode is used, all modes should contain definitions
-for the same set of parameters.
-
-Many Unices contain internal tables that associate different modes to
-supported devices. The Linux SCSI tape driver does not contain such
-tables (and will not do that in future). Instead of that, a utility
-program can be made that fetches the inquiry data sent by the device,
-scans its database, and sets up the modes using the ioctls. Another
-alternative is to make a small script that uses mt to set the defaults
-tailored to the system.
-
-The driver supports fixed and variable block size (within buffer
-limits). Both the auto-rewind (minor equals device number) and
-non-rewind devices (minor is 128 + device number) are implemented.
-
-In variable block mode, the byte count in write() determines the size
-of the physical block on tape. When reading, the drive reads the next
-tape block and returns to the user the data if the read() byte count
-is at least the block size. Otherwise, error ENOMEM is returned.
-
-In fixed block mode, the data transfer between the drive and the
-driver is in multiples of the block size. The write() byte count must
-be a multiple of the block size. This is not required when reading but
-may be advisable for portability.
-
-Support is provided for changing the tape partition and partitioning
-of the tape with one or two partitions. By default support for
-partitioned tape is disabled for each driver and it can be enabled
-with the ioctl MTSETDRVBUFFER.
-
-By default the driver writes one filemark when the device is closed after
-writing and the last operation has been a write. Two filemarks can be
-optionally written. In both cases end of data is signified by
-returning zero bytes for two consecutive reads.
-
-The compile options are defined in the file linux/drivers/scsi/st_options.h.
-
-4. If the open option O_NONBLOCK is used, open succeeds even if the
-drive is not ready. If O_NONBLOCK is not used, the driver waits for
-the drive to become ready. If this does not happen in ST_BLOCK_SECONDS
-seconds, open fails with the errno value EIO.
-
-
-BSD AND SYS V SEMANTICS
-
-The user can choose between these two behaviours of the tape driver by
-defining the value of the symbol ST_SYSV. The semantics differ when a
-file being read is closed. The BSD semantics leaves the tape where it
-currently is whereas the SYS V semantics moves the tape past the next
-filemark unless the filemark has just been crossed.
-
-The default is BSD semantics.
-
-
-BUFFERING
-
-The driver tries to do tranfers directly to/from user space. If this
-is not possible, a driver buffer allocated at run-time is used. If
-direct i/o is not possible for the whole transfer, the driver buffer
-is used (i.e., bounce buffers for individual pages are not
-used). Direct i/o can be impossible because of several reasons, e.g.:
-- one or more pages are at addresses not reachable by the HBA
-- the number of pages in the transfer exceeds the number of
-  scatter/gather segments permitted by the HBA
-- one or more pages can't be locked into memory (should not happen in
-  any reasonable situation)
-
-The size of the driver buffers is always at least one tape block. In fixed
-block mode, the minimum buffer size is defined (in 1024 byte units) by
-ST_FIXED_BUFFER_BLOCKS. With small block size this allows buffering of
-several blocks and using one SCSI read or write to transfer all of the
-blocks. Buffering of data across write calls in fixed block mode is
-allowed if ST_BUFFER_WRITES is non-zero and direct i/o is not used.
-Buffer allocation uses chunks of memory having sizes 2^n * (page
-size). Because of this the actual buffer size may be larger than the
-minimum allowable buffer size.
-
-Asynchronous writing. Writing the buffer contents to the tape is
-started and the write call returns immediately. The status is checked
-at the next tape operation. Asynchronous writes are not done with
-direct i/o.
-
-Buffered writes and asynchronous writes may in some rare cases cause
-problems in multivolume operations if there is not enough space on the
-tape after the early-warning mark to flush the driver buffer.
-
-Read ahead for fixed block mode (ST_READ_AHEAD). Filling the buffer is
-attempted even if the user does not want to get all of the data at
-this read command. Should be disabled for those drives that don't like
-a filemark to truncate a read request or that don't like backspacing.
-
-The threshold for triggering asynchronous write in fixed block mode
-is defined by ST_WRITE_THRESHOLD. This may be optimized for each
-use pattern. The default triggers asynchronous write after three
-default sized writes (10 kB) from tar.
-
-Scatter/gather buffers (buffers that consist of chunks non-contiguous
-in the physical memory) are used if contiguous buffers can't be
-allocated. To support all SCSI adapters (including those not
-supporting scatter/gather), buffer allocation is using the following
-three kinds of chunks:
-1. The initial segment that is used for all SCSI adapters including
-those not supporting scatter/gather. The size of this buffer will be
-(PAGE_SIZE << ST_FIRST_ORDER) bytes if the system can give a chunk of
-this size (and it is not larger than the buffer size specified by
-ST_BUFFER_BLOCKS). If this size is not available, the driver halves
-the size and tries again until the size of one page. The default
-settings in st_options.h make the driver to try to allocate all of the
-buffer as one chunk.
-2. The scatter/gather segments to fill the specified buffer size are
-allocated so that as many segments as possible are used but the number
-of segments does not exceed ST_FIRST_SG.
-3. The remaining segments between ST_MAX_SG (or the module parameter
-max_sg_segs) and the number of segments used in phases 1 and 2
-are used to extend the buffer at run-time if this is necessary. The
-number of scatter/gather segments allowed for the SCSI adapter is not
-exceeded if it is smaller than the maximum number of scatter/gather
-segments specified. If the maximum number allowed for the SCSI adapter
-is smaller than the number of segments used in phases 1 and 2,
-extending the buffer will always fail.
-
-
-EOM BEHAVIOUR WHEN WRITING
-
-When the end of medium early warning is encountered, the current write
-is finished and the number of bytes is returned. The next write
-returns -1 and errno is set to ENOSPC. To enable writing a trailer,
-the next write is allowed to proceed and, if successful, the number of
-bytes is returned. After this, -1 and the number of bytes are
-alternately returned until the physical end of medium (or some other
-error) is encountered.
-
-
-MODULE PARAMETERS
-
-The buffer size, write threshold, and the maximum number of allocated buffers
-are configurable when the driver is loaded as a module. The keywords are:
-
-buffer_kbs=xxx             the buffer size for fixed block mode is set
-			   to xxx kilobytes
-write_threshold_kbs=xxx    the write threshold in kilobytes set to xxx
-max_sg_segs=xxx		   the maximum number of scatter/gather
-			   segments
-try_direct_io=x		   try direct transfer between user buffer and
-			   tape drive if this is non-zero
-
-Note that if the buffer size is changed but the write threshold is not
-set, the write threshold is set to the new buffer size - 2 kB.
-
-
-BOOT TIME CONFIGURATION
-
-If the driver is compiled into the kernel, the same parameters can be
-also set using, e.g., the LILO command line. The preferred syntax is
-to use the same keywords as when loading the driver as module. If
-several parameters are set, the keyword-value pairs are separated with
-a comma (no spaces allowed). A colon can be used instead of the equal
-mark. The definition is prepended by the string st=. Here is an
-example:
-
-	st=buffer_kbs:64,write_threhold_kbs:60
-
-The following syntax used by the old kernel versions is also supported:
-
-           st=aa[,bb[,dd]]
-
-where
-  aa is the buffer size for fixed block mode in 1024 byte units
-  bb is the write threshold in 1024 byte units
-  dd is the maximum number of scatter/gather segments
-
-
-IOCTLS
-
-The tape is positioned and the drive parameters are set with ioctls
-defined in mtio.h The tape control program 'mt' uses these ioctls. Try
-to find an mt that supports all of the Linux SCSI tape ioctls and
-opens the device for writing if the tape contents will be modified
-(look for a package mt-st* from the Linux ftp sites; the GNU mt does
-not open for writing for, e.g., erase).
-
-The supported ioctls are:
-
-The following use the structure mtop:
-
-MTFSF   Space forward over count filemarks. Tape positioned after filemark.
-MTFSFM  As above but tape positioned before filemark.
-MTBSF	Space backward over count filemarks. Tape positioned before
-        filemark.
-MTBSFM  As above but ape positioned after filemark.
-MTFSR   Space forward over count records.
-MTBSR   Space backward over count records.
-MTFSS   Space forward over count setmarks.
-MTBSS   Space backward over count setmarks.
-MTWEOF  Write count filemarks.
-MTWSM   Write count setmarks.
-MTREW   Rewind tape.
-MTOFFL  Set device off line (often rewind plus eject).
-MTNOP   Do nothing except flush the buffers.
-MTRETEN Re-tension tape.
-MTEOM   Space to end of recorded data.
-MTERASE Erase tape. If the argument is zero, the short erase command
-	is used. The long erase command is used with all other values
-	of the argument.
-MTSEEK	Seek to tape block count. Uses Tandberg-compatible seek (QFA)
-        for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and
-	block numbers in the status are not valid after a seek.
-MTSETBLK Set the drive block size. Setting to zero sets the drive into
-        variable block mode (if applicable).
-MTSETDENSITY Sets the drive density code to arg. See drive
-        documentation for available codes.
-MTLOCK and MTUNLOCK Explicitly lock/unlock the tape drive door.
-MTLOAD and MTUNLOAD Explicitly load and unload the tape. If the
-	command argument x is between MT_ST_HPLOADER_OFFSET + 1 and
-	MT_ST_HPLOADER_OFFSET + 6, the number x is used sent to the
-	drive with the command and it selects the tape slot to use of
-	HP C1553A changer.
-MTCOMPRESSION Sets compressing or uncompressing drive mode using the
-	SCSI mode page 15. Note that some drives other methods for
-	control of compression. Some drives (like the Exabytes) use
-	density codes for compression control. Some drives use another
-	mode page but this page has not been implemented in the
-	driver. Some drives without compression capability will accept
-	any compression mode without error.
-MTSETPART Moves the tape to the partition given by the argument at the
-	next tape operation. The block at which the tape is positioned
-	is the block where the tape was previously positioned in the
-	new active partition unless the next tape operation is
-	MTSEEK. In this case the tape is moved directly to the block
-	specified by MTSEEK. MTSETPART is inactive unless
-	MT_ST_CAN_PARTITIONS set.
-MTMKPART Formats the tape with one partition (argument zero) or two
-	partitions (the argument gives in megabytes the size of
-	partition 1 that is physically the first partition of the
-	tape). The drive has to support partitions with size specified
-	by the initiator. Inactive unless MT_ST_CAN_PARTITIONS set.
-MTSETDRVBUFFER
-	Is used for several purposes. The command is obtained from count
-        with mask MT_SET_OPTIONS, the low order bits are used as argument.
-	This command is only allowed for the superuser (root). The
-	subcommands are:
-	0
-           The drive buffer option is set to the argument. Zero means
-           no buffering.
-        MT_ST_BOOLEANS
-           Sets the buffering options. The bits are the new states
-           (enabled/disabled) the following options (in the
-	   parenthesis is specified whether the option is global or
-	   can be specified differently for each mode):
-	     MT_ST_BUFFER_WRITES write buffering (mode)
-	     MT_ST_ASYNC_WRITES asynchronous writes (mode)
-             MT_ST_READ_AHEAD  read ahead (mode)
-             MT_ST_TWO_FM writing of two filemarks (global)
-	     MT_ST_FAST_EOM using the SCSI spacing to EOD (global)
-	     MT_ST_AUTO_LOCK automatic locking of the drive door (global)
-             MT_ST_DEF_WRITES the defaults are meant only for writes (mode)
-	     MT_ST_CAN_BSR backspacing over more than one records can
-		be used for repositioning the tape (global)
-	     MT_ST_NO_BLKLIMS the driver does not ask the block limits
-		from the drive (block size can be changed only to
-		variable) (global)
-	     MT_ST_CAN_PARTITIONS enables support for partitioned
-		tapes (global)
-	     MT_ST_SCSI2LOGICAL the logical block number is used in
-		the MTSEEK and MTIOCPOS for SCSI-2 drives instead of
-		the device dependent address. It is recommended to set
-		this flag unless there are tapes using the device
-		dependent (from the old times) (global)
-	     MT_ST_SYSV sets the SYSV sematics (mode)
-	     MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
-	        the command to finish) for some commands (e.g., rewind)
-	     MT_ST_DEBUGGING debugging (global; debugging must be
-		compiled into the driver)
-	MT_ST_SETBOOLEANS
-	MT_ST_CLEARBOOLEANS
-	   Sets or clears the option bits.
-        MT_ST_WRITE_THRESHOLD
-           Sets the write threshold for this device to kilobytes
-           specified by the lowest bits.
-	MT_ST_DEF_BLKSIZE
-	   Defines the default block size set automatically. Value
-	   0xffffff means that the default is not used any more.
-	MT_ST_DEF_DENSITY
-	MT_ST_DEF_DRVBUFFER
-	   Used to set or clear the density (8 bits), and drive buffer
-	   state (3 bits). If the value is MT_ST_CLEAR_DEFAULT
-	   (0xfffff) the default will not be used any more. Otherwise
-	   the lowermost bits of the value contain the new value of
-	   the parameter.
-	MT_ST_DEF_COMPRESSION
-	   The compression default will not be used if the value of
-	   the lowermost byte is 0xff. Otherwise the lowermost bit
-	   contains the new default. If the bits 8-15 are set to a
-	   non-zero number, and this number is not 0xff, the number is
-	   used as the compression algorithm. The value
-	   MT_ST_CLEAR_DEFAULT can be used to clear the compression
-	   default.
-	MT_ST_SET_TIMEOUT
-	   Set the normal timeout in seconds for this device. The
-	   default is 900 seconds (15 minutes). The timeout should be
-	   long enough for the retries done by the device while
-	   reading/writing.
-	MT_ST_SET_LONG_TIMEOUT
-	   Set the long timeout that is used for operations that are
-	   known to take a long time. The default is 14000 seconds
-	   (3.9 hours). For erase this value is further multiplied by
-	   eight.
-	MT_ST_SET_CLN
-	   Set the cleaning request interpretation parameters using
-	   the lowest 24 bits of the argument. The driver can set the
-	   generic status bit GMT_CLN if a cleaning request bit pattern
-	   is found from the extended sense data. Many drives set one or
-	   more bits in the extended sense data when the drive needs
-	   cleaning. The bits are device-dependent. The driver is
-	   given the number of the sense data byte (the lowest eight
-	   bits of the argument; must be >= 18 (values 1 - 17
-	   reserved) and <= the maximum requested sense data sixe), 
-	   a mask to select the relevant bits (the bits 9-16), and the
-	   bit pattern (bits 17-23). If the bit pattern is zero, one
-	   or more bits under the mask indicate cleaning request. If
-	   the pattern is non-zero, the pattern must match the masked
-	   sense data byte.
-
-	   (The cleaning bit is set if the additional sense code and
-	   qualifier 00h 17h are seen regardless of the setting of
-	   MT_ST_SET_CLN.)
-
-The following ioctl uses the structure mtpos:
-MTIOCPOS Reads the current position from the drive. Uses
-        Tandberg-compatible QFA for SCSI-1 drives and the SCSI-2
-        command for the SCSI-2 drives.
-
-The following ioctl uses the structure mtget to return the status:
-MTIOCGET Returns some status information.
-        The file number and block number within file are returned. The
-        block is -1 when it can't be determined (e.g., after MTBSF).
-        The drive type is either MTISSCSI1 or MTISSCSI2.
-        The number of recovered errors since the previous status call
-        is stored in the lower word of the field mt_erreg.
-        The current block size and the density code are stored in the field
-        mt_dsreg (shifts for the subfields are MT_ST_BLKSIZE_SHIFT and
-        MT_ST_DENSITY_SHIFT).
-	The GMT_xxx status bits reflect the drive status. GMT_DR_OPEN
-	is set if there is no tape in the drive. GMT_EOD means either
-	end of recorded data or end of tape. GMT_EOT means end of tape.
-
-
-MISCELLANEOUS COMPILE OPTIONS
-
-The recovered write errors are considered fatal if ST_RECOVERED_WRITE_FATAL
-is defined.
-
-The maximum number of tape devices is determined by the define
-ST_MAX_TAPES. If more tapes are detected at driver initialization, the
-maximum is adjusted accordingly.
-
-Immediate return from tape positioning SCSI commands can be enabled by
-defining ST_NOWAIT. If this is defined, the user should take care that
-the next tape operation is not started before the previous one has
-finished. The drives and SCSI adapters should handle this condition
-gracefully, but some drive/adapter combinations are known to hang the
-SCSI bus in this case.
-
-The MTEOM command is by default implemented as spacing over 32767
-filemarks. With this method the file number in the status is
-correct. The user can request using direct spacing to EOD by setting
-ST_FAST_EOM 1 (or using the MT_ST_OPTIONS ioctl). In this case the file
-number will be invalid.
-
-When using read ahead or buffered writes the position within the file
-may not be correct after the file is closed (correct position may
-require backspacing over more than one record). The correct position
-within file can be obtained if ST_IN_FILE_POS is defined at compile
-time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl.
-(The driver always backs over a filemark crossed by read ahead if the
-user does not request data that far.)
-
-
-DEBUGGING HINTS
-
-To enable debugging messages, edit st.c and #define DEBUG 1. As seen
-above, debugging can be switched off with an ioctl if debugging is
-compiled into the driver. The debugging output is not voluminuous.
-
-If the tape seems to hang, I would be very interested to hear where
-the driver is waiting. With the command 'ps -l' you can see the state
-of the process using the tape. If the state is D, the process is
-waiting for something. The field WCHAN tells where the driver is
-waiting. If you have the current System.map in the correct place (in
-/boot for the procps I use) or have updated /etc/psdatabase (for kmem
-ps), ps writes the function name in the WCHAN field. If not, you have
-to look up the function from System.map.
-
-Note also that the timeouts are very long compared to most other
-drivers. This means that the Linux driver may appear hung although the
-real reason is that the tape firmware has got confused.
diff -Nru a/drivers/scsi/README.tmscsim b/drivers/scsi/README.tmscsim
--- a/drivers/scsi/README.tmscsim	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,449 +0,0 @@
-The tmscsim driver
-==================
-
-1. Purpose and history
-2. Installation
-3. Features
-4. Configuration via /proc/scsi/tmscsim/?
-5. Configuration via boot/module params
-6. Potential improvements
-7. Bug reports, debugging and updates
-8. Acknowledgements
-9. Copyright
-
-
-1. Purpose and history
-----------------------
-The tmscsim driver supports PCI SCSI Host Adapters based on the AM53C974
-chip. AM53C974 based SCSI adapters include: 
- Tekram DC390, DC390T
- Dawicontrol 2974
- QLogic Fast! PCI Basic
- some on-board adapters
-(This is most probably not a complete list)
-
-It has originally written by C.L. Huang from the Tekram corp. to support the
-Tekram DC390(T) adapter. This is where the name comes from: tm = Tekram
-scsi = SCSI driver, m = AMD (?) as opposed to w for the DC390W/U/F
-(NCR53c8X5, X=2/7) driver. Yes, there was also a driver for the latter,
-tmscsiw, which supported DC390W/U/F adapters. It's not maintained any more,
-as the ncr53c8xx is perfectly supporting these adpaters since some time.
-
-The driver first appeared in April 1996, exclusively supported the DC390 
-and has been enhanced since then in various steps. In May 1998 support for 
-general AM53C974 based adapters and some possibilities to configure it were
-added. The non-DC390 support works by assuming some values for the data
-normally taken from the DC390 EEPROM. See below (chapter 5) for details.
-
-When using the DC390, the configuration is still be done using the DC390
-BIOS setup. The DC390 EEPROM is read and used by the driver, any boot or
-module parameters (chapter 5) are ignored! However, you can change settings
-dynamically, as described in chapter 4. 
-
-For a more detailed description of the driver's history, see the first lines
-of tmscsim.c.
-The numbering scheme isn't consistent. The first versions went from 1.00 to
-1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So
-the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental),
-2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send
-fixes to people for testing, I create intermediate versions with a digit 
-appended, e.g. 2.0c3.
-
-
-2. Installation
----------------
-If you got any recent kernel with this driver and document included in
-linux/drivers/scsi, you basically have to do nothing special to use this
-driver. Of course you have to choose to compile SCSI support and DC390(T)
-support into your kernel or as module when configuring your kernel for
-compiling.
-NEW: You may as well compile this module outside your kernel, using the
-supplied Makefile.
-
- If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of
- this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from
- my web page and apply the patch. Apply further patches to upgrade to the 
- latest version of the driver.
-
- If you want to do it manually, you should copy the files (dc390.h,
- tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to
- linux/drivers/scsi. You have to recompile your kernel/module of course.
-
- You should apply the three patches included in dc390-120-kernel.diff
- (Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff)
- The patches are against 2.1.125, so you might have to manually resolve
- rejections when applying to another kernel version.
-
- The patches will update the kernel startup code to allow boot parameters to
- be passed to the driver, update the Documentation and finally offer you the
- possibility to omit the non-DC390 parts of the driver.
- (By selecting "Omit support for non DC390" you basically disable the
- emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes
- of memory.)
-
-If you got a very old kernel without the tmscsim driver (pre 2.0.31)
-I recommend upgrading your kernel. However, if you don't want to, please
-contact me to get the appropriate patches.
-
-
-Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has
-proven stable on many systems, but it's still a good idea to take some
-precautions. In an ideal world you would have a full backup of your disks.
-The world isn't ideal and most people don't have full backups (me neither).
-So take at least the following measures:
-* make your kernel remount the FS read-only on detecting an error:
-  tune2fs -e remount-ro /dev/sd??
-* have copies of your SCSI disk's partition tables on some safe location:
-  dd if=/dev/sda of=/mnt/floppy/sda bs=512 count=1
-  or just print it with:
-  fdisk -l | lpr
-* make sure you are able to boot Linux (e.g. from floppy disk using InitRD)
-  if your SCSI disk gets corrupted. You can use 
-  ftp://student.physik.uni-dortmund.de/pub/linux/kernel/bootdisk.gz
-
-One more warning: I used to overclock my PCI bus to 41.67 MHz. My Tekram
-DC390F (Sym53c875) accepted this as well as my Millenium. But the Am53C974
-produced errors and started to corrupt my disks. So don't do that! A 37.50
-MHz PCI bus works for me, though, but I don't recommend using higher clocks
-than the 33.33 MHz being in the PCI spec.
-
-If you want to share the IRQ with another device and the driver refuses to
-do so, you might succeed with changing the DC390_IRQ type in tmscsim.c to 
-SA_SHIRQ | SA_INTERRUPT.
-
-
-3.Features
-----------
-- SCSI
- * Tagged command queueing
- * Sync speed up to 10 MHz
- * Disconnection
- * Multiple LUNs
-
-- General / Linux interface
- * Support for up to 4 AM53C974 adapters.
- * DC390 EEPROM usage or boot/module params
- * Information via cat /proc/scsi/tmscsim/?
- * Dynamically configurable by writing to /proc/scsi/tmscsim/?
- * Dynamic allocation of resources
- * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter 
-    specific locks (Linux 2.5?)
- * Uniform source code for Linux-2.x.y
- * Support for dyn. addition/removal of devices via add/remove-single-device
-   (Try: echo "scsi add-single-device C B T U" >/proc/scsi/scsi 
-    C = Controller, B = Bus, T = Target SCSI ID, U = Unit SCSI LUN.) 
-    Use with care!
- * Try to use the partition table for the determination of the mapping
-
-
-4. Configuration via /proc/scsi/tmscsim/?
------------------------------------------
-First of all look at the output of /proc/scsi/tmscsim/? by typing
- cat /proc/scsi/tmscsim/?
-The "?" should be replaced by the SCSI host number. (The shell might do this
-for you.)
-You will see some info regarding the adapter and, at the end, a listing of
-the attached devices and their settings.
-
-Here's an example:
-garloff@kurt:/home/garloff > cat /proc/scsi/tmscsim/0
-Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0e7 2000-11-28
-SCSI Host Nr 1, AM53C974 Adapter Nr 0
-IOPortBase 0xb000, IRQ 10
-MaxID 8, MaxLUN 8, AdapterID 6, SelTimeout 250 ms, DelayReset 1 s
-TagMaxNum 16, Status 0x00, ACBFlag 0x00, GlitchEater 24 ns
-Statistics: Cmnds 1470165, Cmnds not sent directly 0, Out of SRB conds 0
-            Lost arbitrations 587,  Sel. connected 0, Connected: No
-Nr of attached devices: 4, Nr of DCBs: 4
-Map of attached LUNs: 01 00 00 03 01 00 00 00
-Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd
-00  00  00  Yes  Yes  Yes  Yes  Yes   100 ns    10.0 M      15      16
-01  03  00  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
-02  03  01  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
-03  04  00  Yes  Yes  Yes  Yes  No    100 ns    10.0 M      15      01
-
-Note that the settings MaxID and MaxLUN are not zero- but one-based, which
-means that a setting MaxLUN=4, will result in the support of LUNs 0..3. This
-is somehow inconvenient, but the way the mid-level SCSI code expects it to be.
-
-ACB and DCB are acronyms for Adapter Control Block and Device Control Block.
-These are data structures of the driver containing information about the
-adapter and the connected SCSI devices respectively.
-
-Idx is the device index (just a consecutive number for the driver), ID and
-LUN are the SCSI ID and LUN, Prty means Parity checking, Sync synchronous
-negotiation, DsCn Disconnection, SndS Send Start command on startup (not
-used by the driver) and TagQ Tagged Command Queueing. NegoPeriod and
-SyncSpeed are somehow redundant, because they are reciprocal values 
-(1 / 112 ns = 8.9 MHz). At least in theory. The driver is able to adjust the
-NegoPeriod more accurate (4ns) than the SyncSpeed (1 / 25ns). I don't know
-if certain devices will have problems with this discrepancy. Max. speed is
-10 MHz corresp. to a min. NegoPeriod of 100 ns. 
-(The driver allows slightly higher speeds if the devices (Ultra SCSI) accept
-it, but that's out of adapter spec, on your own risk and unlikely to improve
-performance. You're likely to crash your disks.) 
-SyncOffs is the offset used for synchronous negotiations; max. is 15. 
-The last values are only shown, if Sync is enabled. (NegoPeriod is still
-displayed in brackets to show the values which will be used after enabling
-Sync.)
-MaxCmd ist the number of commands (=tags) which can be processed at the same
-time by the device.
-
-If you want to change a setting, you can do that by writing to
-/proc/scsi/tmscsim/?. Basically you have to imitate the output of driver.
-(Don't use the brackets for NegoPeriod on Sync disabled devices.)
-You don't have to care about capitalisation. The driver will accept space,
-tab, comma, = and : as separators.
-
-There are three kinds of changes: 
-
-(1) Change driver settings: 
-    You type the names of the parameters and the params following it.
-    Example:
-     echo "MaxLUN=8 seltimeout 200" >/proc/scsi/tmscsim/0
-
-    Note that you can only change MaxID, MaxLUN, AdapterID, SelTimeOut,
-    TagMaxNum, ACBFlag, GlitchEater and DelayReset. Don't change ACBFlag
-    unless you want to see what happens, if the driver hangs.
-
-(2) Change device settings: You write a config line to the driver. The Nr
-    must match the ID and LUN given. If you give "-" as parameter, it is
-    ignored and the corresponding setting won't be changed. 
-    You can use "y" or "n" instead of "Yes" and "No" if you want to.
-    You don't need to specify a full line. The driver automatically performs
-    an INQUIRY on the device if necessary to check if it is capable to operate
-    with the given settings (Sync, TagQ).
-    Examples:
-     echo "0 0 0 y y y - y - 10 " >/proc/scsi/tmscsim/0
-     echo "3 5 0 y n y " >/proc/scsi/tmscsim/0
-
-    To give a short explanation of the first example: 
-    The first three numbers, "0 0 0" (Device index 0, SCSI ID 0, SCSI LUN 0),
-    select the device to which the following parameters apply. Note that it
-    would be sufficient to use the index or both SCSI ID and LUN, but I chose
-    to require all three to have a syntax similar to the output.
-    The following "y y y - y" enables Parity checking, enables Synchronous
-    transfers, Disconnection, leaves Send Start (not used) untouched and
-    enables Tagged Command Queueing for the selected device. The "-" skips
-    the Negotiation Period setting but the "10" sets the max sync. speed to
-    10 MHz. It's useless to specify both NegoPeriod and SyncSpeed as
-    discussed above. The values used in this example will result in maximum
-    performance.
-
-(3) Special commands: You can force a SCSI bus reset, an INQUIRY command, the
-    removal or the addition of a device's DCB and a SCSI register dump.
-    This is only used for debugging when you meet problems. The parameter of
-    the INQUIRY and REMOVE commands is the device index as shown by the
-    output of /proc/scsi/tmscsim/? in the device listing in the first column
-    (Idx). ADD takes the SCSI ID and LUN.
-    Examples:
-     echo "reset" >/proc/scsi/tmscsim/0
-     echo "inquiry 1" >/proc/scsi/tmscsim/0
-     echo "remove 2" >/proc/scsi/tmscsim/1
-     echo "add 2 3" >/proc/scsi/tmscsim/?
-     echo "dump" >/proc/scsi/tmscsim/0
-
-    Note that you will meet problems when you REMOVE a device's DCB with the
-    remove command if it contains partitions which are mounted. Only use it
-    after unmounting its partitions, telling the SCSI mid-level code to
-    remove it (scsi remove-single-device) and you really need a few bytes of
-    memory.
-    The ADD command allows you to configure a device before you tell the
-    mid-level code to try detection.
-
-
-I'd suggest reviewing the output of /proc/scsi/tmscsim/? after changing
-settings to see if everything changed as requested.
-
-
-5. Configuration via boot/module parameters
--------------------------------------------
-With the DC390, the driver reads its EEPROM settings and tries to use them.
-But you may want to override the settings prior to being able to change the
-driver configuration via /proc/scsi/tmscsim/?.
-If you do have another AM53C974 based adapter, that's even the only
-possibility to adjust settings before you are able to write to the
-/proc/scsi/tmscsim/? pseudo-file, e.g. if you want to use another 
-adapter ID than 7.  
-(BTW, the log message "DC390: No EEPROM found!" is normal without a DC390.)
-For this purpose, you can pass options to the driver before it is initialised
-by using kernel or module parameters. See lilo(8) or modprobe(1) manual
-pages on how to pass params to the kernel or a module.
-[NOTE: Formerly, it was not possible to override the EEPROM supplied
- settings of the DC390 with cmd line parameters. This has changed since
- 2.0e7]
-
-The syntax of the params is much shorter than the syntax of the /proc/...
-interface. This makes it a little bit more difficult to use. However, long
-parameter lines have the risk to be misinterpreted and the length of kernel
-parameters is limited.
-
-As the support for non-DC390 adapters works by simulating the values of the
-DC390 EEPROM, the settings are given in a DC390 BIOS' way.
-
-Here's the syntax:
-tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds,DelayReset
-
-Each of the parameters is a number, containing the described information:
-
-* AdaptID: The SCSI ID of the host adapter. Must be in the range 0..7
-  Default is 7.
-
-* SpdIdx: The index of the maximum speed as in the DC390 BIOS. The values
-  0..7 mean 10, 8.0, 6.7, 5.7, 5.0, 4.0, 3.1 and 2 MHz resp. Default is
-  0 (10.0 MHz).
-
-* DevMode is a bit mapped value describing the per-device features. It
-  applies to all devices. (Sync, Disc and TagQ will only apply, if the
-  device supports it.) The meaning of the bits (* = default):
-
-   Bit Val(hex) Val(dec)  Meaning
-   *0	 0x01	    1	  Parity check
-   *1	 0x02	    2	  Synchronous Negotiation
-   *2	 0x04	    4	  Disconnection
-   *3	 0x08	    8	  Send Start command on startup. (Not used)
-   *4	 0x10	   16	  Tagged Command Queueing
-
-  As usual, the desired value is obtained by adding the wanted values. If
-  you want to enable all values, e.g., you would use 31(0x1f). Default is 31.
-
-* AdaptMode is a bit mapped value describing the enabled adapter features.
-
-   Bit Val(hex) Val(dec)  Meaning
-   *0	 0x01	    1	  Support more than two drives. (Not used)
-   *1	 0x02	    2	  Use DOS compatible mapping for HDs greater than 1GB.
-   *2	 0x04	    4	  Reset SCSI Bus on startup.
-   *3	 0x08	    8	  Active Negation: Improves SCSI Bus noise immunity.
-    4	 0x10	   16	  Immediate return on BIOS seek command. (Not used)
- (*)5	 0x20	   32	  Check for LUNs >= 1.
-  
-  The default for LUN Check depends on CONFIG_SCSI_MULTI_LUN.
-
-* TaggedCmnds is a number indicating the maximum number of Tagged Commands.
-  It is the binary logarithm - 1 of the actual number. Max is 4 (32).
-   Value  Number of Tagged Commands
-     0		 2
-     1		 4
-     2		 8
-    *3		16
-     4		32
-
-* DelayReset is the time in seconds (minus 0.5s), the adapter waits, after a
-  bus reset. Default is 1 (corresp. to 1.5s).
-
-Example:
- modprobe tmscsim tmscsim=6,2,31
-would set the adapter ID to 6, max. speed to 6.7 MHz, enable all device
-features and leave the adapter features, the number of Tagged Commands
-and the Delay after a reset to the defaults.
-
-As you can see, you don't need to specify all of the six params.
-If you want values to be ignored (i.e. the EEprom settings or the defaults
-will be used), you may pass -2 (not 0!) at the corresponding position.
-
-The defaults (7,0,31,15,3,1) are aggressive to allow good performance. You
-can use tmscsim=7,0,31,63,4,0 for maximum performance, if your SCSI chain
-allows it. If you meet problems, you can use tmscsim=-1 which is a shortcut
-for tmscsim=7,4,9,15,2,10.
-
-
-6. Potential improvements
--------------------------
-Most of the intended work on the driver has been done. Here are a few ideas
-to further improve its usability:
-
-* Cleanly separate per-Target and per-LUN properties (DCB)
-* More intelligent abort() routine
-* Use new_eh code (Linux-2.1+)
-* Have the mid-level (ML) code (and not the driver) handle more of the
-  various conditions.
-* Command queueing in the driver: Eliminate Query list and use ML instead.
-* More user friendly boot/module param syntax
-
-Further investigation on these problems:
-
-* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error)
-
-Known problems: 
-Please see http://www.garloff.de/kurt/linux/dc390/problems.html
-
-* Changing the parameters of multi-lun by the tmscsim/? interface will
-  cause problems, cause these settings are mostly per Target and not per LUN
-  and should be updated accordingly. To be fixed for 2.0d24.
-* CDRs (eg Yam CRW4416) not recognized, because some buggy devices don't 
-  recover from a SCSI reset in time. Use a higher delay or don't issue
-  a SCSI bus reset on driver initialization. See problems page.
-  For the CRW4416S, this seems to be solved with firmware 1.0g (reported by 
-  Jean-Yves Barbier).
-* TEAC CD-532S not being recognized. (Works with 1.11).
-* Scanners (eg. Astra UMAX 1220S) don't work: Disable Sync Negotiation.
-  If this does not help, try echo "INQUIRY t" >/proc/scsi/tmscsim/? (t
-  replaced by the dev index of your scanner). You may try to reset your SCSI
-  bus afterwards (echo "RESET" >/proc/scsi/tmscsim/?).
-  The problem seems to be solved as of 2.0d18, thanks to Andreas Rick.
-* If there is a valid partition table, the driver will use it for determing
-  the mapping. If there's none, a reasonable mapping (Symbios-like) will be
-  assumed. Other operating systems may not like this mapping, though
-  it's consistent with the BIOS' behaviour. Old DC390 drivers ignored the
-  partition table and used a H/S = 64/32 or 255/63 translation. So if you
-  want to be compatible to those, use this old mapping when creating
-  partition tables. Even worse, on bootup the DC390 might complain if other
-  mappings are found, so auto rebooting may fail.
-* In some situations, the driver will get stuck in an abort loop. This is a
-  bad interaction between the Mid-Layer of Linux' SCSI code and the driver.
-  Try to disable DsCn, if you meet this problem. Please contact me for
-  further debugging.
-
-
-7. Bug reports, debugging and updates
--------------------------------------
-Whenever you have problems with the driver, you are invited to ask the
-author for help. However, I'd suggest reading the docs and trying to solve
-the problem yourself, first. 
-If you find something, which you believe to be a bug, please report it to me. 
-Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and
-maybe the DC390 log messages to the report. 
-
-Bug reports should be send to me (Kurt Garloff <dc390@garloff.de>) as well
-as to the linux-scsi list (<linux-scsi@vger.kernel.org>), as sometimes bugs
-are caused by the SCSI mid-level code.
-
-I will ask you for some more details and probably I will also ask you to
-enable some of the DEBUG options in the driver (tmscsim.c:DC390_DEBUGXXX
-defines). The driver will produce some data for the syslog facility then.
-Beware: If your syslog gets written to a SCSI disk connected to your
-AM53C974, the logging might produce log output again, and you might end
-having your box spending most of its time doing the logging.
-
-The latest version of the driver can be found at:
- http://www.garloff.de/kurt/linux/dc390/
- ftp://ftp.suse.com/pub/people/garloff/linux/dc390/
-
-
-8. Acknowledgements
--------------------
-Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and 
-all the others for the wonderful OS and software.
-Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver
-release and support.
-Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding.
-Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert 
-Tonneau) for intensively testing the driver (and even risking data loss
-doing this during early revisions).
-Recently, SuSE GmbH, Nuernberg, FRG, has been paying me for the driver
-development and maintenance. Special thanks!
-
-
-9. Copyright
-------------
- This driver 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; version 2 of the License.
- If you want to use any later version of the GNU GPL, you will probably
- be allowed to, but you have to ask me and Tekram <erich@tekram.com.tw>
- before.
-
--------------------------------------------------------------------------
-Written by Kurt Garloff <kurt@garloff.de> 1998/06/11
-Last updated 2000/11/28, driver revision 2.0e7
-$Id: README.tmscsim,v 2.25.2.7 2000/12/20 01:07:12 garloff Exp $
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/scsi/aacraid/linit.c	Sun Nov 17 20:30:13 2002
@@ -204,6 +204,9 @@
 			 * specific information.
 			 */
 			host_ptr = scsi_register( template, sizeof(struct aac_dev) );
+			if(host_ptr == NULL)
+				continue;
+
 			/* 
 			 * These three parameters can be used to allow for wide SCSI 
 			 * and for host adapters that support multiple buses.
diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
--- a/drivers/scsi/aha152x.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/aha152x.c	Sun Nov 17 20:30:02 2002
@@ -216,7 +216,7 @@
  *
  **************************************************************************
  
- see README.aha152x for configuration details
+ see Documentation/scsi/aha152x.txt for configuration details
 
  **************************************************************************/
 
@@ -1859,7 +1859,7 @@
 				       "aha152x: unable to verify geometry for disk with >1GB.\n"
 				       "         Using default translation. Please verify yourself.\n"
 				       "         Perhaps you need to enable extended translation in the driver.\n"
-				       "         See /usr/src/linux/drivers/scsi/README.aha152x for details.\n");
+				       "         See /usr/src/linux/Documentation/scsi/aha152x.txt for details.\n");
 			}
 		} else {
 			info_array[0] = info[0];
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c	Sun Nov 17 20:30:13 2002
@@ -1074,7 +1074,7 @@
 		aic7xxx_setup(aic7xxx);
 	if (dummy_buffer[0] != 'P')
 		printk(KERN_WARNING
-"aic7xxx: Please read the file /usr/src/linux/drivers/scsi/README.aic7xxx\n"
+"aic7xxx: Please read the file /usr/src/linux/Documentation/scsi/aic7xxx.txt\n"
 "aic7xxx: to see the proper way to specify options to the aic7xxx module\n"
 "aic7xxx: Specifically, don't use any commas when passing arguments to\n"
 "aic7xxx: insmod or else it might trash certain memory areas.\n");
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h	Sun Nov 17 20:30:12 2002
@@ -65,6 +65,7 @@
 #include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
diff -Nru a/drivers/scsi/aic7xxx_old/README.aic7xxx b/drivers/scsi/aic7xxx_old/README.aic7xxx
--- a/drivers/scsi/aic7xxx_old/README.aic7xxx	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,511 +0,0 @@
-			    AIC7xxx Driver for Linux
-
-Introduction
-----------------------------
-The AIC7xxx SCSI driver adds support for Adaptec (http://www.adaptec.com)
-SCSI controllers and chipsets. Major portions of the driver and driver
-development are shared between both Linux and FreeBSD. Support for the
-AIC-7xxx chipsets have been in the default Linux kernel since approximately
-linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
-2.1.0 or later.
-
-  Supported cards/chipsets
-  ----------------------------
-    Adaptec Cards
-    ----------------------------
-    AHA-274x
-    AHA-274xT               
-    AHA-2842
-    AHA-2910B               
-    AHA-2920C
-    AHA-2930
-    AHA-2930U
-    AHA-2930CU
-    AHA-2930U2
-    AHA-2940               
-    AHA-2940W              
-    AHA-2940U              
-    AHA-2940UW
-    AHA-2940UW-PRO
-    AHA-2940AU 
-    AHA-2940U2W
-    AHA-2940U2
-    AHA-2940U2B
-    AHA-2940U2BOEM
-    AHA-2944D              
-    AHA-2944WD
-    AHA-2944UD
-    AHA-2944UWD
-    AHA-2950U2
-    AHA-2950U2W
-    AHA-2950U2B
-    AHA-29160M
-    AHA-3940
-    AHA-3940U
-    AHA-3940W
-    AHA-3940UW
-    AHA-3940AUW
-    AHA-3940U2W
-    AHA-3950U2B
-    AHA-3950U2D
-    AHA-3960D
-    AHA-39160M
-    AHA-3985
-    AHA-3985U
-    AHA-3985W
-    AHA-3985UW
-
-    Motherboard Chipsets
-    ----------------------------
-    AIC-777x   
-    AIC-785x
-    AIC-786x
-    AIC-787x
-    AIC-788x
-    AIC-789x
-    AIC-3860
-
-    Bus Types
-    ----------------------------
-    W - Wide SCSI, SCSI-3, 16bit bus, 68pin connector, will also support
-        SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
-    U - Ultra SCSI, transfer rates up to 40MB/s.
-    U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
-    D - Differential SCSI.
-    T - Twin Channel SCSI. Up to 14 SCSI devices.
-
-    AHA-274x - EISA SCSI controller
-    AHA-284x - VLB SCSI controller
-    AHA-29xx - PCI SCSI controller
-    AHA-394x - PCI controllers with two separate SCSI controllers on-board.
-    AHA-398x - PCI RAID controllers with three separate SCSI controllers
-               on-board.
-
-  Not Supported Devices
-  ------------------------------
-    Adaptec Cards
-    ----------------------------
-    AHA-2920 (Only the cards that use the Future Domain chipset are not
-              supported, any 2920 cards based on Adaptec AIC chipsets,
-	      such as the 2920C, are supported)
-    AAA-13x Raid Adapters
-    AAA-113x Raid Port Card
-
-    Motherboard Chipsets
-    ----------------------------
-    AIC-7810
-
-    Bus Types
-    ----------------------------
-    R - Raid Port busses are not supported.
-
-    The hardware RAID devices sold by Adaptec are *NOT* supported by this
-    driver (and will people please stop emailing me about them, they are
-    a totally separate beast from the bare SCSI controllers and this driver
-    can not be retrofitted in any sane manner to support the hardware RAID
-    features on those cards - Doug Ledford).
-    
-
-  People
-  ------------------------------
-    Justin T Gibbs  gibbs@plutotech.com
-      (BSD Driver Author)
-    Dan Eischen     deischen@iworks.InterWorks.org
-      (Original Linux Driver Co-maintainer)
-    Dean Gehnert    deang@teleport.com
-      (Original Linux FTP/patch maintainer)
-    Jess Johnson    jester@frenzy.com
-      (AIC7xxx FAQ author)
-    Doug Ledford    dledford@redhat.com
-      (Current Linux aic7xxx-5.x.x Driver/Patch/FTP maintainer)
-    
-    Special thanks go to John Aycock (aycock@cpsc.ucalgary.ca), the original
-    author of the driver. John has since retired from the project. Thanks
-    again for all his work!
-    
-  Mailing list
-  ------------------------------
-    There is a mailing list available for users who want to track development
-    and converse with other users and developers. This list is for both
-    FreeBSD and Linux support of the AIC7xxx chipsets.
-
-    To subscribe to the AIC7xxx mailing list send mail to the list server,
-    with "subscribe AIC7xxx" in the body (no Subject: required):
-        To: majordomo@FreeBSD.ORG
-        ---
-        subscribe AIC7xxx
-
-    To unsubscribe from the list, send mail to the list server with:
-        To: majordomo@FreeBSD.ORG
-        ---
-        unsubscribe AIC7xxx
-
-    Send regular messages and replies to: AIC7xxx@FreeBSD.ORG
-    
-  Boot Command line options
-  ------------------------------
-    "aic7xxx=no_reset" -  Eliminate the SCSI bus reset during startup.
-        Some SCSI devices need the initial reset that this option disables
-	in order to work.  If you have problems at bootup, please make sure
-	you aren't using this option.
-	
-    "aic7xxx=reverse_scan" - Certain PCI motherboards scan for devices at
-        bootup by scanning from the highest numbered PCI device to the
-	lowest numbered PCI device, others do just the opposite and scan
-	from lowest to highest numbered PCI device.  There is no reliable
-	way to autodetect this ordering.  So, we default to the most common
-	order, which is lowest to highest.  Then, in case your motherboard
-	scans from highest to lowest, we have this option.  If your BIOS
-	finds the drives on controller A before controller B but the linux
-	kernel finds your drives on controller B before A, then you should
-	use this option.
-	
-    "aic7xxx=extended" - Force the driver to detect extended drive translation
-        on your controller.  This helps those people who have cards without
-        a SEEPROM make sure that linux and all other operating systems think
-        the same way about your hard drives.
-
-    "aic7xxx=scbram" - Some cards have external SCB RAM that can be used to
-        give the card more hardware SCB slots.  This allows the driver to use
-	that SCB RAM.  Without this option, the driver won't touch the SCB
-	RAM because it is known to cause problems on a few cards out there
-	(such as 3985 class cards).
-	
-    "aic7xxx=irq_trigger:x" - Replace x with either 0 or 1 to force the kernel
-        to use the correct IRQ type for your card.  This only applies to EISA
-        based controllers.  On these controllers, 0 is for Edge triggered
-        interrupts, and 1 is for Level triggered interrupts.  If you aren't
-        sure or don't know which IRQ trigger type your EISA card uses, then
-        let the kernel autodetect the trigger type.
-	
-    "aic7xxx=verbose" - This option can be used in one of two ways.  If you
-        simply specify aic7xxx=verbose, then the kernel will automatically
-	pick the default set of verbose messages for you to see.
-	Alternatively, you can specify the command as 
-	"aic7xxx=verbose:0xXXXX" where the X entries are replaced with
-	hexadecimal digits.  This option is a bit field type option.  For
-	a full listing of the available options, search for the 
-	#define VERBOSE_xxxxxx lines in the aic7xxx.c file.  If you want
-	verbose messages, then it is recommended that you simply use the
-	aic7xxx=verbose variant of this command.
-	
-    "aic7xxx=pci_parity:x" - This option controls whether or not the driver
-        enables PCI parity error checking on the PCI bus.  By default, this
-        checking is disabled.  To enable the checks, simply specify pci_parity
-        with no value afterwords.  To reverse the parity from even to odd,
-        supply any number other than 0 or 255.  In short:
-          pci_parity     - Even parity checking (even is the normal PCI parity)
-          pci_parity:x   - Where x > 0, Odd parity checking
-          pci_parity:0   - No check (default)
-        NOTE: In order to get Even PCI parity checking, you must use the
-        version of the option that does not include the : and a number at
-        the end (unless you want to enter exactly 2^32 - 1 as the number).
-	
-    "aic7xxx=no_probe" - This option will disable the probing for any VLB
-        based 2842 controllers and any EISA based controllers.  This is
-	needed on certain newer motherboards where the normal EISA I/O ranges
-	have been claimed by other PCI devices.  Probing on those machines
-	will often result in the machine crashing or spontaneously rebooting
-	during startup.  Examples of machines that need this are the
-	Dell PowerEdge 6300 machines.
-
-    "aic7xxx=seltime:2" - This option controls how long the card waits
-        during a device selection sequence for the device to respond.
-	The original SCSI spec says that this "should be" 256ms.  This
-	is generally not required with modern devices.  However, some
-	very old SCSI I devices need the full 256ms.  Most modern devices
-	can run fine with only 64ms.  The default for this option is
-	64ms.  If you need to change this option, then use the following
-	table to set the proper value in the example above:
-	  0  -  256ms
-	  1  -  128ms
-	  2  -   64ms
-	  3  -   32ms
-	
-    "aic7xxx=panic_on_abort" - This option is for debugging and will cause
-        the driver to panic the linux kernel and freeze the system the first
-	time the drivers abort or reset routines are called.  This is most
-	helpful when some problem causes infinite reset loops that scroll too
-	fast to see.  By using this option, you can write down what the errors
-	actually are and send that information to me so it can be fixed.
-	
-    "aic7xxx=dump_card" - This option will print out the *entire* set of
-        configuration registers on the card during the init sequence.  This
-	is a debugging aid used to see exactly what state the card is in
-	when we finally finish our initialization routines.  If you don't
-	have documentation on the chipsets, this will do you absolutely
-	no good unless you are simply trying to write all the information
-	down in order to send it to me.
-	
-    "aic7xxx=dump_sequencer" - This is the same as the above options except
-        that instead of dumping the register contents on the card, this
-	option dumps the contents of the sequencer program RAM.  This gives
-	the ability to verify that the instructions downloaded to the
-	card's sequencer are indeed what they are suppossed to be.  Again,
-	unless you have documentation to tell you how to interpret these
-	numbers, then it is totally useless.
-	
-    "aic7xxx=override_term:0xffffffff" - This option is used to force the
-    	termination on your SCSI controllers to a particular setting.  This
-	is a bit mask variable that applies for up to 8 aic7xxx SCSI channels.
-	Each channel gets 4 bits, divided as follows:
-	bit   3   2   1   0
-	      |   |   |   Enable/Disable Single Ended Low Byte Termination
-	      |   |   En/Disable Single Ended High Byte Termination
-	      |   En/Disable Low Byte LVD Termination
-	      En/Disable High Byte LVD Termination
-
-	The upper 2 bits that deal with LVD termination only apply to Ultra2
-	controllers.  Futhermore, due to the current Ultra2 controller
-	designs, these bits are tied together such that setting either bit
-	enables both low and high byte LVD termination.  It is not possible
-	to only set high or low byte LVD termination in this manner.  This is
-	an artifact of the BIOS definition on Ultra2 controllers.  For other
-	controllers, the only important bits are the two lowest bits.  Setting
-	the higher bits on non-Ultra2 controllers has no effect.  A few
-	examples of how to use this option:
-
-	Enable low and high byte termination on a non-ultra2 controller that
-	is the first aic7xxx controller (the correct bits are 0011), 
-	aic7xxx=override_term:0x3
-
-	Enable all termination on the third aic7xxx controller, high byte
-	termination on the second aic7xxx controller, and low and high byte
-	SE termination on the first aic7xxx controller 
-	(bits are 1111 0010 0011), 
-	aic7xxx=override_term:0xf23
-	
-	No attempt has been made to make this option non-cryptic.  It really
-	shouldn't be used except in dire circumstances, and if that happens,
-	I'm probably going to be telling you what to set this to anyway :)
-
-    "aic7xxx=stpwlev:0xffffffff" - This option is used to control the STPWLEV
-        bit in the DEVCONFIG PCI register.  Currently, this is one of the
-	very few registers that we have absolutely *no* way of detecting
-	what the variable should be.  It depends entirely on how the chipset
-	and external terminators were coupled by the card/motherboard maker.
-	Further, a chip reset (at power up) always sets this bit to 0.  If
-	there is no BIOS to run on the chipset/card (such as with a 2910C
-	or a motherboard controller with the BIOS totally disabled) then
-	the variable may not get set properly.  Of course, if the proper
-	setting was 0, then that's what it would be after the reset, but if
-	the proper setting is actually 1.....you get the picture.  Now, since
-	we can't detect this at all, I've added this option to force the
-	setting.  If you have a BIOS on your controller then you should never
-	need to use this option.  However, if you are having lots of SCSI
-	reset problems and can't seem to get them knocked out, this may help.
-
-	Here's a test to know for certain if you need this option.  Make
-	a boot floppy that you can use to boot your computer up and that
-	will detect the aic7xxx controller.  Next, power down your computer.
-	While it's down, unplug all SCSI cables from your Adaptec SCSI
-	controller.  Boot the system back up to the Adaptec EZ-SCSI BIOS
-	and then make sure that termination is enabled on your adapter (if
-	you have an Adaptec BIOS of course).  Next, boot up the floppy you
-	made and wait for it to detect the aic7xxx controller.  If the kernel
-	finds the controller fine, says scsi : x hosts and then tries to
-	detect your devices like normal, up to the point where it fails to
-	mount your root file system and panics, then you're fine.  If, on
-	the other hand, the system goes into an infinite reset loop, then
-	you need to use this option and/or the previous option to force the
-	proper termination settings on your controller.   If this happens,
-	then you next need to figure out what your settings should be.
-
-	To find the correct settings, power your machine back down, connect
-	back up the SCSI cables, and boot back into your machine like normal.
-	However, boot with the aic7xxx=verbose:0x39 option.  Record the
-	initial DEVCONFIG values for each of your aic7xxx controllers as
-	they are listed, and also record what the machine is detecting as
-	the proper termination on your controllers.  NOTE: the order in
-	which the initial DEVCONFIG values are printed out is not gauranteed
-	to be the same order as the SCSI controllers are registered.  The
-	above option and this option both work on the order of the SCSI
-	controllers as they are registered, so make sure you match the right
-	DEVCONFIG values with the right controllers if you have more than
-	one aic7xxx controller.
-
-	Once you have the detected termination settings and the initial
-	DEVCONFIG values for each controller, then figure out what the
-	termination on each of the controllers *should* be.  Hopefully, that
-	part is correct, but it could possibly be wrong if there is
-	bogus cable detection logic on your controller or something similar.
-	If all the controllers have the correct termination settings, then
-	don't set the aic7xxx=override_term variable at all, leave it alone.
-	Next, on any controllers that go into an infinite reset loop when
-	you unplug all the SCSI cables, get the starting DEVCONFIG value.
-	If the initial DEVCONFIG value is divisible by 2, then the correct
-	setting for that controller is 0.  If it's an odd number, then
-	the correct setting for that controller is 1.  For any other
-	controllers that didn't have an infinite reset problem, then reverse
-	the above options.  If DEVCONFIG was even, then the correct setting
-	is 1, if not then the correct setting is 0.
-
-	Now that you know what the correct setting was for each controller,
-	we need to encode that into the aic7xxx=stpwlev:0x... variable.
-	This variable is a bit field encoded variable.  Bit 0 is for the first
-	aic7xxx controller, bit 1 for the next, etc.  Put all these bits
-	together and you get a number.  For example, if the third aic7xxx
-	needed a 1, but the second and first both needed a 0, then the bits
-	would be 100 in binary.  This then translates to 0x04.  You would
-	therefore set aic7xxx=stpwlev:0x04.  This is fairly standard binary
-	to hexadecimal conversions here.  If you aren't up to speed on the
-	binary->hex conversion then send an email to the aic7xxx mailing
-	list and someone can help you out.
-
-    "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
-        or enable Tagged Command Queueing (TCQ) on specific devices.  As of
-	driver version 5.1.11, TCQ is now either on or off by default
-	according to the setting you choose during the make config process.
-	In order to en/disable TCQ for certian devices at boot time, a user
-	may use this boot param.  The driver will then parse this message out
-        and en/disable the specific device entries that are present based upon
-        the value given.  The param line is parsed in the following manner:
-
-          { - first instance indicates the start of this parameter values
-              second instance is the start of entries for a particular
-              device entry
-          } - end the entries for a particular host adapter, or end the entire
-              set of parameter entries
-          , - move to next entry.  Inside of a set of device entries, this
-              moves us to the next device on the list.  Outside of device
-              entries, this moves us to the next host adapter
-          . - Same effect as , but is safe to use with insmod.
-          x - the number to enter into the array at this position.  
-              0 = Enable tagged queueing on this device and use the default
-                  queue depth
-              1-254 = Enable tagged queueing on this device and use this
-                      number as the queue depth
-              255 = Disable tagged queueing on this device.
-              Note: anything above 32 for an actual queue depth is wasteful
-                    and not recommended.
-
-        A few examples of how this can be used:
-
-        tag_info:{{8,12,,0,,255,4}}
-          This line will only effect the first aic7xxx card registered.  It
-          will set scsi id 0 to a queue depth of 8, id 1 to 12, leave id 2
-          at the default, set id 3 to tagged queueing enabled and use the
-          default queue depth, id 4 default, id 5 disabled, and id 6 to 4.
-          Any not specified entries stay at the default value, repeated
-          commas with no value specified will simply increment to the next id
-          without changing anything for the missing values.
-
-        tag_info:{,,,{,,,255}}
-          First, second, and third adapters at default values.  Fourth
-          adapter, id 3 is disabled.  Notice that leading commas simply
-	  increment what the first number effects, and there are no need
-	  for trailing commas.  When you close out an adapter, or the
-	  entire entry, anything not explicitly set stays at the default
-	  value.
-
-        A final note on this option.  The scanner I used for this isn't
-        perfect or highly robust.  If you mess the line up, the worst that
-        should happen is that the line will get ignored.  If you don't
-        close out the entire entry with the final bracket, then any other
-        aic7xxx options after this will get ignored.  So, in general, be
-        sure of what you are entering, and after you have it right, just
-        add it to the lilo.conf file so there won't be any mistakes.  As
-        a means of checking this parser, the entire tag_info array for
-        each card is now printed out in the /proc/scsi/aic7xxx/x file.  You
-        can use that to verify that your options were parsed correctly. 
-        
-    Boot command line options may be combined to form the proper set of options
-    a user might need.  For example, the following is valid:
-    
-    aic7xxx=verbose,extended,irq_trigger:1
-    
-    The only requirement is that individual options be separated by a comma or
-    a period on the command line.
-        
-  Module Loading command options
-  ------------------------------
-    When loading the aic7xxx driver as a module, the exact same options are
-    available to the user.  However, the syntax to specify the options changes
-    slightly.  For insmod, you need to wrap the aic7xxx= argument in quotes
-    and replace all ',' with '.'.  So, for example, a valid insmod line
-    would be:
-
-    insmod aic7xxx aic7xxx='verbose.irq_trigger:1.extended'
-
-    This line should result in the *exact* same behaviour as if you typed
-    it in at the lilo prompt and the driver was compiled into the kernel
-    instead of being a module.  The reason for the single quote is so that
-    the shell won't try to interpret anything in the line, such as {. 
-    Insmod assumes any options starting with a letter instead of a number
-    is a character string (which is what we want) and by switching all of
-    the commas to periods, insmod won't interpret this as more than one
-    string and write junk into our binary image.  I consider it a bug in
-    the insmod program that even if you wrap your string in quotes (quotes
-    that pass the shell mind you and that insmod sees) it still treates
-    a comma inside of those quotes as starting a new variable, resulting
-    in memory scribbles if you don't switch the commas to periods.
-
-
-  Kernel Compile options
-  ------------------------------
-    The various kernel compile time options for this driver are now fairly
-    well documented in the file Documentation/Configure.help.  In order to
-    see this documentation, you need to use one of the advanced configuration
-    programs (menuconfig and xconfig).  If you are using the "make menuconfig"
-    method of configuring your kernel, then you would simply highlight the
-    option in question and hit the ? key.  If you are using the "make xconfig"
-    method of configuring your kernel, then simply click on the help button
-    next to the option you have questions about.  The help information from
-    the Configure.help file will then get automatically displayed.
-
-  /proc support
-  ------------------------------
-    The /proc support for the AIC7xxx can be found in the /proc/scsi/aic7xxx/
-    directory. That directory contains a file for each SCSI controller in
-    the system. Each file presents the current configuration and transfer
-    statistics (enabled with #define in aic7xxx.c) for each controller.
-
-    Thanks to Michael Neuffer for his upper-level SCSI help, and
-    Matthew Jacob for statistics support.
-
-  Debugging the driver
-  ------------------------------
-    Should you have problems with this driver, and would like some help in
-    getting them solved, there are a couple debugging items built into
-    the driver to facilitate getting the needed information from the system.
-    In general, I need a complete description of the problem, with as many
-    logs as possible concerning what happens.  To help with this, there is
-    a command option aic7xxx=panic_on_abort.  This option, when set, forces
-    the driver to panic the kernel on the first SCSI abort issued by the
-    mid level SCSI code.  If your system is going to reset loops and you
-    can't read the screen, then this is what you need.  Not only will it
-    stop the system, but it also prints out a large amount of state
-    information in the process.  Second, if you specify the option
-    "aic7xxx=verbose:0x1ffff", the system will print out *SOOOO* much
-    information as it runs that you won't be able to see anything.
-    However, this can actually be very useful if your machine simply
-    locks up when trying to boot, since it will pin-point what was last
-    happening (in regards to the aic7xxx driver) immediately prior to
-    the lockup.  This is really only useful if your machine simply can
-    not boot up successfully.  If you can get your machine to run, then
-    this will produce far too much information.
-
-  FTP sites
-  ------------------------------
-    ftp://ftp.redhat.com/pub/aic/
-      - Out of date.  I used to keep stuff here, but too many people
-        complained about having a hard time getting into Red Hat's ftp
-	server.  So use the web site below instead.
-    ftp://ftp.pcnet.com/users/eischen/Linux/
-      - Dan Eischen's driver distribution area
-    ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
-      - European Linux mirror of Teleport site
-
-  Web sites
-  ------------------------------
-    http://people.redhat.com/dledford/
-      - My web site, also the primary aic7xxx site with several related
-        pages.
-
-Dean W. Gehnert
-deang@teleport.com
-
-$Revision: 3.0 $
-
-Modified by Doug Ledford 1998-2000
-
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/scsi/aic7xxx_old.c	Sun Nov 17 20:30:13 2002
@@ -9310,7 +9310,8 @@
           pci_write_config_dword(pdev, DEVCONFIG, devconfig);
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
 
-          if(temp_p->base && check_region(temp_p->base, MAXREG - MINREG))
+          if(temp_p->base && !request_region(temp_p->base, MAXREG - MINREG,
+				  "aic7xxx"))
           {
             printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
@@ -9389,12 +9390,6 @@
 #endif
 
           /*
-           * Lock out other contenders for our i/o space.
-           */
-          if(temp_p->base)
-            request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
-
-          /*
            * We HAVE to make sure the first pause_sequencer() and all other
            * subsequent I/O that isn't PCI config space I/O takes place
            * after the MMAPed I/O region is configured and tested.  The
@@ -9742,7 +9737,7 @@
   {
     base = SLOTBASE(slot) + MINREG;
 
-    if (check_region(base, MAXREG - MINREG))
+    if (!request_region(base, MAXREG - MINREG, "aic7xxx"))
     {
       /*
        * Some other driver has staked a
@@ -9755,6 +9750,7 @@
     type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
     if (type == -1)
     {
+      release_region(base, MAXREG - MINREG);
       slot++;
       continue;
     }
@@ -9762,13 +9758,10 @@
     if (temp_p == NULL)
     {
       printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+      release_region(base, MAXREG - MINREG);
       slot++;
       continue; /* back to the beginning of the while loop */
     }
-    /*
-     * Lock out other contenders for our i/o space.
-     */
-    request_region(base, MAXREG - MINREG, "aic7xxx");
 
     /*
      * Pause the card preserving the IRQ type.  Allow the operator
@@ -10972,6 +10965,10 @@
  *
  * Description:
  *   Return the disk geometry for the given SCSI device.
+ *
+ * Note:
+ *   This function is broken for today's really large drives and needs
+ *   fixed.
  *-F*************************************************************************/
 int
 aic7xxx_biosparam(struct scsi_device *sdev, struct block_device *bdev,
diff -Nru a/drivers/scsi/cpqfc.Readme b/drivers/scsi/cpqfc.Readme
--- a/drivers/scsi/cpqfc.Readme	Sun Nov 17 20:30:16 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,275 +0,0 @@
-Notes for CPQFCTS driver for Compaq Tachyon TS
-Fibre Channel Host Bus Adapter, PCI 64-bit, 66MHz
-for Linux (RH 6.1, 6.2 kernel 2.2.12-32, 2.2.14-5)
-SMP tested
-Tested in single and dual HBA configuration, 32 and 64bit busses,
-33 and 66MHz.  Only supports FC-AL.
-SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() 
-	max of 128k bytes contiguous.
-
-Ver 2.5.4  Oct 03, 2002
-   * fixed memcpy of sense buffer in ioctl to copy the smaller defined size
-Ver 2.5.3  Aug 01, 2002
-   * fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
-Ver 2.5.1  Jul 30, 2002
-   * fix ioctl to pay attention to the specified LUN.
-Ver 2.5.0  Nov 29, 2001
-   * eliminated io_request_lock.  This change makes the driver specific
-     to the 2.5.x kernels.
-   * silenced excessively noisy printks.
-
-Ver 2.1.2  July 23, 2002
-   * initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
-
-Ver 2.1.1  Oct 18, 2001
-   * reinitialize Cmnd->SCp.sent_command (used to identify commands as
-     passthrus) on calling scsi_done, since the scsi mid layer does not
-     use (or reinitialize) this field to prevent subsequent comands from
-     having it set incorrectly. 
-
-Ver 2.1.0  Aug 27, 2001
-   * Revise driver to use new kernel 2.4.x PCI DMA API, instead of 
-     virt_to_bus().  (enables driver to work w/ ia64 systems with >2Gb RAM.)
-     Rework main scatter-gather code to handle cases where SG element
-     lengths are larger than 0x7FFFF bytes and use as many scatter 
-     gather pages as necessary. (Steve Cameron)
-   * Makefile changes to bring cpqfc into line w/ rest of SCSI drivers
-     (thanks to Keith Owens)
-
-Ver 2.0.5  Aug 06, 2001
-   * Reject non-existent luns in the driver rather than letting the 
-     hardware do it.  (some HW behaves differently than others in this area.)
-   * Changed Makefile to rely on "make dep" instead of explicit dependencies
-   * ifdef'ed out fibre channel analyzer triggering debug code
-   * fixed a jiffies wrapping issue
-
-Ver 2.0.4  Aug 01, 2001
-   * Incorporated fix for target device reset from Steeleye
-   * Fixed passthrough ioctl so it doesn't hang.
-   * Fixed hang in launch_FCworker_thread() that occurred on some machines.
-   * Avoid problem when number of volumes in a single cabinet > 8
-
-Ver 2.0.2  July 23, 2001
-   Changed the semiphore changes so the driver would compile in 2.4.7. 
-   This version is for 2.4.7 and beyond. 
- 
-Ver 2.0.1  May 	7, 2001
-   Merged version 1.3.6 fixes into version 2.0.0.   
-
-Ver 2.0.0  May   7, 2001
-  Fixed problem so spinlock is being initialized to UNLOCKED. 
-  Fixed updated driver so it compiles in the 2.4 tree. 
- 
- Ver 1.3.6  Feb  27, 2001
-   Added Target_Device_Reset function for SCSI error handling
-   Fixed problem with not reseting addressing mode after implicit logout
- 
-
-Ver 1.3.4  Sep   7, 2000
-  Added Modinfo information
-  Fixed problem with statically linking the driver
-
-Ver 1.3.3, Aug  23, 2000
-  Fixed device/function number in ioctl
-
-Ver 1.3.2, July 27, 2000
-  Add include for Alpha compile on 2.2.14 kernel (cpq*i2c.c)
-  Change logic for different FCP-RSP sense_buffer location for HSG80 target
-  And search for Agilent Tachyon XL2 HBAs (not finished! - in test)
-
-Tested with 
-(storage):
-           Compaq RA-4x000, RAID firmware ver 2.40 - 2.54
-           Seagate FC drives model ST39102FC, rev 0006
-           Hitachi DK31CJ-72FC rev J8A8
-           IBM DDYF-T18350R rev F60K
-           Compaq FC-SCSI bridge w/ DLT 35/70 Gb DLT (tape)
-(servers):
-           Compaq PL-1850R
-           Compaq PL-6500 Xeon (400MHz)
-	   Compaq PL-8500 (500MHz, 66MHz, 64bit PCI)
-           Compaq Alpha DS20 (RH 6.1)
-(hubs):
-           Vixel Rapport 1000 (7-port "dumb")
-	   Gadzoox Gibralter (12-port "dumb")
-	   Gadzoox Capellix 2000, 3000 
-(switches):
-           Brocade 2010, 2400, 2800, rev 2.0.3a (& later)
-           Gadzoox 3210 (Fabric blade beta)
-           Vixel 7100 (Fabric beta firmare - known hot plug issues)
-using "qa_test" (esp. io_test script) suite modified from Unix tests.
-	
-Installation:
-copy file cpqfcTS.patch to /usr/src/linux
-patch -p1 < cpqfcTS.patch
-make menuconfig
-  (select SCSI low-level, Compaq FC HBA)
-make dep
-make modules
-make modules_install
-
-e.g. insmod -f cpqfc
-
-Due to Fabric/switch delays, driver requires 4 seconds 
-to initialize.  If adapters are found, there will be a entries at
-/proc/scsi/cpqfcTS/*
-
-sample contents of startup messages
-
-*************************
- scsi_register allocating 3596 bytes for CPQFCHBA
- ioremap'd Membase: c887e600
-  HBA Tachyon RevId 1.2
-Allocating 119808 for 576 Exchanges @ c0dc0000
-Allocating 112904 for LinkQ @ c0c20000 (576 elements)
-Allocating 110600 for TachSEST for 512 Exchanges
-  cpqfcTS: writing IMQ BASE 7C0000h    PI 7C4000h
-  cpqfcTS: SEST c0e40000(virt): Wrote base E40000h @ c887e740
-cpqfcTS: New FC port 0000E8h WWN: 500507650642499D SCSI Chan/Trgt 0/0
-cpqfcTS: New FC port 0000EFh WWN: 50000E100000D5A6 SCSI Chan/Trgt 0/1
-cpqfcTS: New FC port 0000E4h WWN: 21000020370097BB SCSI Chan/Trgt 0/2
-cpqfcTS: New FC port 0000E2h WWN: 2100002037009946 SCSI Chan/Trgt 0/3
-cpqfcTS: New FC port 0000E1h WWN: 21000020370098FE SCSI Chan/Trgt 0/4
-cpqfcTS: New FC port 0000E0h WWN: 21000020370097B2 SCSI Chan/Trgt 0/5
-cpqfcTS: New FC port 0000DCh WWN: 2100002037006CC1 SCSI Chan/Trgt 0/6
-cpqfcTS: New FC port 0000DAh WWN: 21000020370059F6 SCSI Chan/Trgt 0/7
-cpqfcTS: New FC port 00000Fh WWN: 500805F1FADB0E20 SCSI Chan/Trgt 0/8
-cpqfcTS: New FC port 000008h WWN: 500805F1FADB0EBA SCSI Chan/Trgt 0/9
-cpqfcTS: New FC port 000004h WWN: 500805F1FADB1EB9 SCSI Chan/Trgt 0/10
-cpqfcTS: New FC port 000002h WWN: 500805F1FADB1ADE SCSI Chan/Trgt 0/11
-cpqfcTS: New FC port 000001h WWN: 500805F1FADBA2CA SCSI Chan/Trgt 0/12
-scsi4 : Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2: WWN 500508B200193F50
- on PCI bus 0 device 0xa0fc irq 5 IObaseL 0x3400, MEMBASE 0xc6ef8600
-PCI bus width 32 bits, bus speed 33 MHz
-FCP-SCSI Driver v1.3.0
-GBIC detected: Short-wave.  LPSM 0h Monitor
-scsi : 5 hosts.
-  Vendor: IBM       Model: DDYF-T18350R      Rev: F60K
-  Type:   Direct-Access                      ANSI SCSI revision: 03
-Detected scsi disk sdb at scsi4, channel 0, id 0, lun 0
-  Vendor: HITACHI   Model: DK31CJ-72FC       Rev: J8A8
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdc at scsi4, channel 0, id 1, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdd at scsi4, channel 0, id 2, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sde at scsi4, channel 0, id 3, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdf at scsi4, channel 0, id 4, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdg at scsi4, channel 0, id 5, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdh at scsi4, channel 0, id 6, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdi at scsi4, channel 0, id 7, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdj at scsi4, channel 0, id 8, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdk at scsi4, channel 0, id 8, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdl at scsi4, channel 0, id 9, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdm at scsi4, channel 0, id 9, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdn at scsi4, channel 0, id 10, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdo at scsi4, channel 0, id 11, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdp at scsi4, channel 0, id 11, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdq at scsi4, channel 0, id 12, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdr at scsi4, channel 0, id 12, lun 1
-resize_dma_pool: unknown device type 12
-resize_dma_pool: unknown device type 12
-SCSI device sdb: hdwr sector= 512 bytes. Sectors= 35843670 [17501 MB] [17.5 GB]
- sdb: sdb1
-SCSI device sdc: hdwr sector= 512 bytes. Sectors= 144410880 [70513 MB] [70.5 GB]
- sdc: sdc1
-SCSI device sdd: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdd: sdd1
-SCSI device sde: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sde: sde1
-SCSI device sdf: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdf: sdf1
-SCSI device sdg: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdg: sdg1
-SCSI device sdh: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdh: sdh1
-SCSI device sdi: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdi: sdi1
-SCSI device sdj: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
- sdj: sdj1
-SCSI device sdk: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
- sdk: sdk1
-SCSI device sdl: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdl: sdl1
-SCSI device sdm: hdwr sector= 512 bytes. Sectors= 8380320 [4091 MB] [4.1 GB]
- sdm: sdm1
-SCSI device sdn: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdn: sdn1
-SCSI device sdo: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdo: sdo1
-SCSI device sdp: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdp: sdp1
-SCSI device sdq: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
- sdq: sdq1
-SCSI device sdr: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
- sdr: sdr1
-
-*************************
-
-If a GBIC of type Short-wave, Long-wave, or Copper is detected, it will
-print out; otherwise, "none" is displayed.  If the cabling is correct
-and a loop circuit is completed, you should see "Monitor"; otherwise, 
-"LoopFail" (on open circuit) or some LPSM number/state with bit 3 set.
-
-
-ERRATA:
-1. Normally, Linux Scsi queries FC devices with INQUIRY strings.  All LUNs
-found according to INQUIRY should get READ commands at sector 0 to find
-partition table, etc.  Older kernels only query the first 4 devices.  Some
-Linux kernels only look for one LUN per target (i.e. FC device).
-
-2. Physically removing a device, or a malfunctioning system which hides a
-device, leads to a 30-second timeout and subsequent _abort call.  
-In some process contexts, this will hang the kernel (crashing the system).
-Single bit errors in frames and virtually all hot plugging events are 
-gracefully handled with internal driver timer and Abort processing.
-
-3. Some SCSI drives with error conditions will not handle the 7 second timeout
-in this software driver, leading to infinite retries on timed out SCSI commands.
-The 7 secs balances the need to quickly recover from lost frames (esp. on sequence
-initiatives) and time needed by older/slower/error-state drives in responding.
-This can be easily changed in "Exchanges[].timeOut".
-
-4. Due to the nature of FC soft addressing, there is no assurance that the 
-same LUNs (drives) will have the same path (e.g. /dev/sdb1) from one boot to
-next.  Dynamic soft address changes (i.e. 24-bit FC port_id) are
-supported during run time (e.g. due to hot plug event) by the use of WWN to
-SCSI Nexus (channel/target/LUN) mapping.
-
-5. Compaq RA4x00 firmware version 2.54 and later supports SSP (Selective 
-Storage Presentation), which maps LUNs to a WWN.  If RA4x00 firmware prior
-2.54 (e.g. older controller) is used, or the FC HBA is replaced (another WWN
-is used), logical volumes on the RA4x00 will no longer be visible.
-
-
-Send questions/comments to:
-Amy Vanzant-Hodge (fibrechannel@compaq.com)
-
diff -Nru a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h
--- a/drivers/scsi/dpt/dpti_ioctl.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/scsi/dpt/dpti_ioctl.h	Sun Nov 17 20:30:13 2002
@@ -5,7 +5,8 @@
     copyright            : (C) 2001 by Adaptec
     email                : deanna_bonds@adaptec.com
 
-    See README.dpti for history, notes, license info, and credits
+    See Documentation/scsi/dpti.txt for history, notes, license info
+    and credits
  ***************************************************************************/
 
 /***************************************************************************
diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
--- a/drivers/scsi/dpt_i2o.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/dpt_i2o.c	Sun Nov 17 20:30:15 2002
@@ -5,10 +5,11 @@
     copyright            : (C) 2000 by Adaptec
     email                : deanna_bonds@adaptec.com
 
-    			   July 30, 2001 First version being submitted
+			   July 30, 2001 First version being submitted
 			   for inclusion in the kernel.  V2.4
 
-    See README.dpti for history, notes, license info, and credits
+    See Documentation/scsi/dpti.txt for history, notes, license info
+    and credits
  ***************************************************************************/
 
 /***************************************************************************
diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
--- a/drivers/scsi/dpti.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/dpti.h	Sun Nov 17 20:30:02 2002
@@ -5,7 +5,8 @@
     copyright            : (C) 2001 by Adaptec
     email                : deanna_bonds@adaptec.com
 
-    See README.dpti for history, notes, license info, and credits
+    See Documentation/scsi/dpti.txt for history, notes, license info
+    and credits
  ***************************************************************************/
 
 /***************************************************************************
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/gdth.c	Sun Nov 17 20:30:14 2002
@@ -3991,6 +3991,9 @@
             break;
         if (gdth_search_isa(isa_bios)) {        /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
+	    if(shp == NULL)
+		    continue;
+
             ha = HADATA(shp);
             if (!gdth_init_isa(isa_bios,ha)) {
                 scsi_unregister(shp);
@@ -4105,6 +4108,9 @@
             break;
         if (gdth_search_eisa(eisa_slot)) {      /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
+	    if(shp == NULL)
+		    continue;
+
             ha = HADATA(shp);
             if (!gdth_init_eisa(eisa_slot,ha)) {
                 scsi_unregister(shp);
@@ -4214,6 +4220,9 @@
             if (gdth_ctr_count >= MAXHA)
                 break;
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
+	    if(shp == NULL)
+		    continue;
+
             ha = HADATA(shp);
             if (!gdth_init_pci(&pcistr[ctr],ha)) {
                 scsi_unregister(shp);
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/hosts.c	Sun Nov 17 20:30:02 2002
@@ -34,6 +34,7 @@
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 
@@ -45,12 +46,101 @@
 #include "scsi.h"
 #include "hosts.h"
 
-static LIST_HEAD(scsi_host_hn_list);
 static LIST_HEAD(scsi_host_list);
 static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
 
 static int scsi_host_next_hn;		/* host_no for next new host */
 static int scsi_hosts_registered;	/* cnt of registered scsi hosts */
+static char *scsihosts;
+
+MODULE_PARM(scsihosts, "s");
+MODULE_PARM_DESC(scsihosts, "scsihosts=driver1,driver2,driver3");
+#ifndef MODULE
+int __init scsi_setup(char *str)
+{
+	scsihosts = str;
+	return 1;
+}
+
+__setup("scsihosts=", scsi_setup);
+#endif
+
+/**
+  * scsi_find_host_by_num - get a Scsi_Host by host no
+  *
+  * @host_no:	host number to locate
+  *
+  * Return value:
+  *	A pointer to located Scsi_Host or NULL.
+  **/
+static struct Scsi_Host *scsi_find_host_by_num(unsigned short host_no)
+{
+	struct Scsi_Host *shost, *shost_found = NULL;
+
+	spin_lock(&scsi_host_list_lock);
+	list_for_each_entry(shost, &scsi_host_list, sh_list) {
+		if (shost->host_no > host_no) {
+			/*
+			 * The list is sorted.
+			 */
+			break;
+		} else if (shost->host_no == host_no) {
+			shost_found = shost;
+			break;
+		}
+	}
+	spin_unlock(&scsi_host_list_lock);
+	return shost_found;
+}
+
+/**
+ * scsi_alloc_hostnum - choose new SCSI host number based on host name.
+ * @name:	String to store in name field
+ *
+ * Return value:
+ *	Pointer to a new Scsi_Host_Name
+ **/
+static int scsi_alloc_host_num(const char *name)
+{
+	int hostnum;
+	int namelen;
+	const char *start, *end;
+
+	if (name) {
+		hostnum = 0;
+		namelen = strlen(name);
+		start = scsihosts; 
+		while (1) {
+			int hostlen;
+
+			if (start && start[0] != '\0') {
+				end = strpbrk(start, ",:");
+				if (end) {
+					hostlen = (end - start);
+					end++;
+				} else
+					hostlen = strlen(start);
+				/*
+				 * Look for a match on the scsihosts list.
+				 */
+				if ((hostlen == namelen) && 
+				    (strncmp(name, start, hostlen) == 0) && 
+				    (!scsi_find_host_by_num(hostnum)))
+					return hostnum;
+				start = end;
+			} else  {
+				/*
+				 * Look for any unused numbers.
+				 */
+				if (!scsi_find_host_by_num(hostnum))
+					return hostnum;
+			}
+			hostnum++;
+		}
+	} else
+		return scsi_host_next_hn++;
+}
+
 
 /**
  * scsi_tp_for_each_host - call function for each scsi host off a template
@@ -131,12 +221,6 @@
 	struct scsi_cmnd *scmd;
 
 	/*
-	 * Current policy is all shosts go away on unregister.
-	 */
-	if (shost->hostt->module && GET_USE_COUNT(shost->hostt->module))
-		return 1;
-
-	/*
 	 * FIXME Do ref counting.  We force all of the devices offline to
 	 * help prevent race conditions where other hosts/processors could
 	 * try and get in and queue a command.
@@ -243,21 +327,11 @@
  **/
 void scsi_unregister(struct Scsi_Host *shost)
 {
-	struct list_head *lh;
-	Scsi_Host_Name *shost_name;
-
 	/* Remove shost from scsi_host_list */
 	spin_lock(&scsi_host_list_lock);
 	list_del(&shost->sh_list);
 	spin_unlock(&scsi_host_list_lock);
 
-	/* Unregister from scsi_host_hn_list */
-	list_for_each(lh, &scsi_host_hn_list) {
-		shost_name = list_entry(lh, Scsi_Host_Name, shn_list);
-		if (shost->host_no == shost_name->host_no)
-			shost_name->host_registered = 0;
-	}
-
 	/*
 	 * Next, kill the kernel error recovery thread for this host.
 	 */
@@ -273,54 +347,13 @@
 	shost->hostt->present--;
 
 	/* Cleanup proc and driverfs */
-#ifdef CONFIG_PROC_FS
 	scsi_proc_host_rm(shost);
-	if (!shost->hostt->present)
-		remove_proc_entry(shost->hostt->proc_name, proc_scsi);
-#endif
 	device_unregister(&shost->host_driverfs_dev);
 
 	kfree(shost);
 }
 
 /**
- * scsi_host_hn_add - allocate and add new Scsi_Host_Name
- * @name:	String to store in name field
- *
- * Return value:
- * 	Pointer to a new Scsi_Host_Name
- **/
-Scsi_Host_Name *scsi_host_hn_add(char *name)
-{
-	Scsi_Host_Name *shost_name;
-	int len;
-
-	len = strlen(name);
-	shost_name =  kmalloc(sizeof(*shost_name), GFP_KERNEL);
-	if (!shost_name) {
-		printk(KERN_ERR "%s: out of memory at line %d.\n",
-		       __FUNCTION__, __LINE__);
-		return NULL;
-	}
-	shost_name->name = kmalloc(len + 1, GFP_KERNEL);
-	if (!shost_name->name) {
-		kfree(shost_name);
-		printk(KERN_ERR "%s: out of memory at line %d.\n",
-		       __FUNCTION__, __LINE__);
-		return NULL;
-	}
-
-	if (len)
-		strncpy(shost_name->name, name, len);
-	shost_name->name[len] = 0;
-	shost_name->host_no = scsi_host_next_hn++;
-	shost_name->host_registered = 0;
-	list_add_tail(&shost_name->shn_list, &scsi_host_hn_list);
-
-	return shost_name;
-}
-
-/**
  * scsi_register - register a scsi host adapter instance.
  * @shost_tp:	pointer to scsi host template
  * @xtr_bytes:	extra bytes to allocate for driver
@@ -337,14 +370,19 @@
 struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
 {
 	struct Scsi_Host *shost, *shost_scr;
-	Scsi_Host_Name *shost_name = NULL;
-	Scsi_Host_Name *shn = NULL;
-	char *hname;
-	size_t hname_len;
 	struct list_head *lh;
 	int gfp_mask;
 	DECLARE_MUTEX_LOCKED(sem);
 
+        /* Check to see if this host has any error handling facilities */
+        if(shost_tp->eh_strategy_handler == NULL &&
+           shost_tp->eh_abort_handler == NULL &&
+           shost_tp->eh_device_reset_handler == NULL &&
+           shost_tp->eh_bus_reset_handler == NULL &&
+           shost_tp->eh_host_reset_handler == NULL) {
+		printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\nERROR: This is not a safe way to run your SCSI host\nERROR: The error handling must be added to this driver\n", shost_tp->proc_name);
+		dump_stack();
+        } 
 	gfp_mask = GFP_KERNEL;
 	if (shost_tp->unchecked_isa_dma && xtr_bytes)
 		gfp_mask |= __GFP_DMA;
@@ -357,33 +395,7 @@
 
 	memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes);
 
-	/*
-	 * Determine host number. Check reserved first before allocating
-	 * new one
-	 */
-	hname = (shost_tp->proc_name) ?  shost_tp->proc_name : "";
-	hname_len = strlen(hname);
-
-	if (hname_len)
-		list_for_each(lh, &scsi_host_hn_list) {
-			shn = list_entry(lh, Scsi_Host_Name, shn_list);
-			if (!(shn->host_registered) &&
-			    !strncmp(hname, shn->name, hname_len)) {
-				shost_name = shn;
-				break;
-			}
-		}
-
-	if (!shost_name) {
-		shost_name = scsi_host_hn_add(hname);
-		if (!shost_name) {
-			kfree(shost);
-			return NULL;
-		}
-	}
-
-	shost->host_no = shost_name->host_no;
-	shost_name->host_registered = 1;
+	shost->host_no = scsi_alloc_host_num(shost_tp->proc_name);
 	scsi_hosts_registered++;
 
 	spin_lock_init(&shost->default_lock);
@@ -449,12 +461,7 @@
 found:
 	spin_unlock(&scsi_host_list_lock);
 
-#ifdef CONFIG_PROC_FS
-	/* Add the new driver to /proc/scsi if not already there */
-	if (!shost_tp->proc_dir)
-		scsi_proc_host_mkdir(shost_tp);
 	scsi_proc_host_add(shost);
-#endif
 
 	strncpy(shost->host_driverfs_dev.name, shost_tp->proc_name,
 		DEVICE_NAME_SIZE-1);
@@ -499,8 +506,6 @@
 
 	cur_cnt = scsi_hosts_registered;
 
-	MOD_INC_USE_COUNT;
-
 	/*
 	 * The detect routine must carefully spinunlock/spinlock if it
 	 * enables interrupts, since all interrupt handlers do spinlock as
@@ -584,8 +589,6 @@
 		printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
 		       (scsi_hosts_registered == 1) ? "" : "s");
 
-	MOD_DEC_USE_COUNT;
-
 	unlock_kernel();
 	return 0;
 
@@ -632,22 +635,8 @@
  **/
 struct Scsi_Host *scsi_host_hn_get(unsigned short host_no)
 {
-	struct list_head *lh;
-	struct Scsi_Host *shost;
-
-	spin_lock(&scsi_host_list_lock);
-	list_for_each(lh, &scsi_host_list) {
-		shost = list_entry(lh, struct Scsi_Host, sh_list);
-		if (shost->host_no == host_no) {
-			/* XXX Inc ref count */
-			goto done;
-		}
-	}
-
-	shost = (struct Scsi_Host *)NULL;
-done:
-	spin_unlock(&scsi_host_list_lock);
-	return shost;
+	/* XXX Inc ref count */
+	return scsi_find_host_by_num(host_no);
 }
 
 /**
@@ -664,38 +653,19 @@
 }
 
 /**
- * scsi_host_hn_init - init scsi host number list from string
- * @shost_hn:	string of scsi host driver names.
- **/
-void __init scsi_host_hn_init(char *shost_hn)
-{
-	char *temp = shost_hn;
-
-	while (temp) {
-		while (*temp && (*temp != ':') && (*temp != ','))
-			temp++;
-		if (!*temp)
-			temp = NULL;
-		else
-			*temp++ = 0;
-		(void)scsi_host_hn_add(shost_hn);
-		shost_hn = temp;
-	}
-}
-
-/**
- * scsi_host_no_release - free all entries in scsi host number list
+ * scsi_host_init - set up the scsi host number list based on any entries
+ * scsihosts.
  **/
-void __exit scsi_host_hn_release()
+void __init scsi_host_init(void)
 {
-	struct list_head *lh, *next;
-	Scsi_Host_Name *shn;
+	char *shost_hn;
 
-	list_for_each_safe(lh, next, &scsi_host_hn_list) {
-		shn = list_entry(lh, Scsi_Host_Name, shn_list);
-		if (shn->name)
-			kfree(shn->name);
-		kfree(shn);
+	shost_hn = scsihosts;
+	while (shost_hn) {
+		scsi_host_next_hn++;
+		shost_hn = strpbrk(shost_hn, ":,");
+		if (shost_hn)
+			shost_hn++;
 	}
 }
 
diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
--- a/drivers/scsi/hosts.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/hosts.h	Sun Nov 17 20:30:12 2002
@@ -53,8 +53,6 @@
  * type of host adapter that is supported on the system.
  */
 
-typedef struct scsi_disk Disk;
-
 typedef struct	SHT
 {
     /* Used with loadable modules so that we know when it is safe to unload */
@@ -511,17 +509,6 @@
 	unsigned short host_registered;
 } Scsi_Host_Name;
 	
-extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
-extern void scsi_proc_host_add(struct Scsi_Host *);
-extern void scsi_proc_host_rm(struct Scsi_Host *);
-
-/*
- *  scsi_init initializes the scsi hosts.
- */
-
-extern int next_scsi_host;
-
-unsigned int scsi_init(void);
 extern void scsi_register_blocked_host(struct Scsi_Host *);
 extern void scsi_deregister_blocked_host(struct Scsi_Host *);
 
@@ -543,18 +530,13 @@
  */
 extern void scan_scsis(struct Scsi_Host *, uint, uint, uint, uint);
 
-extern void scsi_mark_host_reset(struct Scsi_Host *);
-
-#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-
 struct Scsi_Device_Template
 {
-    struct Scsi_Device_Template * next;
+    struct list_head list;
     const char * name;
     const char * tag;
     struct module * module;	  /* Used for loadable modules */
     unsigned char scsi_type;
-    int (*detect)(Scsi_Device *); /* Returns 1 if we can attach this device */
     int (*attach)(Scsi_Device *); /* Attach devices to arrays */
     void (*detach)(Scsi_Device *);
     int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
@@ -592,8 +574,7 @@
 extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *);
 extern struct Scsi_Host *scsi_host_hn_get(unsigned short);
 extern void scsi_host_put(struct Scsi_Host *);
-extern void scsi_host_hn_init(char *);
-extern void scsi_host_hn_release(void);
+extern void scsi_host_init(void);
 
 /*
  * host_busy inc/dec/test functions
diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
--- a/drivers/scsi/ibmmca.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/scsi/ibmmca.c	Sun Nov 17 20:30:03 2002
@@ -4,8 +4,9 @@
  Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
  General Public License. Written by Martin Kolinek, December 1995.
  Further development by: Chris Beauregard, Klaus Kudielka, Michael Lang
- See the file README.ibmmca for a detailed description of this driver,
- the commandline arguments and the history of its development.
+ See the file Documentation/scsi/ibmmca.txt for a detailed description
+ of this driver, the commandline arguments and the history of its
+ development.
  See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest
  updates, info and ADF-files for adapters supported by this driver.
 
diff -Nru a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h
--- a/drivers/scsi/ibmmca.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/ibmmca.h	Sun Nov 17 20:30:14 2002
@@ -1,6 +1,7 @@
-/* 
+/*
  * Low Level Driver for the IBM Microchannel SCSI Subsystem
- * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver
+ * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the
+ * IBM MCA SCSI-driver.
  * For use under the GNU General Public License within the Linux-kernel project.
  * This include file works only correctly with kernel 2.4.0 or higher!!! */
 
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/megaraid.c	Sun Nov 17 20:30:02 2002
@@ -494,6 +494,7 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
+#include <linux/string.h>
 #include <asm/pgtable.h>
 
 #include <linux/sched.h>
@@ -760,9 +761,8 @@
 /* For controller re-ordering */ 
 
 static struct file_operations megadev_fops = {
-	ioctl:megadev_ioctl_entry,
-	open:megadev_open,
-	release:megadev_close,
+	.owner			= THIS_MODULE,
+	.ioctl			= megadev_ioctl_entry,
 };
 
 /*
@@ -4333,15 +4333,6 @@
 	}
 }
 
-/*
- * Routines for the character/ioctl interface to the driver
- */
-static int megadev_open (struct inode *inode, struct file *filep)
-{
-	MOD_INC_USE_COUNT;
-	return 0;		/* success */
-}
-
 static int megadev_ioctl_entry (struct inode *inode, struct file *filep,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -4851,16 +4842,6 @@
 
 	return scb;
 }
-
-static int
-megadev_close (struct inode *inode, struct file *filep)
-{
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
-	return 0;
-}
-
 
 static int
 mega_support_ext_cdb(mega_host_config *this_hba)
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/ncr53c8xx.c	Sun Nov 17 20:30:12 2002
@@ -1621,7 +1621,7 @@
 	**	Possible data corruption during Memory Write and Invalidate.
 	**	This work-around resets the addressing logic prior to the 
 	**	start of the first MOVE of a DATA IN phase.
-	**	(See README.ncr53c8xx for more information)
+	**	(See Documentation/scsi/ncr53c8xx.txt for more information)
 	*/
 	SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
 		20,
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/osst.c	Sun Nov 17 20:30:14 2002
@@ -1,6 +1,6 @@
 /*
   SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
-  file README.st for more information.
+  file Documentation/scsi/st.txt for more information.
 
   History:
 
@@ -153,20 +153,18 @@
 
 static int osst_init(void);
 static int osst_attach(Scsi_Device *);
-static int osst_detect(Scsi_Device *);
 static void osst_detach(Scsi_Device *);
 
-static int osst_dev_noticed;
 static int osst_nr_dev;
 static int osst_dev_max;
 
 struct Scsi_Device_Template osst_template =
 {
        module:		THIS_MODULE,
+       list:		LIST_HEAD_INIT(osst_template.list),
        name:		"OnStream tape",
        tag:		"osst",
        scsi_type:	TYPE_TAPE,
-       detect:		osst_detect,
        attach:		osst_attach,
        detach:		osst_detach
 };
@@ -4174,15 +4172,13 @@
 #endif
 		return (-EBUSY);
 	}
+	
+	if (!try_module_get(STp->device->host->hostt->module))
+		return (-ENXIO);
+	STp->device->access_count++;
 	STp->in_use       = 1;
 	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);
-	if (osst_template.module)
-		 __MOD_INC_USE_COUNT(osst_template.module);
-	STp->device->access_count++;
-
 	if (mode != STp->current_mode) {
 #if DEBUG
 		if (debugging)
@@ -4521,10 +4517,7 @@
 	STp->header_ok = 0;
 	STp->device->access_count--;
 
-	if (STp->device->host->hostt->module)
-	    __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
-	if (osst_template.module)
-	    __MOD_DEC_USE_COUNT(osst_template.module);
+	module_put(STp->device->host->hostt->module);
 
 	return retval;
 }
@@ -4652,10 +4645,7 @@
 	STp->in_use = 0;
 	STp->device->access_count--;
 
-	if (STp->device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
-	if(osst_template.module)
-		__MOD_DEC_USE_COUNT(osst_template.module);
+	module_put(STp->device->host->hostt->module);
 
 	return result;
 }
@@ -5486,7 +5476,7 @@
 			   0, 0, &osst_fops, NULL);
 # endif
 	}
-	devfs_register_tape (tpnt->de_r[0]);
+	disk->number = devfs_register_tape(SDp->de);
 #endif
 
 	tpnt->device = SDp;
@@ -5564,15 +5554,6 @@
 	return 0;
 };
 
-static int osst_detect(Scsi_Device * SDp)
-{
-	if (SDp->type != TYPE_TAPE) return 0;
-	if ( ! osst_supports(SDp) ) return 0;
-	
-	osst_dev_noticed++;
-	return 1;
-}
-
 static int osst_registered = 0;
 
 /* Driver initialization (not __initfunc because may be called later) */
@@ -5580,9 +5561,6 @@
 {
 	int i;
 
-	if (osst_dev_noticed == 0)
-		return 0;
-
 	if (!osst_registered) {
 		if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
 			printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
@@ -5647,13 +5625,13 @@
 			devfs_unregister (tpnt->de_n[mode]);
 			tpnt->de_n[mode] = NULL;
 		}
+		devfs_unregister_tape(tpnt->disk->number);
 #endif
 		put_disk(tpnt->disk);
 		kfree(tpnt);
 		os_scsi_tapes[i] = NULL;
 		scsi_slave_detach(SDp);
 		osst_nr_dev--;
-		osst_dev_noticed--;
 		return;
 	}
   }
diff -Nru a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
--- a/drivers/scsi/pcmcia/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/pcmcia/Kconfig	Sun Nov 17 20:30:14 2002
@@ -46,7 +46,7 @@
 	help
 	  If you intend to attach this type of PCMCIA SCSI host adapter to
 	  your computer, say Y here and read
-	  <file:Documentation/README.nsp_cs.eng>.
+	  <file:Documentation/scsi/NinjaSCSI.txt>.
 
 	  This driver is also available as a module called nsp_cs.o ( =
 	  code which can be inserted in and removed from the running kernel
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/pcmcia/nsp_cs.c	Sun Nov 17 20:30:15 2002
@@ -1224,6 +1224,9 @@
 
 	request_region(data->BaseAddress, data->NumAddress, "nsp_cs");
 	host		  = scsi_register(sht, 0);
+	if(host == NULL)
+		return 0;
+
 	host->unique_id	  = data->BaseAddress;
 	host->io_port	  = data->BaseAddress;
 	host->n_io_port	  = data->NumAddress;
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/scsi/qla1280.c	Sun Nov 17 20:30:16 2002
@@ -246,10 +246,10 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
@@ -955,8 +955,8 @@
 		qla1280_setup(options, NULL);
 
 	printk(KERN_WARNING
-	       "qla1280: Please read the file /usr/src/linux/drivers"
-	       "/scsi/README.qla1280\n"
+	       "qla1280: Please read the file /usr/src/linux/Documentation"
+	       "/scsi/qla1280.txt\n"
 	       "qla1280: to see the proper way to specify options to the qla1280 "
 	       "module\n"
 	       "qla1280: Specifically, don't use any commas when passing "
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/scsi.c	Sun Nov 17 20:30:14 2002
@@ -74,13 +74,6 @@
 #include <linux/kmod.h>
 #endif
 
-struct proc_dir_entry *proc_scsi;
-
-#ifdef CONFIG_PROC_FS
-static int scsi_proc_info(char *buffer, char **start, off_t offset, int length);
-static void scsi_dump_status(int level);
-#endif
-
 #define SG_MEMPOOL_NR		5
 #define SG_MEMPOOL_SIZE		32
 
@@ -135,7 +128,7 @@
 /*
  * List of all highlevel drivers.
  */
-static struct Scsi_Device_Template *scsi_devicelist;
+LIST_HEAD(scsi_devicelist);
 static DECLARE_RWSEM(scsi_devicelist_mutex);
 
 /*
@@ -163,6 +156,10 @@
 };
 
 static char * scsi_null_device_strs = "nullnullnullnull";
+static const char * const spaces = "                "; /* 16 of them */
+
+static unsigned scsi_default_dev_flags;
+LIST_HEAD(scsi_dev_info_list);
 
 /* 
  * Function prototypes.
@@ -171,11 +168,6 @@
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
 
 /*
- * Private interface into the new error handling code.
- */
-extern int scsi_new_reset(Scsi_Cmnd *SCpnt, unsigned int flag);
-
-/*
  * Function:    scsi_initialize_queue()
  *
  * Purpose:     Selects queue handler function for a device.
@@ -226,6 +218,8 @@
 
 	if (!SHpnt->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+
+        blk_queue_prep_rq(q, scsi_prep_fn);
 }
 
 #ifdef MODULE
@@ -1668,305 +1662,239 @@
 	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
-#ifdef CONFIG_PROC_FS
-static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
+/*
+ * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into
+ * devinfo vendor and model strings.
+ */
+static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length,
+				char *from, int compatible)
 {
-	Scsi_Device *scd;
-	struct Scsi_Host *HBA_ptr;
-	int size, len = 0;
-	off_t begin = 0;
-	off_t pos = 0;
+	size_t from_length;
 
-	/*
-	 * First, see if there are any attached devices or not.
-	 */
-	for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
-	     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
-		if (HBA_ptr->host_queue != NULL) {
-			break;
-		}
-	}
-	size = sprintf(buffer + len, "Attached devices: %s\n", (HBA_ptr) ? "" : "none");
-	len += size;
-	pos = begin + len;
-	for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
-	     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
-#if 0
-		size += sprintf(buffer + len, "scsi%2d: %s\n", (int) HBA_ptr->host_no,
-				HBA_ptr->hostt->procname);
-		len += size;
-		pos = begin + len;
-#endif
-		for (scd = HBA_ptr->host_queue; scd; scd = scd->next) {
-			proc_print_scsidevice(scd, buffer, &size, len);
-			len += size;
-			pos = begin + len;
-
-			if (pos < offset) {
-				len = 0;
-				begin = pos;
-			}
-			if (pos > offset + length)
-				goto stop_output;
+	from_length = strlen(from);
+	strncpy(to, from, min(to_length, from_length));
+	if (from_length < to_length) {
+		if (compatible) {
+			/*
+			 * NUL terminate the string if it is short.
+			 */
+			to[from_length] = '\0';
+		} else {
+			/* 
+			 * space pad the string if it is short. 
+			 */
+			strncpy(&to[from_length], spaces,
+				to_length - from_length);
 		}
 	}
+	if (from_length > to_length)
+		 printk(KERN_WARNING "%s: %s string '%s' is too long\n",
+			__FUNCTION__, name, from);
+}
 
-stop_output:
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);	/* Start slop */
-	if (len > length)
-		len = length;	/* Ending slop */
-	return (len);
-}
-
-static int proc_scsi_gen_write(struct file * file, const char * buf,
-                              unsigned long length, void *data)
-{
-	Scsi_Device *scd;
-	struct Scsi_Host *HBA_ptr;
-	char *p;
-	int host, channel, id, lun;
-	char * buffer;
-	int err;
-
-	if (!buf || length>PAGE_SIZE)
-		return -EINVAL;
-
-	if (!(buffer = (char *) __get_free_page(GFP_KERNEL)))
+/**
+ * scsi_dev_info_list_add: add one dev_info list entry.
+ * @vendor:	vendor string
+ * @model:	model (product) string
+ * @strflags:	integer string
+ * @flag:	if strflags NULL, use this flag value
+ *
+ * Description:
+ * 	Create and add one dev_info entry for @vendor, @model, @strflags or
+ * 	@flag. If @compatible, add to the tail of the list, do not space
+ * 	pad, and set devinfo->compatible. The scsi_static_device_list entries
+ * 	are added with @compatible 1 and @clfags NULL.
+ *
+ * Returns: 0 OK, -error on failure.
+ **/
+static int scsi_dev_info_list_add(int compatible, char *vendor, char *model,
+			    char *strflags, int flags)
+{
+	struct scsi_dev_info_list *devinfo;
+
+	devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL);
+	if (!devinfo) {
+		printk(KERN_ERR "%s: no memory\n", __FUNCTION__);
 		return -ENOMEM;
-	if(copy_from_user(buffer, buf, length))
-	{
-		err =-EFAULT;
-		goto out;
 	}
 
-	err = -EINVAL;
+	scsi_strcpy_devinfo("vendor", devinfo->vendor, sizeof(devinfo->vendor),
+			    vendor, compatible);
+	scsi_strcpy_devinfo("model", devinfo->model, sizeof(devinfo->model),
+			    model, compatible);
 
-	if (length < PAGE_SIZE)
-		buffer[length] = '\0';
-	else if (buffer[PAGE_SIZE-1])
-		goto out;
+	if (strflags)
+		devinfo->flags = simple_strtoul(strflags, NULL, 0);
+	else
+		devinfo->flags = flags;
 
-	if (length < 11 || strncmp("scsi", buffer, 4))
-		goto out;
+	devinfo->compatible = compatible;
 
-	/*
-	 * Usage: echo "scsi dump #N" > /proc/scsi/scsi
-	 * to dump status of all scsi commands.  The number is used to specify the level
-	 * of detail in the dump.
-	 */
-	if (!strncmp("dump", buffer + 5, 4)) {
-		unsigned int level;
+	if (compatible)
+		list_add_tail(&devinfo->dev_info_list, &scsi_dev_info_list);
+	else
+		list_add(&devinfo->dev_info_list, &scsi_dev_info_list);
 
-		p = buffer + 10;
+	return 0;
+}
 
-		if (*p == '\0')
-			goto out;
+/**
+ * scsi_dev_info_list_add_str: parse dev_list and add to the
+ * scsi_dev_info_list.
+ * @dev_list:	string of device flags to add
+ *
+ * Description:
+ * 	Parse dev_list, and add entries to the scsi_dev_info_list.
+ * 	dev_list is of the form "vendor:product:flag,vendor:product:flag".
+ * 	dev_list is modified via strsep. Can be called for command line
+ * 	addition, for proc or mabye a sysfs interface.
+ *
+ * Returns: 0 if OK, -error on failure.
+ **/
+int scsi_dev_info_list_add_str (char *dev_list)
+{
+	char *vendor, *model, *strflags, *next;
+	char *next_check;
+	int res = 0;
 
-		level = simple_strtoul(p, NULL, 0);
-		scsi_dump_status(level);
+	next = dev_list;
+	if (next && next[0] == '"') {
+		/*
+		 * Ignore both the leading and trailing quote.
+		 */
+		next++;
+		next_check = ",\"";
+	} else {
+		next_check = ",";
 	}
+
 	/*
-	 * Usage: echo "scsi log token #N" > /proc/scsi/scsi
-	 * where token is one of [error,scan,mlqueue,mlcomplete,llqueue,
-	 * llcomplete,hlqueue,hlcomplete]
+	 * For the leading and trailing '"' case, the for loop comes
+	 * through the last time with vendor[0] == '\0'.
 	 */
-#ifdef CONFIG_SCSI_LOGGING		/* { */
-
-	if (!strncmp("log", buffer + 5, 3)) {
-		char *token;
-		unsigned int level;
-
-		p = buffer + 9;
-		token = p;
-		while (*p != ' ' && *p != '\t' && *p != '\0') {
-			p++;
-		}
-
-		if (*p == '\0') {
-			if (strncmp(token, "all", 3) == 0) {
-				/*
-				 * Turn on absolutely everything.
-				 */
-				scsi_logging_level = ~0;
-			} else if (strncmp(token, "none", 4) == 0) {
-				/*
-				 * Turn off absolutely everything.
-				 */
-				scsi_logging_level = 0;
-			} else {
-				goto out;
-			}
-		} else {
-			*p++ = '\0';
-
-			level = simple_strtoul(p, NULL, 0);
-
-			/*
-			 * Now figure out what to do with it.
-			 */
-			if (strcmp(token, "error") == 0) {
-				SCSI_SET_ERROR_RECOVERY_LOGGING(level);
-			} else if (strcmp(token, "timeout") == 0) {
-				SCSI_SET_TIMEOUT_LOGGING(level);
-			} else if (strcmp(token, "scan") == 0) {
-				SCSI_SET_SCAN_BUS_LOGGING(level);
-			} else if (strcmp(token, "mlqueue") == 0) {
-				SCSI_SET_MLQUEUE_LOGGING(level);
-			} else if (strcmp(token, "mlcomplete") == 0) {
-				SCSI_SET_MLCOMPLETE_LOGGING(level);
-			} else if (strcmp(token, "llqueue") == 0) {
-				SCSI_SET_LLQUEUE_LOGGING(level);
-			} else if (strcmp(token, "llcomplete") == 0) {
-				SCSI_SET_LLCOMPLETE_LOGGING(level);
-			} else if (strcmp(token, "hlqueue") == 0) {
-				SCSI_SET_HLQUEUE_LOGGING(level);
-			} else if (strcmp(token, "hlcomplete") == 0) {
-				SCSI_SET_HLCOMPLETE_LOGGING(level);
-			} else if (strcmp(token, "ioctl") == 0) {
-				SCSI_SET_IOCTL_LOGGING(level);
-			} else {
-				goto out;
-			}
-		}
-
-		printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level);
+	for (vendor = strsep(&next, ":"); vendor && (vendor[0] != '\0')
+	     && (res == 0); vendor = strsep(&next, ":")) {
+		strflags = NULL;
+		model = strsep(&next, ":");
+		if (model)
+			strflags = strsep(&next, next_check);
+		if (!model || !strflags) {
+			printk(KERN_ERR "%s: bad dev info string '%s' '%s'"
+			       " '%s'\n", __FUNCTION__, vendor, model,
+			       strflags);
+			res = -EINVAL;
+		} else
+			res = scsi_dev_info_list_add(0 /* compatible */, vendor,
+						     model, strflags, 0);
 	}
-#endif	/* CONFIG_SCSI_LOGGING */ /* } */
+	return res;
+}
 
-	/*
-	 * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
-	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
-	 * Consider this feature BETA.
-	 *     CAUTION: This is not for hotplugging your peripherals. As
-	 *     SCSI was not designed for this you could damage your
-	 *     hardware !
-	 * However perhaps it is legal to switch on an
-	 * already connected device. It is perhaps not
-	 * guaranteed this device doesn't corrupt an ongoing data transfer.
-	 */
-	if (!strncmp("add-single-device", buffer + 5, 17)) {
-		p = buffer + 23;
-
-		host = simple_strtoul(p, &p, 0);
-		channel = simple_strtoul(p + 1, &p, 0);
-		id = simple_strtoul(p + 1, &p, 0);
-		lun = simple_strtoul(p + 1, &p, 0);
-
-		printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
-		       id, lun);
-
-		for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
-		     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
-			if (HBA_ptr->host_no == host) {
-				break;
-			}
-		}
-		err = -ENXIO;
-		if (!HBA_ptr)
-			goto out;
-
-		for (scd = HBA_ptr->host_queue; scd; scd = scd->next) {
-			if ((scd->channel == channel
-			     && scd->id == id
-			     && scd->lun == lun)) {
-				break;
-			}
-		}
+/**
+ * scsi_dev_list_init: set up the dynamic device list.
+ * @dev_list:	string of device flags to add
+ *
+ * Description:
+ * 	Add command line @dev_list entries, then add
+ * 	scsi_static_device_list entries to the scsi device info list.
+ **/
+static void scsi_dev_info_list_init (char *dev_list)
+{
+	int i;
 
-		err = -ENOSYS;
-		if (scd)
-			goto out;	/* We do not yet support unplugging */
+	if (scsi_dev_info_list_add_str(dev_list) == -ENOMEM)
+		return;
+	for (i = 0; scsi_static_device_list[i].vendor != NULL; i++)
+		if (scsi_dev_info_list_add(1 /* compatibile */,
+			   scsi_static_device_list[i].vendor,
+			   scsi_static_device_list[i].model,
+			   NULL,
+			   scsi_static_device_list[i].flags) == -ENOMEM)
+			return;
+}
 
-		scan_scsis(HBA_ptr, 1, channel, id, lun);
-		err = length;
-		goto out;
+/**
+ * scsi_dev_info_list_delete: called from scsi.c:exit_scsi to remove
+ * 	the scsi_dev_info_list.
+ **/
+static void scsi_dev_info_list_delete (void)
+{
+	struct list_head *lh, *lh_next;
+	struct scsi_dev_info_list *devinfo;
+
+	list_for_each_safe(lh, lh_next, &scsi_dev_info_list) {
+		devinfo = list_entry(lh, struct scsi_dev_info_list,
+				     dev_info_list);
+		kfree(devinfo);
 	}
-	/*
-	 * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
-	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
-	 *
-	 * Consider this feature pre-BETA.
-	 *
-	 *     CAUTION: This is not for hotplugging your peripherals. As
-	 *     SCSI was not designed for this you could damage your
-	 *     hardware and thoroughly confuse the SCSI subsystem.
-	 *
-	 */
-	else if (!strncmp("remove-single-device", buffer + 5, 20)) {
-		p = buffer + 26;
-
-		host = simple_strtoul(p, &p, 0);
-		channel = simple_strtoul(p + 1, &p, 0);
-		id = simple_strtoul(p + 1, &p, 0);
-		lun = simple_strtoul(p + 1, &p, 0);
+}
 
+/**
+ * get_device_flags - get device specific flags from the dynamic device
+ * list. Called during scan time.
+ * @vendor:	vendor name
+ * @model:	model name
+ *
+ * Description:
+ *     Search the scsi_dev_info_list for an entry matching @vendor and
+ *     @model, if found, return the matching flags value, else return
+ *     scsi_default_dev_flags.
+ **/
+int scsi_get_device_flags(unsigned char *vendor, unsigned char *model)
+{
+	struct scsi_dev_info_list *devinfo;
 
-		for (HBA_ptr = scsi_host_get_next(NULL); HBA_ptr;
-		     HBA_ptr = scsi_host_get_next(HBA_ptr)) {
-			if (HBA_ptr->host_no == host) {
-				break;
-			}
-		}
-		err = -ENODEV;
-		if (!HBA_ptr)
-			goto out;
-
-		for (scd = HBA_ptr->host_queue; scd; scd = scd->next) {
-			if ((scd->channel == channel
-			     && scd->id == id
-			     && scd->lun == lun)) {
-				break;
+	list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) {
+		if (devinfo->compatible) {
+			/*
+			 * Behave like the older version of get_device_flags.
+			 */
+			size_t max;
+			/*
+			 * XXX why skip leading spaces? If an odd INQUIRY
+			 * value, that should have been part of the
+			 * scsi_static_device_list[] entry, such as "  FOO"
+			 * rather than "FOO". Since this code is already
+			 * here, and we don't know what device it is
+			 * trying to work with, leave it as-is.
+			 */
+			max = 8;	/* max length of vendor */
+			while ((max > 0) && *vendor == ' ') {
+				max--;
+				vendor++;
 			}
-		}
-
-		if (scd == NULL)
-			goto out;	/* there is no such device attached */
-
-		err = -EBUSY;
-		if (scd->access_count)
-			goto out;
-
-		scsi_detach_device(scd);
-
-		if (scd->attached == 0) {
-			devfs_unregister (scd->de);
-
-			/* Now we can remove the device structure */
-			if (scd->next != NULL)
-				scd->next->prev = scd->prev;
-
-			if (scd->prev != NULL)
-				scd->prev->next = scd->next;
-
-			if (HBA_ptr->host_queue == scd) {
-				HBA_ptr->host_queue = scd->next;
+			/*
+			 * XXX removing the following strlen() would be
+			 * good, using it means that for a an entry not in
+			 * the list, we scan every byte of every vendor
+			 * listed in scsi_static_device_list[], and never match
+			 * a single one (and still have to compare at
+			 * least the first byte of each vendor).
+			 */
+			if (memcmp(devinfo->vendor, vendor,
+				    min(max, strlen(devinfo->vendor))))
+				continue;
+			/*
+			 * Skip spaces again.
+			 */
+			max = 16;	/* max length of model */
+			while ((max > 0) && *model == ' ') {
+				max--;
+				model++;
 			}
-			blk_cleanup_queue(&scd->request_queue);
-			if (scd->inquiry)
-				kfree(scd->inquiry);
-			kfree((char *) scd);
+			if (memcmp(devinfo->model, model,
+				   min(max, strlen(devinfo->model))))
+				continue;
+			return devinfo->flags;
 		} else {
-			goto out;
+			if (!memcmp(devinfo->vendor, vendor,
+				     sizeof(devinfo->vendor)) &&
+			     !memcmp(devinfo->model, model,
+				      sizeof(devinfo->model)))
+				return devinfo->flags;
 		}
-		err = 0;
 	}
-out:
-	
-	free_page((unsigned long) buffer);
-	return err;
-}
-#endif
-
-void scsi_detect_device(struct scsi_device *sdev)
-{
-	struct Scsi_Device_Template *sdt;
-
-	down_read(&scsi_devicelist_mutex);
-	for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
-		if (sdt->detect)
-			(*sdt->detect)(sdev);
-	up_read(&scsi_devicelist_mutex);
+	return scsi_default_dev_flags;
 }
 
 int scsi_attach_device(struct scsi_device *sdev)
@@ -1974,22 +1902,22 @@
 	struct Scsi_Device_Template *sdt;
 
 	down_read(&scsi_devicelist_mutex);
-	for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
-		if (sdt->attach)
+	list_for_each_entry(sdt, &scsi_devicelist, list)
+		if (sdt->attach) {
 			/*
 			 * XXX check result when the upper level attach
 			 * return values are fixed, and on failure goto
 			 * fail.
 			 */
-			(*sdt->attach) (sdev);
+			if(try_module_get(sdt->module)) {
+				(*sdt->attach)(sdev);
+				module_put(sdt->module);
+			} else {
+				printk(KERN_WARNING "SCSI module %s not ready, skipping attach.\n", sdt->name);
+			}
+		}
 	up_read(&scsi_devicelist_mutex);
 	return 0;
-
-fail:
-	printk(KERN_ERR "%s: Allocation failure during SCSI scanning, "
-			"some SCSI devices might not be configured\n",
-			__FUNCTION__);
-	return -ENOMEM;
 }
 
 void scsi_detach_device(struct scsi_device *sdev)
@@ -1997,9 +1925,15 @@
 	struct Scsi_Device_Template *sdt;
 
 	down_read(&scsi_devicelist_mutex);
-	for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
-		if (sdt->detach)
-			(*sdt->detach)(sdev);
+	list_for_each_entry(sdt, &scsi_devicelist, list)
+		if (sdt->detach) {
+			if(try_module_get(sdt->module)) {
+				(*sdt->detach)(sdev);
+				module_put(sdt->module);
+			} else {
+				printk(KERN_WARNING "SCSI module %s not ready, skipping detach.\n", sdt->name);
+			}
+		}
 	up_read(&scsi_devicelist_mutex);
 }
 
@@ -2064,24 +1998,34 @@
 /*
  * This entry point should be called by a loadable module if it is trying
  * add a high level scsi driver to the system.
+ *
+ * This entry point is called from the upper level module's module_init()
+ * routine.  That implies that when this function is called, the
+ * scsi_mod module is locked down because of upper module layering and
+ * that the high level driver module is locked down by being in it's
+ * init routine.  So, the *only* thing we have to do to protect adds 
+ * we perform in this function is to make sure that all call's
+ * to the high level driver's attach() and detach() call in points, other
+ * than via scsi_register_device and scsi_unregister_device which are in
+ * the module_init and module_exit code respectively and therefore already
+ * locked down by the kernel module loader, are wrapped by try_module_get()
+ * and module_put() to avoid races on device adds and removes.
  */
 int scsi_register_device(struct Scsi_Device_Template *tpnt)
 {
 	Scsi_Device *SDpnt;
 	struct Scsi_Host *shpnt;
-	int out_of_space = 0;
 
 #ifdef CONFIG_KMOD
 	if (scsi_host_get_next(NULL) == NULL)
 		request_module("scsi_hostadapter");
 #endif
 
-	if (tpnt->next)
+	if (!list_empty(&tpnt->list))
 		return 1;
 
 	down_write(&scsi_devicelist_mutex);
-	tpnt->next = scsi_devicelist;
-	scsi_devicelist = tpnt;
+	list_add_tail(&tpnt->list, &scsi_devicelist);
 	up_write(&scsi_devicelist_mutex);
 
 	tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
@@ -2089,22 +2033,6 @@
 
 	driver_register(&tpnt->scsi_driverfs_driver);
 
-	/*
-	 * First scan the devices that we know about, and see if we notice them.
-	 */
-
-	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) {
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			if (tpnt->detect)
-				(*tpnt->detect) (SDpnt);
-		}
-	}
-
-	/*
-	 * Now actually connect the devices to the new driver.
-	 */
 	for (shpnt = scsi_host_get_next(NULL); shpnt;
 	     shpnt = scsi_host_get_next(shpnt)) {
 		for (SDpnt = shpnt->host_queue; SDpnt;
@@ -2120,13 +2048,6 @@
 		}
 	}
 
-	MOD_INC_USE_COUNT;
-
-	if (out_of_space) {
-		scsi_unregister_device(tpnt);	/* easiest way to clean up?? */
-		return 1;
-	}
-
 	return 0;
 }
 
@@ -2134,16 +2055,7 @@
 {
 	Scsi_Device *SDpnt;
 	struct Scsi_Host *shpnt;
-	struct Scsi_Device_Template *spnt;
-	struct Scsi_Device_Template *prev_spnt;
 	
-	lock_kernel();
-	/*
-	 * If we are busy, this is not going to fly.
-	 */
-	if (GET_USE_COUNT(tpnt->module) != 0)
-		goto error_out;
-
 	driver_unregister(&tpnt->scsi_driverfs_driver);
 
 	/*
@@ -2162,126 +2074,54 @@
 	 * Extract the template from the linked list.
 	 */
 	down_write(&scsi_devicelist_mutex);
-	spnt = scsi_devicelist;
-	prev_spnt = NULL;
-	while (spnt != tpnt) {
-		prev_spnt = spnt;
-		spnt = spnt->next;
-	}
-	if (prev_spnt == NULL)
-		scsi_devicelist = tpnt->next;
-	else
-		prev_spnt->next = spnt->next;
+	list_del(&tpnt->list);
 	up_write(&scsi_devicelist_mutex);
 
-	MOD_DEC_USE_COUNT;
-	unlock_kernel();
 	/*
 	 * Final cleanup for the driver is done in the driver sources in the
 	 * cleanup function.
 	 */
 	return 0;
-error_out:
-	unlock_kernel();
-	return -1;
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * Function:    scsi_dump_status
- *
- * Purpose:     Brain dump of scsi system, used for problem solving.
- *
- * Arguments:   level - used to indicate level of detail.
- *
- * Notes:       The level isn't used at all yet, but we need to find some way
- *              of sensibly logging varying degrees of information.  A quick one-line
- *              display of each command, plus the status would be most useful.
- *
- *              This does depend upon CONFIG_SCSI_LOGGING - I do want some way of turning
- *              it all off if the user wants a lean and mean kernel.  It would probably
- *              also be useful to allow the user to specify one single host to be dumped.
- *              A second argument to the function would be useful for that purpose.
- *
- *              FIXME - some formatting of the output into tables would be very handy.
- */
-static void scsi_dump_status(int level)
-{
-#ifdef CONFIG_SCSI_LOGGING		/* { */
-	int i;
-	struct Scsi_Host *shpnt;
-	Scsi_Cmnd *SCpnt;
-	Scsi_Device *SDpnt;
-	printk(KERN_INFO "Dump of scsi host parameters:\n");
-	i = 0;
-	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) {
-		printk(KERN_INFO " %d %d %d : %d %d\n",
-		       shpnt->host_failed,
-		       shpnt->host_busy,
-		       atomic_read(&shpnt->host_active),
-		       shpnt->host_blocked,
-		       shpnt->host_self_blocked);
-	}
-
-	printk(KERN_INFO "\n\n");
-	printk(KERN_INFO "Dump of scsi command parameters:\n");
-	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) {
-		printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result\n");
-		for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
-			for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-				/*  (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x      */
-				printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
-				       i++,
-
-				       SCpnt->host->host_no,
-				       SCpnt->channel,
-                                       SCpnt->target,
-                                       SCpnt->lun,
-
-                                       SCpnt->request->rq_disk ?
-                                       SCpnt->request->rq_disk->disk_name : "?",
-                                       (unsigned long long)SCpnt->request->sector,
-				       SCpnt->request->nr_sectors,
-				       (long)SCpnt->request->current_nr_sectors,
-				       SCpnt->request->rq_status,
-				       SCpnt->use_sg,
-
-				       SCpnt->retries,
-				       SCpnt->allowed,
-				       SCpnt->flags,
-
-				       SCpnt->timeout_per_command,
-				       SCpnt->timeout,
-				       SCpnt->internal_timeout,
-
-				       SCpnt->cmnd[0],
-				       SCpnt->sense_buffer[2],
-				       SCpnt->result);
-			}
-		}
-	}
-#endif	/* CONFIG_SCSI_LOGGING */ /* } */
 }
-#endif				/* CONFIG_PROC_FS */
 
-static char *scsihosts;
-
-MODULE_PARM(scsihosts, "s");
+static char *scsi_dev_flags;
+MODULE_PARM(scsi_dev_flags, "s");
+MODULE_PARM_DESC(scsi_dev_flags,
+	 "Given scsi_dev_flags=vendor:model:flags, add a black/white list"
+	 " entry for vendor and model with an integer value of flags"
+	 " to the scsi device info list");
+MODULE_PARM(scsi_default_dev_flags, "i");
+MODULE_PARM_DESC(scsi_default_dev_flags,
+		 "scsi default device flag integer value");
 MODULE_DESCRIPTION("SCSI core");
 MODULE_LICENSE("GPL");
 
 #ifndef MODULE
-int __init scsi_setup(char *str)
+
+int __init setup_scsi_dev_flags(char *str)
 {
-	scsihosts = str;
+	scsi_dev_flags = str;
 	return 1;
 }
+__setup("scsi_dev_flags=", setup_scsi_dev_flags);
 
-__setup("scsihosts=", scsi_setup);
-#endif
+static int __init setup_scsi_default_dev_flags(char *str)
+{
+	unsigned int tmp;
+	if (get_option(&str, &tmp) == 1) {
+		scsi_default_dev_flags = tmp;
+		printk(KERN_WARNING "%s %d\n", __FUNCTION__,
+		       scsi_default_dev_flags);
+		return 1;
+	} else {
+		printk(KERN_WARNING "%s: usage scsi_default_dev_flags=intr\n",
+		       __FUNCTION__);
+		return 0;
+	}
+}
+__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
 
+#endif
 static void *scsi_pool_alloc(int gfp_mask, void *data)
 {
 	return kmem_cache_alloc(data, gfp_mask);
@@ -2365,7 +2205,6 @@
 
 static int __init init_scsi(void)
 {
-	struct proc_dir_entry *generic;
 	int i;
 
 	printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
@@ -2379,40 +2218,17 @@
 
 		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");
+			printk(KERN_ERR "SCSI: can't init sg slab %s\n", sgp->name);
 
 		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");
+			printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name);
 	}
 
-	/*
-	 * This makes /proc/scsi and /proc/scsi/scsi visible.
-	 */
-#ifdef CONFIG_PROC_FS
-	proc_scsi = proc_mkdir("scsi", 0);
-	if (!proc_scsi) {
-		printk (KERN_ERR "cannot init /proc/scsi\n");
-		return -ENOMEM;
-	}
-	generic = create_proc_info_entry ("scsi/scsi", 0, 0, scsi_proc_info);
-	if (!generic) {
-		printk (KERN_ERR "cannot init /proc/scsi/scsi\n");
-		remove_proc_entry("scsi", 0);
-		return -ENOMEM;
-	}
-	generic->write_proc = proc_scsi_gen_write;
-#endif
-
-        scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
-
-	scsi_host_hn_init(scsihosts);
-
+	scsi_host_init();
+	scsi_dev_info_list_init(scsi_dev_flags);
 	bus_register(&scsi_driverfs_bus_type);
-
-	/* Where we handle work queued by scsi_done */
 	open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
-
 	return 0;
 }
 
@@ -2420,16 +2236,10 @@
 {
 	int i;
 
-        devfs_unregister (scsi_devfs_handle);
-
-	scsi_host_hn_release();
+	devfs_unregister(scsi_devfs_handle);
+	scsi_exit_procfs();
+	scsi_dev_info_list_delete();
 
-#ifdef CONFIG_PROC_FS
-	/* No, we're not here anymore. Don't show the /proc/scsi files. */
-	remove_proc_entry ("scsi/scsi", 0);
-	remove_proc_entry ("scsi", 0);
-#endif
-	
 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
 		mempool_destroy(sgp->pool);
@@ -2533,112 +2343,3 @@
 		kfree(SDpnt->inquiry);
         kfree(SDpnt);
 }
-
-/*
- * Function:	scsi_reset_provider_done_command
- *
- * Purpose:	Dummy done routine.
- *
- * Notes:	Some low level drivers will call scsi_done and end up here,
- *		others won't bother.
- *		We don't want the bogus command used for the bus/device
- *		reset to find its way into the mid-layer so we intercept
- *		it here.
- */
-static void
-scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt)
-{
-}
-
-/*
- * Function:	scsi_reset_provider
- *
- * Purpose:	Send requested reset to a bus or device at any phase.
- *
- * Arguments:	device	- device to send reset to
- *		flag - reset type (see scsi.h)
- *
- * Returns:	SUCCESS/FAILURE.
- *
- * Notes:	This is used by the SCSI Generic driver to provide
- *		Bus/Device reset capability.
- */
-int
-scsi_reset_provider(Scsi_Device *dev, int flag)
-{
-	Scsi_Cmnd SC, *SCpnt = &SC;
-        struct request req;
-	int rtn;
-
-        SCpnt->request = &req;
-	memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
-	SCpnt->host                    	= dev->host;
-	SCpnt->device                  	= dev;
-	SCpnt->target                  	= dev->id;
-	SCpnt->lun                     	= dev->lun;
-	SCpnt->channel                 	= dev->channel;
-	SCpnt->request->rq_status      	= RQ_SCSI_BUSY;
-	SCpnt->request->waiting        	= NULL;
-	SCpnt->use_sg                  	= 0;
-	SCpnt->old_use_sg              	= 0;
-	SCpnt->old_cmd_len             	= 0;
-	SCpnt->underflow               	= 0;
-	SCpnt->transfersize            	= 0;
-	SCpnt->resid			= 0;
-	SCpnt->serial_number           	= 0;
-	SCpnt->serial_number_at_timeout	= 0;
-	SCpnt->host_scribble           	= NULL;
-	SCpnt->next                    	= NULL;
-	SCpnt->state                   	= SCSI_STATE_INITIALIZING;
-	SCpnt->owner	     		= SCSI_OWNER_MIDLEVEL;
-    
-	memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd));
-    
-	SCpnt->scsi_done		= scsi_reset_provider_done_command;
-	SCpnt->done			= NULL;
-	SCpnt->reset_chain		= NULL;
-        
-	SCpnt->buffer			= NULL;
-	SCpnt->bufflen			= 0;
-	SCpnt->request_buffer		= NULL;
-	SCpnt->request_bufflen		= 0;
-
-	SCpnt->internal_timeout		= NORMAL_TIMEOUT;
-	SCpnt->abort_reason		= DID_ABORT;
-
-	SCpnt->cmd_len			= 0;
-
-	SCpnt->sc_data_direction	= SCSI_DATA_UNKNOWN;
-	SCpnt->sc_request		= NULL;
-	SCpnt->sc_magic			= SCSI_CMND_MAGIC;
-
-	/*
-	 * Sometimes the command can get back into the timer chain,
-	 * so use the pid as an identifier.
-	 */
-	SCpnt->pid			= 0;
-
-        rtn = scsi_new_reset(SCpnt, flag);
-
-	scsi_delete_timer(SCpnt);
-	return rtn;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/scsi.h	Sun Nov 17 20:30:12 2002
@@ -391,6 +391,11 @@
 #include "scsi_obsolete.h"
 
 /*
+ * Forward-declaration of structs for prototypes.
+ */
+struct Scsi_Host;
+
+/*
  * Add some typedefs so that we can prototyope a bunch of the functions.
  */
 typedef struct scsi_device Scsi_Device;
@@ -404,15 +409,7 @@
  * Here is where we prototype most of the mid-layer.
  */
 
-/*
- *  Initializes all SCSI devices.  This scans all scsi busses.
- */
-
 extern unsigned int scsi_logging_level;		/* What do we log? */
-extern unsigned int scsi_dma_free_sectors;	/* How much room do we have left */
-extern unsigned int scsi_need_isa_buffer;	/* True if some devices need indirection
-						   * buffers */
-extern volatile int in_scan_scsis;
 
 extern struct bus_type scsi_driverfs_bus_type;
 
@@ -455,6 +452,7 @@
 extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
 			       int block_sectors);
 extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt);
+extern int scsi_prep_fn(struct request_queue *q, struct request *req);
 extern void scsi_request_fn(request_queue_t * q);
 extern int scsi_starvation_completion(Scsi_Device * SDpnt);
 
@@ -480,9 +478,9 @@
 			int timeout, int retries);
 extern int scsi_dev_init(void);
 extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
-extern void scsi_detect_device(struct scsi_device *);
 extern int scsi_attach_device(struct scsi_device *);
 extern void scsi_detach_device(struct scsi_device *);
+extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model);
 
 /*
  * Newer request-based interfaces.
@@ -500,17 +498,24 @@
 extern int scsi_insert_special_req(Scsi_Request * SRpnt, int);
 extern void scsi_init_cmd_from_req(Scsi_Cmnd *, Scsi_Request *);
 
-
-/*
- * Prototypes for functions/data in hosts.c
- */
-extern int max_scsi_hosts;
-
 /*
  * Prototypes for functions in scsi_proc.c
  */
-extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
+#ifdef CONFIG_PROC_FS
+extern int scsi_init_procfs(void);
+extern void scsi_exit_procfs(void);
+
+extern void scsi_proc_host_add(struct Scsi_Host *);
+extern void scsi_proc_host_rm(struct Scsi_Host *);
+
 extern struct proc_dir_entry *proc_scsi;
+#else
+static inline int scsi_init_procfs(void) { return 0; };
+static inline void scsi_exit_procfs(void) { };
+
+static inline void scsi_proc_host_add(struct Scsi_Host *);
+static inline void scsi_proc_host_rm(struct Scsi_Host *);
+#endif /* CONFIG_PROC_FS */
 
 /*
  * Prototypes for functions in constants.c
@@ -528,6 +533,31 @@
 extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
 
 /*
+ * dev_info: for the black/white list in the old scsi_static_device_list
+ */
+struct dev_info {
+	char *vendor;
+	char *model;
+	char *revision;	/* revision known to be bad, unused */
+	unsigned flags;
+};
+
+extern struct dev_info scsi_static_device_list[] __initdata;
+
+/*
+ * scsi_dev_info_list: structure to hold black/white listed devices.
+ */
+struct scsi_dev_info_list {
+	struct list_head dev_info_list;
+	char vendor[8];
+	char model[16];
+	unsigned flags;
+	unsigned compatible; /* for use with scsi_static_device_list entries */
+};
+extern struct list_head scsi_dev_info_list;
+extern int scsi_dev_info_list_add_str(char *);
+
+/*
  *  The scsi_device struct contains what we know about each given scsi
  *  device.
  *
@@ -837,25 +867,6 @@
 #define SCSI_MLQUEUE_HOST_BUSY   0x1055
 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
 
-#define SCSI_SLEEP(QUEUE, CONDITION) {		    \
-    if (CONDITION) {			            \
-	DECLARE_WAITQUEUE(wait, current);	    \
-	add_wait_queue(QUEUE, &wait);		    \
-	for(;;) {			            \
-	set_current_state(TASK_UNINTERRUPTIBLE);    \
-	if (CONDITION) {		            \
-            if (in_interrupt())	                    \
-	        panic("scsi: trying to call schedule() in interrupt" \
-		      ", file %s, line %d.\n", __FILE__, __LINE__);  \
-	    schedule();			\
-        }				\
-	else			        \
-	    break;      		\
-	}			        \
-	remove_wait_queue(QUEUE, &wait);\
-	current->state = TASK_RUNNING;	\
-    }; }
-
 /*
  * old style reset request from external source
  * (private to sg.c and scsi_error.c, supplied by scsi_obsolete.c)
@@ -885,8 +896,9 @@
 static inline void scsi_activate_tcq(Scsi_Device *SDpnt, int depth) {
         request_queue_t *q = &SDpnt->request_queue;
 
-        if(SDpnt->tagged_supported && !blk_queue_tagged(q)) {
-                blk_queue_init_tags(q, depth);
+        if(SDpnt->tagged_supported) {
+		if(!blk_queue_tagged(q))
+			blk_queue_init_tags(q, depth);
 		scsi_adjust_queue_depth(SDpnt, MSG_ORDERED_TAG, depth);
         }
 }
@@ -895,9 +907,12 @@
  * scsi_deactivate_tcq - turn off tag command queueing
  * @SDpnt:	device to turn off TCQ for
  **/
-static inline void scsi_deactivate_tcq(Scsi_Device *SDpnt) {
-        blk_queue_free_tags(&SDpnt->request_queue);
-	scsi_adjust_queue_depth(SDpnt, 0, 2);
+static inline void scsi_deactivate_tcq(Scsi_Device *SDpnt, int depth) {
+	request_queue_t *q = &SDpnt->request_queue;
+
+	if(blk_queue_tagged(q))
+		blk_queue_free_tags(q);
+	scsi_adjust_queue_depth(SDpnt, 0, depth);
 }
 
 /**
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/scsi_debug.c	Sun Nov 17 20:30:14 2002
@@ -1,14 +1,15 @@
 /* 
  *  linux/kernel/scsi_debug.c
- *
+ * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  *  Copyright (C) 1992  Eric Youngdale
  *  Simulate a host adapter with 2 disks attached.  Do a lot of checking
  *  to make sure that we are not getting blocks mixed up, and PANIC if
  *  anything out of the ordinary is seen.
+ * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  *
  *  This version is more generic, simulating a variable number of disk 
- *  (or disk like devices) sharing a common amount of RAM (default 8 MB
- *  but can be set at driver/module load time).
+ *  (or disk like devices) sharing a common amount of RAM 
+ *  
  *
  *  For documentation see http://www.torque.net/sg/sdebug.html
  *
@@ -36,8 +37,6 @@
 #include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 
-#include <asm/io.h>
-
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
@@ -50,10 +49,7 @@
 
 #include "scsi_debug.h"
 
-static const char * scsi_debug_version_str = "Version: 1.63 (20021103)";
-
-#define DRIVERFS_SUPPORT 1	/* comment out whole line to disable */
-
+static const char * scsi_debug_version_str = "Version: 1.64 (20021111 2)";
 
 #ifndef SCSI_CMD_READ_16
 #define SCSI_CMD_READ_16 0x88
@@ -72,6 +68,8 @@
 #define DEF_DELAY   1
 #define DEF_MAX_LUNS   2
 #define DEF_SCSI_LEVEL   3
+#define DEF_NUM_HOST   1
+#define MAX_NUM_HOSTS   128
 
 #define DEF_OPTS   0
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -87,8 +85,8 @@
 static int scsi_debug_delay = DEF_DELAY;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
 static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
+static int scsi_debug_add_host = DEF_NUM_HOST;
 
-#define NR_HOSTS_PRESENT (((scsi_debug_num_devs - 1) / 7) + 1)
 	/* This assumes one lun used per allocated target id */
 #define N_HEAD          8
 #define N_SECTOR        32
@@ -109,6 +107,7 @@
 #define CAPACITY (N_HEAD * N_SECTOR * N_CYLINDER)
 #define SECT_SIZE_PER(TGT) SECT_SIZE
 
+struct Scsi_Host *scsi_debug_hosts[MAX_NUM_HOSTS];
 
 #define SDEBUG_SENSE_LEN 32
 
@@ -146,9 +145,7 @@
 static spinlock_t queued_arr_lock = SPIN_LOCK_UNLOCKED;
 static rwlock_t atomic_rw = RW_LOCK_UNLOCKED;
 
-#ifdef DRIVERFS_SUPPORT
 static struct device_driver sdebug_driverfs_driver;
-#endif
 
 /* function declarations */
 static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
@@ -176,10 +173,9 @@
 static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
 static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
                            const char * dev_id_str, int dev_id_str_len);
-#ifdef DRIVERFS_SUPPORT
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
-#endif
+static struct Scsi_Host * sdebug_add_shost(void);
 
 
 static unsigned char * scatg2virt(const struct scatterlist * sclp)
@@ -225,7 +221,7 @@
 		bufflen = SDEBUG_SENSE_LEN;
 	}
 
-        if(target == driver_template.this_id) {
+        if(target == sdebug_driver_template.this_id) {
                 printk(KERN_WARNING 
 		       "scsi_debug: initiator's id used as target!\n");
 		return schedule_resp(SCpnt, NULL, done, 0, 0);
@@ -809,92 +805,8 @@
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int initialized = 0;
-static int num_hosts_present = 0;
 static const char * sdebug_proc_name = "scsi_debug";
 
-static int scsi_debug_detect(struct SHT * tpnt)
-{
-	int k, sz;
-	struct Scsi_Host * hpnt;
-
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: detect\n");
-	if (0 == initialized) {
-		++initialized;
-		sz = sizeof(struct sdebug_dev_info) * scsi_debug_num_devs;
-		devInfop = vmalloc(sz);
-		if (NULL == devInfop) {
-			printk(KERN_ERR "scsi_debug_detect: out of "
-			       "memory\n");
-			return 0;
-		}
-		memset(devInfop, 0, sz);
-		sz = STORE_SIZE;
-		fake_storep = vmalloc(sz);
-		if (NULL == fake_storep) {
-			printk(KERN_ERR "scsi_debug_detect: out of memory"
-			       ", 1\n");
-			return 0;
-		}
-		memset(fake_storep, 0, sz);
-		init_all_queued();
-#ifdef DRIVERFS_SUPPORT
-		sdebug_driverfs_driver.name = (char *)sdebug_proc_name;
-		sdebug_driverfs_driver.bus = &scsi_driverfs_bus_type;
-		driver_register(&sdebug_driverfs_driver);
-		do_create_driverfs_files();
-#endif
-		tpnt->proc_name = (char *)sdebug_proc_name;
-		for (num_hosts_present = 0, k = 0; k < NR_HOSTS_PRESENT; k++) {
-			if ((hpnt = scsi_register(tpnt, 0)) == NULL)
-				printk(KERN_ERR "scsi_debug_detect: "
-					"scsi_register failed k=%d\n", k);
-			else {
-				hpnt->max_lun = scsi_debug_max_luns;
-				++num_hosts_present;
-			}
-		}
-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: ... built %d host(s)\n",
-			       num_hosts_present);
-		return num_hosts_present;
-	} else {
-		printk(KERN_WARNING "scsi_debug_detect: called again\n");
-		return 0;
-	}
-}
-
-
-static int num_releases = 0;
-
-static int scsi_debug_release(struct Scsi_Host * hpnt)
-{
-	int host_no = hpnt->host_no;
-
-	if (++num_releases == num_hosts_present) {
-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: [last] release, "
-			       "host_no=%u\n", host_no);
-		num_releases = 0;
-		initialized = 0;
-		stop_all_queued();
-#ifdef DRIVERFS_SUPPORT
-		do_remove_driverfs_files();
-		driver_unregister(&sdebug_driverfs_driver);
-#endif
-		vfree(fake_storep);
-		vfree(devInfop);
-	}
-	else {
-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: release, host_no=%u\n",
-			       host_no);
-	}
-	scsi_unregister(hpnt);
-	return 0;
-}
-
 static int scsi_debug_slave_attach(struct scsi_device * sdp)
 {
 	int k;
@@ -1290,6 +1202,22 @@
 }
 __setup("scsi_debug_delay=", delay_setup);
 
+static int __init add_host_setup(char *str)
+{
+    int tmp;
+
+    if (get_option(&str, &tmp) == 1) {
+	scsi_debug_add_host = tmp;
+        return 1;
+    } else {
+        printk(KERN_INFO "scsi_debug_add_host: usage "
+               "scsi_debug_add_host=<n>\n"
+               "    <n> 0..127 (default 1)\n");
+        return 0;
+    }
+}
+__setup("scsi_debug_add_host=", add_host_setup);
+
 #endif
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
@@ -1308,6 +1236,8 @@
 MODULE_PARM_DESC(scsi_debug_every_nth, "timeout every nth command(def=100)");
 MODULE_PARM(scsi_debug_delay, "i");
 MODULE_PARM_DESC(scsi_debug_delay, "# of jiffies to delay response(def=1)");
+MODULE_PARM(scsi_debug_add_host, "i");
+MODULE_PARM_DESC(scsi_debug_add_host, "0..127 hosts allowed(def=1)");
 MODULE_LICENSE("GPL");
 
 static char sdebug_info[256];
@@ -1372,7 +1302,6 @@
 	return len;
 }
 
-#ifdef DRIVERFS_SUPPORT
 static ssize_t sdebug_delay_read(struct device_driver * ddp, char * buf, 
 				 size_t count, loff_t off)
 {
@@ -1464,6 +1393,58 @@
 }
 DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_read, NULL) 
 
+static ssize_t sdebug_add_host_read(struct device_driver * ddp, char * buf, 
+				    size_t count, loff_t off)
+{
+        return off ? 0 : snprintf(buf, count, "%d\n", scsi_debug_add_host);
+}
+
+static ssize_t sdebug_add_host_write(struct device_driver * ddp, 
+				  const char * buf, size_t count, loff_t off)
+{
+	struct Scsi_Host * hpnt;
+        int delta_hosts, k;
+	char work[20];
+
+        if (off)
+                return 0;
+        if (1 != sscanf(buf, "%10s", work))
+		return -EINVAL;
+	if (1 != sscanf(work, "%d", &delta_hosts))
+		return -EINVAL;
+	if (delta_hosts > 0) {
+		do {
+			for (k = 0; k < MAX_NUM_HOSTS; ++k) {
+				if (NULL == scsi_debug_hosts[k]) {
+					hpnt = sdebug_add_shost();
+					scsi_debug_hosts[k] = hpnt;
+					break;
+				}
+			}
+			if (k == MAX_NUM_HOSTS)
+				break;
+			++scsi_debug_add_host;
+		} while (--delta_hosts);
+	} else if (delta_hosts < 0) {
+		do {
+			for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) {
+				if (scsi_debug_hosts[k]) {
+					scsi_remove_host(scsi_debug_hosts[k]);
+					scsi_unregister(scsi_debug_hosts[k]);
+					scsi_debug_hosts[k] = NULL;
+					break;
+				}
+			}
+			if (k < 0)
+				break;
+			--scsi_debug_add_host;
+		} while (++delta_hosts);
+	}
+	return count;
+}
+DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_read, 
+	    sdebug_add_host_write)
+
 static void do_create_driverfs_files()
 {
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
@@ -1473,10 +1454,12 @@
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
 static void do_remove_driverfs_files()
 {
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
@@ -1485,6 +1468,98 @@
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay);
 }
-#endif
 
-#include "scsi_module.c"
+static struct Scsi_Host * sdebug_add_shost(void)
+{
+	struct Scsi_Host * hpnt;
+	int err;
+
+	hpnt = scsi_register(&sdebug_driver_template, 0);
+	if (NULL == hpnt) {
+		printk(KERN_ERR "sdebug_add_shost: scsi_register failed\n");
+		return NULL;
+	}
+	err = scsi_add_host(hpnt);
+	if (err) {
+		printk(KERN_ERR "sdebug_add_shost: scsi_add_host failed\n");
+		scsi_unregister(hpnt);
+		return NULL;
+	}
+	hpnt->max_lun = scsi_debug_max_luns;
+	return hpnt;
+}
+
+
+static int __init scsi_debug_init(void)
+{
+	int sz, k;
+
+	if (scsi_debug_num_devs > 0) {
+		sz = sizeof(struct sdebug_dev_info) * scsi_debug_num_devs;
+		devInfop = vmalloc(sz);
+		if (NULL == devInfop) {
+			printk(KERN_ERR "scsi_debug_init: out of memory\n");
+			return -ENOMEM;
+		}
+		memset(devInfop, 0, sz);
+	}
+
+	sz = STORE_SIZE;
+	fake_storep = vmalloc(sz);
+	if (NULL == fake_storep) {
+		printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
+		if (devInfop)
+			vfree(devInfop);
+		return -ENOMEM;
+	}
+	memset(fake_storep, 0, sz);
+
+	init_all_queued();
+
+	sdebug_driverfs_driver.name = (char *)sdebug_proc_name;
+	sdebug_driverfs_driver.bus = &scsi_driverfs_bus_type;
+	driver_register(&sdebug_driverfs_driver);
+	do_create_driverfs_files();
+
+	sdebug_driver_template.proc_name = (char *)sdebug_proc_name;
+
+	memset(scsi_debug_hosts, 0, sizeof(struct Scsi_Host *) * MAX_NUM_HOSTS);
+	for (k = 0; (k < scsi_debug_add_host) && (k < MAX_NUM_HOSTS); k++) {
+		scsi_debug_hosts[k] = sdebug_add_shost();
+		if (NULL == scsi_debug_hosts[k]) {
+			printk(KERN_ERR "scsi_debug_init: "
+			       "sdebug_add_shost failed k=%d\n", k);
+			break;
+		}
+	}
+	scsi_debug_add_host = k;	// number of hosts actually present
+
+	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+		printk(KERN_INFO "scsi_debug: ... built %d host(s)\n",
+		       scsi_debug_add_host);
+	}
+	return 0;
+}
+
+static void __exit scsi_debug_exit(void)
+{
+	int k;
+
+	for (k = MAX_NUM_HOSTS - 1; k >= 0; --k) {
+		if (scsi_debug_hosts[k]) {
+			scsi_remove_host(scsi_debug_hosts[k]);
+			scsi_unregister(scsi_debug_hosts[k]);
+			scsi_debug_hosts[k] = NULL;
+		}
+	}
+	stop_all_queued();
+	do_remove_driverfs_files();
+	driver_unregister(&sdebug_driverfs_driver);
+
+	vfree(fake_storep);
+	if (devInfop)
+		vfree(devInfop);
+}
+
+module_init(scsi_debug_init);
+module_exit(scsi_debug_exit);
diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
--- a/drivers/scsi/scsi_debug.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/scsi_debug.h	Sun Nov 17 20:30:14 2002
@@ -1,13 +1,9 @@
 #ifndef _SCSI_DEBUG_H
 
 #include <linux/types.h>
-#include <linux/kdev_t.h>
 
-static int scsi_debug_detect(struct SHT *);
 static int scsi_debug_slave_attach(struct scsi_device *);
 static void scsi_debug_slave_detach(struct scsi_device *);
-static int scsi_debug_release(struct Scsi_Host *);
-/* static int scsi_debug_command(struct scsi_cmnd *); */
 static int scsi_debug_queuecommand(struct scsi_cmnd *, 
 				   void (*done) (struct scsi_cmnd *));
 static int scsi_debug_ioctl(struct scsi_device *, int, void *);
@@ -20,10 +16,6 @@
 static int scsi_debug_proc_info(char *, char **, off_t, int, int, int);
 static const char * scsi_debug_info(struct Scsi_Host *);
 
-#ifndef NULL
-#define NULL 0
-#endif
-
 /*
  * This driver is written for the lk 2.5 series
  */
@@ -31,14 +23,12 @@
 
 #define SCSI_DEBUG_MAX_CMD_LEN 16
 
-static Scsi_Host_Template driver_template = {
+static Scsi_Host_Template sdebug_driver_template = {
 	.proc_info =		scsi_debug_proc_info,
 	.name =			"SCSI DEBUG",
 	.info =			scsi_debug_info,
-	.detect =		scsi_debug_detect,
 	.slave_attach =		scsi_debug_slave_attach,
 	.slave_detach =		scsi_debug_slave_detach,
-	.release =		scsi_debug_release,
 	.ioctl =		scsi_debug_ioctl,
 	.queuecommand =		scsi_debug_queuecommand,
 	.eh_abort_handler =	scsi_debug_abort,
@@ -50,8 +40,9 @@
 	.this_id =		7,
 	.sg_tablesize =		64,
 	.cmd_per_lun =		3,
+	.max_sectors =		4096,
 	.unchecked_isa_dma = 	0,
 	.use_clustering = 	ENABLE_CLUSTERING,
-};	/* the name 'driver_template' is used by scsi_module.c */
+};
 
 #endif
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/scsi_error.c	Sun Nov 17 20:30:02 2002
@@ -177,8 +177,7 @@
  **/
 int scsi_block_when_processing_errors(Scsi_Device *sdev)
 {
-
-	SCSI_SLEEP(&sdev->host->host_wait, sdev->host->in_recovery);
+	wait_event(sdev->host->host_wait, (sdev->host->in_recovery == 0));
 
 	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __FUNCTION__,
 					  sdev->online));
@@ -1715,7 +1714,7 @@
  * Return value:
  *    SUCCESS/FAILED.
  **/
-int scsi_new_reset(Scsi_Cmnd *scmd, int flag)
+static int scsi_new_reset(Scsi_Cmnd *scmd, int flag)
 {
 	int rtn;
 
@@ -1737,5 +1736,84 @@
 		rtn = FAILED;
 	}
 
+	return rtn;
+}
+
+static void
+scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt)
+{
+}
+
+/*
+ * Function:	scsi_reset_provider
+ *
+ * Purpose:	Send requested reset to a bus or device at any phase.
+ *
+ * Arguments:	device	- device to send reset to
+ *		flag - reset type (see scsi.h)
+ *
+ * Returns:	SUCCESS/FAILURE.
+ *
+ * Notes:	This is used by the SCSI Generic driver to provide
+ *		Bus/Device reset capability.
+ */
+int
+scsi_reset_provider(Scsi_Device *dev, int flag)
+{
+	struct scsi_cmnd SC, *SCpnt = &SC;
+	struct request req;
+	int rtn;
+
+	SCpnt->request = &req;
+	memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
+	SCpnt->host                    	= dev->host;
+	SCpnt->device                  	= dev;
+	SCpnt->target                  	= dev->id;
+	SCpnt->lun                     	= dev->lun;
+	SCpnt->channel                 	= dev->channel;
+	SCpnt->request->rq_status      	= RQ_SCSI_BUSY;
+	SCpnt->request->waiting        	= NULL;
+	SCpnt->use_sg                  	= 0;
+	SCpnt->old_use_sg              	= 0;
+	SCpnt->old_cmd_len             	= 0;
+	SCpnt->underflow               	= 0;
+	SCpnt->transfersize            	= 0;
+	SCpnt->resid			= 0;
+	SCpnt->serial_number           	= 0;
+	SCpnt->serial_number_at_timeout	= 0;
+	SCpnt->host_scribble           	= NULL;
+	SCpnt->next                    	= NULL;
+	SCpnt->state                   	= SCSI_STATE_INITIALIZING;
+	SCpnt->owner	     		= SCSI_OWNER_MIDLEVEL;
+    
+	memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd));
+    
+	SCpnt->scsi_done		= scsi_reset_provider_done_command;
+	SCpnt->done			= NULL;
+	SCpnt->reset_chain		= NULL;
+        
+	SCpnt->buffer			= NULL;
+	SCpnt->bufflen			= 0;
+	SCpnt->request_buffer		= NULL;
+	SCpnt->request_bufflen		= 0;
+
+	SCpnt->internal_timeout		= NORMAL_TIMEOUT;
+	SCpnt->abort_reason		= DID_ABORT;
+
+	SCpnt->cmd_len			= 0;
+
+	SCpnt->sc_data_direction	= SCSI_DATA_UNKNOWN;
+	SCpnt->sc_request		= NULL;
+	SCpnt->sc_magic			= SCSI_CMND_MAGIC;
+
+	/*
+	 * Sometimes the command can get back into the timer chain,
+	 * so use the pid as an identifier.
+	 */
+	SCpnt->pid			= 0;
+
+	rtn = scsi_new_reset(SCpnt, flag);
+
+	scsi_delete_timer(SCpnt);
 	return rtn;
 }
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/scsi_lib.c	Sun Nov 17 20:30:14 2002
@@ -102,6 +102,13 @@
 {
 	request_queue_t *q = &SRpnt->sr_device->request_queue;
 
+	/* This is used to insert SRpnt specials.  Because users of
+	 * this function are apt to reuse requests with no modification,
+	 * we have to sanitise the request flags here
+	 */
+
+	SRpnt->sr_request->flags &= ~REQ_DONTPREP;
+
 	blk_insert_request(q, SRpnt->sr_request, at_head, SRpnt);
 	return 0;
 }
@@ -240,6 +247,12 @@
 		SCpnt->request->special = (void *) SCpnt;
 		if(blk_rq_tagged(SCpnt->request))
 			blk_queue_end_tag(q, SCpnt->request);
+		/* set REQ_SPECIAL - we have a command
+		 * clear REQ_DONTPREP - we assume the sg table has been 
+		 *	nuked so we need to set it up again.
+		 */
+		SCpnt->request->flags |= REQ_SPECIAL;
+		SCpnt->request->flags &= ~REQ_DONTPREP;
 		__elv_add_request(q, SCpnt->request, 0, 0);
 	}
 
@@ -714,13 +727,15 @@
  *
  * Arguments:   SCpnt   - Command descriptor we wish to initialize
  *
- * Returns:     1 on success.
+ * Returns:     0 on success
+ *		BLKPREP_DEFER if the failure is retryable
+ *		BLKPREP_KILL if the failure is fatal
  */
 static int scsi_init_io(Scsi_Cmnd *SCpnt)
 {
 	struct request     *req = SCpnt->request;
 	struct scatterlist *sgpnt;
-	int count, gfp_mask;
+	int count, gfp_mask, ret = 0;
 
 	/*
 	 * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer
@@ -730,7 +745,7 @@
 		SCpnt->request_buffer = req->data;
 		req->buffer = req->data;
 		SCpnt->use_sg = 0;
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -741,7 +756,7 @@
 	SCpnt->use_sg = req->nr_phys_segments;
 
 	gfp_mask = GFP_NOIO;
-	if (in_interrupt()) {
+	if (likely(in_atomic())) {
 		gfp_mask &= ~__GFP_WAIT;
 		gfp_mask |= __GFP_HIGH;
 	}
@@ -750,8 +765,11 @@
 	 * if sg table allocation fails, requeue request later.
 	 */
 	sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
-	if (unlikely(!sgpnt))
+	if (unlikely(!sgpnt)) {
+		req->flags |= REQ_SPECIAL;
+		ret = BLKPREP_DEFER;
 		goto out;
+	}
 
 	SCpnt->request_buffer = (char *) sgpnt;
 	SCpnt->request_bufflen = req->nr_sectors << 9;
@@ -768,12 +786,11 @@
 	/*
 	 * mapped well, send it off
 	 */
-	if (unlikely(count > SCpnt->use_sg))
-		goto incorrect;
-	SCpnt->use_sg = count;
-	return 1;
+	if (count <= SCpnt->use_sg) {
+		SCpnt->use_sg = count;
+		return 0;
+	}
 
-incorrect:
 	printk(KERN_ERR "Incorrect number of segments after building list\n");
 	printk(KERN_ERR "counted %d, received %d\n", count, SCpnt->use_sg);
 	printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
@@ -784,8 +801,117 @@
 	 */
 	SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
 	BUG_ON(SCpnt);
+	ret = BLKPREP_KILL;
 out:
-	return 0;
+	return ret;
+}
+
+int scsi_prep_fn(struct request_queue *q, struct request *req)
+{
+	struct Scsi_Device_Template *STpnt;
+	Scsi_Cmnd *SCpnt;
+	Scsi_Device *SDpnt;
+
+	SDpnt = (Scsi_Device *) q->queuedata;
+	BUG_ON(!SDpnt);
+
+	/*
+	 * Find the actual device driver associated with this command.
+	 * The SPECIAL requests are things like character device or
+	 * ioctls, which did not originate from ll_rw_blk.  Note that
+	 * the special field is also used to indicate the SCpnt for
+	 * the remainder of a partially fulfilled request that can 
+	 * come up when there is a medium error.  We have to treat
+	 * these two cases differently.  We differentiate by looking
+	 * at request->cmd, as this tells us the real story.
+	 */
+	if (req->flags & REQ_SPECIAL) {
+		Scsi_Request *SRpnt;
+
+		STpnt = NULL;
+		SCpnt = (Scsi_Cmnd *) req->special;
+		SRpnt = (Scsi_Request *) req->special;
+		
+		if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) {
+			SCpnt = scsi_allocate_device(SRpnt->sr_device, 
+						     FALSE, FALSE);
+			if (!SCpnt)
+				return BLKPREP_DEFER;
+			scsi_init_cmd_from_req(SCpnt, SRpnt);
+		}
+		
+	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+		/*
+		 * Now try and find a command block that we can use.
+		 */
+		if (req->special) {
+				SCpnt = (Scsi_Cmnd *) req->special;
+		} else {
+			SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
+		}
+		/*
+		 * if command allocation failure, wait a bit
+		 */
+		if (unlikely(!SCpnt))
+			return BLKPREP_DEFER;
+		
+		/* pull a tag out of the request if we have one */
+		SCpnt->tag = req->tag;
+	} else {
+		blk_dump_rq_flags(req, "SCSI bad req");
+		return BLKPREP_KILL;
+	}
+	
+	/* note the overloading of req->special.  When the tag
+	 * is active it always means SCpnt.  If the tag goes
+	 * back for re-queueing, it may be reset */
+	req->special = SCpnt;
+	SCpnt->request = req;
+	
+	/*
+	 * FIXME: drop the lock here because the functions below
+	 * expect to be called without the queue lock held.  Also,
+	 * previously, we dequeued the request before dropping the
+	 * lock.  We hope REQ_STARTED prevents anything untoward from
+	 * happening now.
+	 */
+
+	if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+		int ret;
+
+		/*
+		 * This will do a couple of things:
+		 *  1) Fill in the actual SCSI command.
+		 *  2) Fill in any other upper-level specific fields
+		 * (timeout).
+		 *
+		 * If this returns 0, it means that the request failed
+		 * (reading past end of disk, reading offline device,
+		 * etc).   This won't actually talk to the device, but
+		 * some kinds of consistency checking may cause the	
+		 * request to be rejected immediately.
+		 */
+		STpnt = scsi_get_request_dev(req);
+		BUG_ON(!STpnt);
+
+		/* 
+		 * This sets up the scatter-gather table (allocating if
+		 * required).
+		 */
+		if ((ret = scsi_init_io(SCpnt)))
+			return ret;
+		
+		/*
+		 * Initialize the actual SCSI command for this request.
+		 */
+		if (!STpnt->init_command(SCpnt)) {
+			scsi_release_buffers(SCpnt);
+			return BLKPREP_KILL;
+		}
+	}
+	/* The request is now prepped, no need to come back here */
+	req->flags |= REQ_DONTPREP;
+	return BLKPREP_OK;
 }
 
 /*
@@ -811,10 +937,8 @@
 {
 	struct request *req;
 	Scsi_Cmnd *SCpnt;
-	Scsi_Request *SRpnt;
 	Scsi_Device *SDpnt;
 	struct Scsi_Host *SHpnt;
-	struct Scsi_Device_Template *STpnt;
 
 	ASSERT_LOCK(q->queue_lock, 1);
 
@@ -837,6 +961,14 @@
 		if (SHpnt->in_recovery || blk_queue_plugged(q))
 			return;
 
+		/*
+		 * get next queueable request.  We do this early to make sure
+		 * that the request is fully prepared even if we cannot 
+		 * accept it.  If there is no request, we'll detect this
+		 * lower down.
+		 */
+		req = elv_next_request(q);
+
 		if(SHpnt->host_busy == 0 && SHpnt->host_blocked) {
 			/* unblock after host_blocked iterates to zero */
 			if(--SHpnt->host_blocked == 0) {
@@ -888,141 +1020,40 @@
 		if (blk_queue_empty(q))
 			break;
 
-		/*
-		 * get next queueable request.
-		 */
-		req = elv_next_request(q);
-
-		/*
-		 * Find the actual device driver associated with this command.
-		 * The SPECIAL requests are things like character device or
-		 * ioctls, which did not originate from ll_rw_blk.  Note that
-		 * the special field is also used to indicate the SCpnt for
-		 * the remainder of a partially fulfilled request that can 
-		 * come up when there is a medium error.  We have to treat
-		 * these two cases differently.  We differentiate by looking
-		 * at request->cmd, as this tells us the real story.
-		 */
-		if (req->flags & REQ_SPECIAL) {
-			STpnt = NULL;
-			SCpnt = (Scsi_Cmnd *) req->special;
-			SRpnt = (Scsi_Request *) req->special;
-
-			if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) {
-				SCpnt = scsi_allocate_device(SRpnt->sr_device, 
-							     FALSE, FALSE);
-				if (!SCpnt)
-					break;
-				scsi_init_cmd_from_req(SCpnt, SRpnt);
-			}
-
-		} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
-			SRpnt = NULL;
-			STpnt = scsi_get_request_dev(req);
-			if (!STpnt) {
-				panic("Unable to find device associated with request");
-			}
-			/*
-			 * Now try and find a command block that we can use.
-			 */
-			if (req->special) {
-				SCpnt = (Scsi_Cmnd *) req->special;
-			} else {
-				SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
-			}
-			/*
-			 * If so, we are ready to do something.  Bump the count
-			 * while the queue is locked and then break out of the
-			 * loop. Otherwise loop around and try another request.
-			 */
-			if (!SCpnt)
-				break;
-
-			/* pull a tag out of the request if we have one */
-			SCpnt->tag = req->tag;
-		} else {
-			blk_dump_rq_flags(req, "SCSI bad req");
+		if(!req) {
+			/* can happen if the prep fails 
+			 * FIXME: elv_next_request() should be plugging the
+			 * queue */
+			blk_plug_device(q);
 			break;
 		}
 
-		/*
-		 * Now bump the usage count for both the host and the
-		 * device.
+		SCpnt = (struct scsi_cmnd *)req->special;
+
+		/* Should be impossible for a correctly prepared request
+		 * please mail the stack trace to linux-scsi@vger.kernel.org
 		 */
-		SHpnt->host_busy++;
-		SDpnt->device_busy++;
+		BUG_ON(!SCpnt);
 
 		/*
 		 * Finally, before we release the lock, we copy the
 		 * request to the command block, and remove the
-		 * request from the request list.   Note that we always
+		 * request from the request list.  Note that we always
 		 * operate on the queue head - there is absolutely no
-		 * reason to search the list, because all of the commands
-		 * in this queue are for the same device.
+		 * reason to search the list, because all of the
+		 * commands in this queue are for the same device.
 		 */
 		if(!(blk_queue_tagged(q) && (blk_queue_start_tag(q, req) == 0)))
 			blkdev_dequeue_request(req);
-
-		/* note the overloading of req->special.  When the tag
-		 * is active it always means SCpnt.  If the tag goes
-		 * back for re-queueing, it may be reset */
-		req->special = SCpnt;
-		SCpnt->request = req;
-
+	
 		/*
-		 * Now it is finally safe to release the lock.  We are
-		 * not going to noodle the request list until this
-		 * request has been queued and we loop back to queue
-		 * another.  
+		 * Now bump the usage count for both the host and the
+		 * device.
 		 */
-		req = NULL;
+		SHpnt->host_busy++;
+		SDpnt->device_busy++;
 		spin_unlock_irq(q->queue_lock);
 
-		if (!(SCpnt->request->flags & REQ_DONTPREP)
-		    && (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC))) {
-			/*
-			 * This will do a couple of things:
-			 *  1) Fill in the actual SCSI command.
-			 *  2) Fill in any other upper-level specific fields
-			 * (timeout).
-			 *
-			 * If this returns 0, it means that the request failed
-			 * (reading past end of disk, reading offline device,
-			 * etc).   This won't actually talk to the device, but
-			 * some kinds of consistency checking may cause the	
-			 * request to be rejected immediately.
-			 */
-			if (STpnt == NULL)
-				STpnt = scsi_get_request_dev(SCpnt->request);
-
-			/* 
-			 * This sets up the scatter-gather table (allocating if
-			 * required).
-			 */
-			if (!scsi_init_io(SCpnt)) {
-				scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
-				spin_lock_irq(q->queue_lock);
-				break;
-			}
-
-			/*
-			 * Initialize the actual SCSI command for this request.
-			 */
-			if (!STpnt->init_command(SCpnt)) {
-				scsi_release_buffers(SCpnt);
-				SCpnt = __scsi_end_request(SCpnt, 0, 
-							   SCpnt->request->nr_sectors, 0, 0);
-				if( SCpnt != NULL )
-				{
-					panic("Should not have leftover blocks\n");
-				}
-				spin_lock_irq(q->queue_lock);
-				SHpnt->host_busy--;
-				SDpnt->device_busy--;
-				continue;
-			}
-		}
-		SCpnt->request->flags |= REQ_DONTPREP;
 		/*
 		 * Finally, initialize any error handling parameters, and set up
 		 * the timers for timeouts.
diff -Nru a/drivers/scsi/scsi_mid_low_api.txt b/drivers/scsi/scsi_mid_low_api.txt
--- a/drivers/scsi/scsi_mid_low_api.txt	Sun Nov 17 20:30:15 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,542 +0,0 @@
-                          Linux Kernel 2.5 series
-                    SCSI mid_level - lower_level interface
-                    ======================================
-
-Introduction
-============
-This document outlines the interface between the Linux scsi mid level
-and lower level drivers. Lower level drivers are variously called HBA
-(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
-The latter alludes to the fact that a lower level driver may be a
-bridge to another IO subsystem (and the "ide-scsi" driver is an example
-of this). There can be many lower level drivers active in a running
-system, but only one per hardware type. For example, the aic7xxx driver
-controls adaptec controllers based on the 7xxx chip series. Most lower 
-level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
-
-The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
-refers to this file. With the appropriate DocBook toolset, this permits
-users to generate html, ps and pdf renderings of information within this
-file (e.g. the interface functions).
-
-Driver structure
-================
-Traditionally a lower level driver for the scsi subsystem has been
-at least two files in the drivers/scsi directory. For example, a
-driver called "xyz" has a header file "xyz.h" and a source file
-"xyz.c". [Actually there is no good reason why this couldn't all
-be in one file.] Some drivers that have been ported to several operating
-systems (e.g. aic7xxx which has separate  files for generic and 
-OS-specific code) have more than two files. Such drivers tend to have 
-their own directory under the drivers/scsi directory.
-
-scsi_module.c is normally included at the end of a lower
-level driver. For it to work a declaration like this is needed before
-it is included:
-    static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
-    #include "scsi_module.c"
-
-In this case "DRIVER_TEMPLATE" is defined to be a structure initializer
-that is placed in the driver header file by convention. It contains
-pointers to supported interface functions and other values.
-Scsi_Host_Template is defined in hosts.h . 
-
-The scsi_module.c assumes the name "driver_template" is appropriately
-defined. scsi_module.c contains 2 functions:
-  1) init_this_scsi_driver() called during builtin and module driver
-     initialization: invokes mid level's scsi_register_host()
-  2) exit_this_scsi_driver() called during closedown: invokes
-     mid level's scsi_unregister_host()
-
-When a new, lower level driver is being added to Linux, the following 
-files (all found in the drivers/scsi directory) will need some attention: 
-Makefile, Config.help and Config.in . It is probably best to look at what 
-an existing lower level driver does in this regard.
-
-
-
-Interface Functions
-===================
-Interface functions should be declared static. The accepted convention
-is that driver "xyz" will declare its detect() function as:
-    static int xyz_detect(Scsi_Host_Template * shtp);
-
-A pointer to this function should be placed in the 'detect' member of
-a Scsi_Host_Template instance. A pointer to such an instance should
-passed to the mid level's scsi_register_host().
-
-The interface functions are listed below in alphabetical order.
-
-
-/**
- *      bios_param - fetch head, sector, cylinder info for a disk
- *      @sdev: pointer to scsi device context (defined in scsi.h)
- *      @bdev: pointer to block device context (defined in fs.h)
- *	@capacity:  device size
- *      @params: three element array to place output:
- *              params[0] number of heads
- *              params[1] number of sectors
- *              params[2] number of cylinders
- *
- *      Return value is ignored
- *
- *      Required: no
- *
- *      Locks: none
- *
- *      Notes: sd driver will make up geometry (based on READ CAPACITY)
- *      if this function is not provided. The params array is
- *      pre-initialized with made up values just in case this function 
- *      doesn't output anything.
- **/
-    int bios_param(struct scsi_device * sdev, struct block_device *bdev,
-    			sector_t capacity, int params[3]);
-
-
-/**
- *      command - send scsi command to device, wait for reply
- *      @scp: pointer to scsi command object
- *
- *      Returns an int with four component bytes: scsi_byte, msg_byte, 
- *      host_byte, driver_byte (status_byte is in the lsb). A value of
- *      0 is an unqualified success.
- *
- *      Required: if Scsi_Host::can_queue can ever by cleared (zero)
- *                then this function is required.
- *
- *      Locks: Scsi_Host::host_lock held on entry (with "irqsave") and
- *             is expected to be held on return.
- *
- *      Notes: Drivers tend to be dropping support for this function and
- *      rather supporting queuecommand().
- **/
-    int command(Scsi_Cmnd * scp);
-
-
-/**
- *      detect - detects HBAs this driver wants to control
- *      @shtp: host template for this driver.
- *
- *      Returns number of hosts this driver wants to control. 0 means no
- *      suitable hosts found.
- *
- *      Required: yes
- *
- *      Locks: none held
- *
- *      Notes: First function called from the scsi mid level on this
- *      driver. Upper level drivers (e.g. sd) may not (yet) be present.
- *      For each host found, this method should call scsi_register() 
- *      [see hosts.c].
- **/
-    int detect(Scsi_Host_Template * shtp);
-
-
-/**
- *      eh_abort_handler - abort command associated with scp
- *      @scp: identifies command to be aborted
- *
- *      Returns SUCCESS if command aborted else FAILED
- *
- *      Required: no
- *
- *      Locks: Scsi_Host::host_lock held (with irqsave) on entry and assumed
- *      to be held on return.
- *
- *      Notes: Invoked from scsi_eh thread. No other commands will be
- *      queued on current host during eh.
- **/
-     int eh_abort_handler(Scsi_Cmnd * scp);
-
-
-/**
- *      eh_device_reset_handler - issue scsi device reset
- *      @scp: identifies scsi device to be reset
- *
- *      Returns SUCCESS if command aborted else FAILED
- *
- *      Required: no
- *
- *      Locks: Scsi_Host::host_lock held (with irqsave) on entry and assumed
- *      to be held on return.
- *
- *      Notes: Invoked from scsi_eh thread. No other commands will be
- *      queued on current host during eh.
- **/
-     int eh_device_reset_handler(Scsi_Cmnd * scp);
-
-
-/**
- *      eh_bus_reset_handler - issue scsi bus reset
- *      @scp: scsi bus that contains this device should be reset
- *
- *      Returns SUCCESS if command aborted else FAILED
- *
- *      Required: no
- *
- *      Locks: Scsi_Host::host_lock held (with irqsave) on entry and assumed
- *      to be held on return.
- *
- *      Notes: Invoked from scsi_eh thread. No other commands will be
- *      queued on current host during eh.
- **/
-     int eh_bus_reset_handler(Scsi_Cmnd * scp);
-
-
-/**
- *      eh_host_reset_handler - reset host (host bus adapter)
- *      @scp: scsi host that contains this device should be reset
- *
- *      Returns SUCCESS if command aborted else FAILED
- *
- *      Required: no
- *
- *      Locks: Scsi_Host::host_lock held (with irqsave) on entry and assumed
- *      to be held on return.
- *
- *      Notes: Invoked from scsi_eh thread. No other commands will be
- *      queued on current host during eh. 
- *      With the default eh_strategy in place, if none of the _abort_, 
- *      _device_reset_, _bus_reset_ or this eh handler function are 
- *      defined (or they all return FAILED) then the device in question 
- *      will be set offline whenever eh is invoked.
- **/
-     int eh_host_reset_handler(Scsi_Cmnd * scp);
-
-
-/**
- *      eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
- *      @shp: host on which error has occurred
- *
- *      Returns TRUE if host unjammed, else FALSE.
- *
- *      Required: no
- *
- *      Locks: none
- *
- *      Notes: Invoked from scsi_eh thread. Driver supplied alternate to 
- *      scsi_unjam_host() found in scsi_error.c
- **/
-     int eh_strategy_handler(struct Scsi_Host * shp);
-
-
-/**
- *      info - supply information about given host: driver name plus data
- *             to distinguish given host
- *      @shp: host to supply information about
- *
- *      Return ASCII null terminated string. [This driver is assumed to
- *      manage the memory pointed to and maintain it, typically for the
- *      lifetime of this host.]
- *
- *      Required: no
- *
- *      Locks: none
- *
- *      Notes: Often supplies PCI or ISA information such as IO addresses
- *      and interrupt numbers. If not supplied Scsi_Host::name used
- *      instead. It is assumed the returned information fits on one line 
- *      (i.e. does not included embedded newlines).
- *      The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this
- *      function (or Scsi_Host::name if this function is not available).
- *      In a similar manner, scsi_register_host() outputs to the console
- *      each host's "info" (or name) for the driver it is registering.
- *      Also if proc_info() is not supplied, the output of this function
- *      is used instead.
- **/
-    const char * info(struct Scsi_Host * shp);
-
-
-/**
- *      ioctl - driver can respond to ioctls
- *      @sdp: device that ioctl was issued for
- *      @cmd: ioctl number
- *      @arg: pointer to read or write data from. Since it points to
- *            user space, should use appropriate kernel functions
- *            (e.g. copy_from_user() ). In the Unix style this argument
- *            can also be viewed as an unsigned long.
- *
- *      Returns negative "errno" value when there is a problem. 0 or a
- *      positive value indicates success and is returned to the user space.
- *
- *      Required: no
- *
- *      Locks: none
- *
- *      Notes: The scsi subsystem uses a "trickle down" ioctl model.
- *      The user issues an ioctl() against an upper level driver
- *      (e.g. /dev/sdc) and if the upper level driver doesn't recognize
- *      the 'cmd' then it is passed to the scsi mid level. If the scsi
- *      mid level does not recognize it, then the lower driver that controls
- *      the device receives the ioctl. According to recent Unix standards
- *      unsupported ioctl() 'cmd' numbers should return -ENOTTY.
- *      However the mid level returns -EINVAL for unrecognized 'cmd'
- *      numbers when this function is not supplied by the driver.
- *      Unfortunately some applications expect -EINVAL and react badly
- *	when -ENOTTY is returned; stick with -EINVAL.
- **/
-    int ioctl(Scsi_Device *sdp, int cmd, void *arg);
-
-
-/**
- *      proc_info - supports /proc/scsi/{driver_name}/{host_no}
- *      @buffer: anchor point to output to (0==writeto1_read0) or fetch from
- *               (1==writeto1_read0).
- *      @start: where "interesting" data is written to. Ignored when
- *              1==writeto1_read0.
- *      @offset: offset within buffer 0==writeto1_read0 is actually
- *               interested in. Ignored when 1==writeto1_read0 .
- *      @length: maximum (or actual) extent of buffer
- *      @host_no: host number of interest (Scsi_Host::host_no)
- *      @writeto1_read0: 1 -> data coming from user space towards driver
- *                            (e.g. "echo some_string > /proc/scsi/xyz/2")
- *                       0 -> user what data from this driver
- *                            (e.g. "cat /proc/scsi/xyz/2")
- *
- *      Returns length when 1==writeto1_read0. Otherwise number of chars
- *      output to buffer past offset.
- *
- *      Required: no
- *
- *      Locks: none held
- *
- *      Notes: Driven from scsi_proc.c which interfaces to proc_fs
- **/
-int proc_info(char * buffer, char ** start, off_t offset, 
-              int length, int hostno, int writeto1_read0);
-
-
-/**
- *      queuecommand - queue scsi command, invoke 'done' on completion
- *      @scp: pointer to scsi command object
- *      @done: function pointer to be invoked on completion
- *
- *      Returns 1 if the adapter (host) is busy, else returns 0. One
- *		reason for an adapter to be busy is that the number
- *		of outstanding queued commands is already equal to
- *		Scsi_Host::can_queue .
- *
- *      Required: if Scsi_Host::can_queue is ever non-zero
- *                then this function is required.
- *
- *      Locks: Scsi_Host::host_lock held on entry (with "irqsave") and
- *             is expected to be held on return.
- *
- *      Notes: This function should be relatively fast. Normally it will
- *      not wait for IO to complete. Hence the 'done' callback is invoked 
- *      (often directly from an interrupt service routine) sometime after
- *      this command has returned. In some cases (e.g. pseudo adapter 
- *      drivers that manufacture the response to a scsi INQUIRY)
- *      the 'done' callback may be invoked before this function returns.
- *      If the 'done' callback is not invoked within a certain period
- *      the scsi mid level will commence error processing.
- *      The integer with 4 component bytes that command() uses as its
- *      return value should be generated by this function. However, in
- *      this case, it should be placed in scp->result before this function 
- *      returns.
- *      If a status of CHECK CONDITION is placed in "result" when the
- *	'done' callback is invoked, then the lower level driver should 
- *	perform autosense and fill in the Scsi_Cmnd::sense_buffer array.
- **/
-    int queuecommand(Scsi_Cmnd * scp, void (*done)(Scsi_Cmnd *));
-
-
-/**
- *      release - release all resources associated with given host
- *      @shp: host to be released.
- *
- *      Return value ignored.
- *
- *      Required: no
- *
- *      Locks: lock_kernel() active on entry and expected to be active
- *      on return.
- *
- *      Notes: Invoked from mid level's scsi_unregister_host().
- *      This function should call scsi_unregister(shp) [found in hosts.c]
- *      prior to returning.
- **/
-    int release(struct Scsi_Host * shp);
-
-/**
- *      select_queue_depths - calculate allowable number of scsi commands
- *                            that can be queued on each device (disk)
- *                            on the given host
- *      @shp: host containing device
- *      @sdp: first device to examine [start of list]
- *
- *      Returns nothing
- *
- *      Required: no
- *
- *      Locks: none
- *
- *      Notes: This function should examine all devices on the given host.
- *      The next device can be fetched with sdp->next (NULL when finished).
- *      Queue depths should be placed in Scsi_Device::queue_depth . 
- **/
-    void select_queue_depths(struct Scsi_Host * shp, Scsi_Device * sdp);
-
-
-Data Structures
-===============
-Scsi_Host_Template
-------------------
-There is one Scsi_Host_Template instance per lower level driver. It is
-typically initialized as a file scope static in a driver's header file. That
-way members that are not explicitly initialized will be set to 0 or NULL.
-Member of interest:
-    name         - name of driver (should only use characters that are
-                   permitted in a unix file name)
-    proc_name    - name used in "/proc/scsi/<proc_name>/<host_no>"
-The structure is defined and commented in hosts.h
-
-Scsi_Host
----------
-There is one Scsi_Host instance per host (HBA) that a lower level driver
-controls. The Scsi_Host structure has many members in common with the
-Scsi_Host_Template. When a new Scsi_Host instance is created (in
-scsi_register() in hosts.c) those common members are initialized from
-the driver's Scsi_Host_Template instance. Members of interest:
-    host_no      - system wide unique number that is used for identifying
-                   this host. Issued in ascending order from 0 (and the
-                   positioning can be influenced by the scsihosts
-                   kernel boot (or module) parameter)
-    can_queue    - 0->use command(), greater than 0->use queuecommand() and do
-                   not send more than can_queue commands to the adapter.
-    this_id      - scsi id of host (scsi initiator) or -1 if not known
-    sg_tablesize - maximum scatter gather elements allowed by host.
-                   0 implies scatter gather not supported by host
-    max_sectors  - maximum number of sectors (usually 512 bytes) allowed
-                   in a single scsi command. 0 implies no maximum.
-    cmd_per_lun  - maximum number of command that can be queued on devices
-                   controlled by the host. Used if select_queue_depths()
-                   not defined or yields 0.
-    unchecked_isa_dma - 1->only use bottom 16 MB of ram (ISA DMA addressing
-                   restriction), 0->can use full 32 bit (or better) DMA
-                   address space
-    use_clustering - 1->scsi commands in mid level's queue can be merged,
-                     0->disallow scsi command merging
-    highmem_io   - 1->can DMA in to or out of high memory,
-                   0->use bounce buffers if data is in high memory
-    hostt        - pointer to driver's Scsi_Host_Template from which this
-                   Scsi_Host instance was spawned
-    host_queue   - deceptively named pointer to the start of a double linked
-                   list of Scsi_Device instances that belong to this host.
-The structure is defined in hosts.h
-
-Scsi_Device
------------
-Generally, there is one instance of this structure for each scsi logical unit
-on a host. Scsi devices are uniquely identified within a host by bus number,
-target id and logical unit number (lun).
-The structure is defined in scsi.h
-
-Scsi_Cmnd
----------
-Instances of this structure convey scsi commands to the lower level
-driver. Each scsi device has a pool of Scsi_Cmnd instances whose size
-is determined by select_queue_depths (or Scsi_Host::cmd_per_lun). There
-will be at least one instance of Scsi_Cmnd for each scsi device.
-The structure is defined in scsi.h
-
-
-Flow of control during initialization
-=====================================
-
-Lower level driver                        mid level
-------------------                        ---------
-
-init_this_scsi_driver() [1]              -----+
-  <scsi_modules.c>                            |
-                                              v
-                                         scsi_register_host()
-                                              |
-detect() [2]                               <--+
-                                              |
-queuecommand()** [3]                       <--+
-                                              |
-select_queue_depths()*                     <--+
-
-
-Notes
------
-[1] invoked during kernel initialization when built in or during module
-    initialization. The scsi mid level will already be initialized.
-[2] detect() calls scsi_register() for each HBA it wants to control
-    (if not, scsi_register_host() will do it instead)
-[3] called as part of scsi bus scan during discovery of devices. This scan
-    will be done for each host. Scsi commands such as INQUIRY, MODE SENSE
-    and REPORT LUNS will be sent during device discovery
-*   invoked for each host controlled by the lower level driver
-**  invoked for each device of each host controlled by the driver
-
-
-Locks
-=====
-Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
-which is initialized in scsi_register() [found in hosts.c]. Within the
-same function the Scsi_Host::host_lock pointer is initialized to point
-at default_lock with the scsi_assign_lock() function. Thereafter 
-lock and unlock operations performed by the mid level use the
-Scsi_Host::host_lock pointer.
-
-Lower level drivers can override the use of Scsi_Host::default_lock by
-using scsi_assign_lock(). The earliest opportunity to do this would
-be in the detect() function after it has invoked scsi_register(). It
-could be replaced by a coarser grain lock (e.g. per driver) or a
-lock of equal granularity (i.e. per host). Using finer grain locks 
-(e.g. per scsi device) may be possible by juggling locks in
-queuecommand().
-
-Autosense
-=========
-Autosense (or auto-sense) is defined in the SAM-2 document as "the
-automatic return of sense data to the application client coincident
-with the completion of a SCSI command" when a status of CHECK CONDITION
-occurs. Lower level drivers should perform autosense. This should be
-done when the lower level driver detects a CHECK CONDITION status by either: 
-    a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI))
-       to perform an extra data in phase on such responses
-    b) or, the lower level driver issuing a REQUEST SENSE command itself
-
-Either way, the mid level decides whether the lower level driver has 
-performed autosense by checking Scsi_Cmnd::sense_buffer[0] . If this
-byte has an upper nibble of 7 then autosense is assumed to have taken 
-place. If it has another value (and this byte is initialized to 0 before
-each command) then the mid level will issue a REQUEST SENSE command.
-
-In the presence of queued commands the "nexus" that maintains sense
-buffer data from the command that failed until a following REQUEST SENSE
-may get out of synchronization. This is why it is best for the lower
-level driver to perform autosense.
-
-
-Changes since lk 2.4 series
-===========================
-io_request_lock has been replaced by several finer grained locks. The lock 
-relevant to lower level drivers is Scsi_Host::host_lock and there is one 
-per scsi host.
-
-The older error handling mechanism has been removed. This means the
-lower level interface functions abort() and reset() have been removed.
-The Scsi_Host_Template::use_new_eh_code flag has been removed.
-
-In the 2.4 series the scsi subsystem configuration descriptions were 
-aggregated with the configuration descriptions from all other Linux 
-subsystems in the Documentation/Configure.help file. In the 2.5 series, 
-the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
-file.
-
-
-Credits
-=======
-The following people have contributed to this document:
-        Mike Anderson <andmike@us.ibm.com>
-        James Bottomley <James.Bottomley@steeleye.com> 
-        Patrick Mansfield <patmans@us.ibm.com> 
-
-
-Douglas Gilbert
-dgilbert@interlog.com
-13th August 2002
diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
--- a/drivers/scsi/scsi_proc.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/scsi/scsi_proc.c	Sun Nov 17 20:30:02 2002
@@ -16,9 +16,8 @@
  * Michael A. Griffith <grif@acm.org>
  */
 
-#include <linux/config.h>	/* for CONFIG_PROC_FS */
+#include <linux/config.h>
 #include <linux/module.h>
-
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -26,245 +25,133 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/blk.h>
-
 #include <asm/uaccess.h>
 
 #include "scsi.h"
 #include "hosts.h"
 
-#ifndef TRUE
-#define TRUE  1
-#define FALSE 0
-#endif
+/* 4K page size, but our output routines, use some slack for overruns */
+#define PROC_BLOCK_SIZE (3*1024)
 
-#ifdef CONFIG_PROC_FS
+/* XXX: this shouldn't really be exposed to drivers. */
+struct proc_dir_entry *proc_scsi;
+EXPORT_SYMBOL(proc_scsi);
 
-/* generic_proc_info
- * Used if the driver currently has no own support for /proc/scsi
- */
-int generic_proc_info(char *buffer, char **start, off_t offset, int length, 
-		      const char *(*info) (struct Scsi_Host *),
-		      struct Scsi_Host *sh)
-{
-	int len, pos, begin;
-
-	begin = 0;
-	if (info && sh) {
-		pos = len = sprintf(buffer, "%s\n", info(sh));
-	} else {
-		pos = len = sprintf(buffer,
-			"The driver does not yet support the proc-fs\n");
-	}
+
+/* Used if the driver currently has no own support for /proc/scsi */
+static int generic_proc_info(char *buffer, char **start, off_t offset,
+			     int count, const char *(*info)(struct Scsi_Host *),
+			     struct Scsi_Host *shost)
+{
+	int len, pos, begin = 0;
+	static const char noprocfs[] =
+		"The driver does not yet support the proc-fs\n";
+
+	if (info && shost)
+		len = sprintf(buffer, "%s\n", info(shost));
+	else
+		len = sprintf(buffer, "%s\n", noprocfs);
+
+	pos = len;
 	if (pos < offset) {
 		len = 0;
 		begin = pos;
 	}
-	*start = buffer + (offset - begin);	/* Start of wanted data */
+
+	*start = buffer + (offset - begin);
 	len -= (offset - begin);
-	if (len > length)
-		len = length;
+	if (len > count)
+		len = count;
 
-	return (len);
+	return len;
 }
 
-/* dispatch_scsi_info is the central dispatcher 
- * It is the interface between the proc-fs and the SCSI subsystem code
- */
 static int proc_scsi_read(char *buffer, char **start, off_t offset,
-	int length, int *eof, void *data)
+			  int length, int *eof, void *data)
 {
-	struct Scsi_Host *hpnt = data;
+	struct Scsi_Host *shost = data;
 	int n;
 
-	if (hpnt->hostt->proc_info == NULL)
+	if (shost->hostt->proc_info == NULL)
 		n = generic_proc_info(buffer, start, offset, length,
-				      hpnt->hostt->info, hpnt);
+				      shost->hostt->info, shost);
 	else
-		n = (hpnt->hostt->proc_info(buffer, start, offset,
-					   length, hpnt->host_no, 0));
-	*eof = (n<length);
+		n = (shost->hostt->proc_info(buffer, start, offset,
+					   length, shost->host_no, 0));
+
+	*eof = (n < length);
 	return n;
 }
 
-#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
-				      * use some slack for overruns 
-				      */
-
-static int proc_scsi_write(struct file * file, const char * buf,
+static int proc_scsi_write(struct file *file, const char *buf,
                            unsigned long count, void *data)
 {
-	struct Scsi_Host *hpnt = data;
-	ssize_t ret = 0;
-	char * page;
+	struct Scsi_Host *shost = data;
+	ssize_t ret = -ENOMEM;
+	char *page;
 	char *start;
     
-	if (hpnt->hostt->proc_info == NULL)
-		ret = -ENOSYS;
-
+	if (!shost->hostt->proc_info)
+		return -ENOSYS;
 	if (count > PROC_BLOCK_SIZE)
 		return -EOVERFLOW;
 
-	if (!(page = (char *) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	if(copy_from_user(page, buf, count))
-	{
-		free_page((ulong) page);
-		return -EFAULT;
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (page) {
+		ret = -EFAULT;
+		if (copy_from_user(page, buf, count))
+			goto out;
+		ret = shost->hostt->proc_info(page, &start, 0, count,
+					      shost->host_no, 1);
 	}
-
-	ret = hpnt->hostt->proc_info(page, &start, 0, count,
-				     hpnt->host_no, 1);
-
-	free_page((ulong) page);
-	return(ret);
-}
-
-void scsi_proc_host_mkdir(Scsi_Host_Template *shost_tp)
-{
-	shost_tp->proc_dir = proc_mkdir(shost_tp->proc_name, proc_scsi);
-        if (!shost_tp->proc_dir) {
-		printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
-		       __FUNCTION__, shost_tp->proc_name);
-                return;
-        }
-	shost_tp->proc_dir->owner = shost_tp->module;
+out:
+	free_page((unsigned long)page);
+	return ret;
 }
 
 void scsi_proc_host_add(struct Scsi_Host *shost)
 {
-	char name[10];
+	Scsi_Host_Template *sht = shost->hostt;
 	struct proc_dir_entry *p;
+	char name[10];
 
-	sprintf(name,"%d",shost->host_no);
-	p = create_proc_read_entry(name,
-			S_IFREG | S_IRUGO | S_IWUSR,
-			shost->hostt->proc_dir,
-			proc_scsi_read,
-			(void *)shost);
+	if (!sht->proc_dir) {
+		sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
+        	if (!sht->proc_dir) {
+			printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
+			       __FUNCTION__, sht->proc_name);
+			return;
+		}
+		sht->proc_dir->owner = sht->module;
+	}
+
+	sprintf(name,"%d", shost->host_no);
+	p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+			shost->hostt->proc_dir, proc_scsi_read, shost);
 	if (!p) {
 		printk(KERN_ERR "%s: Failed to register host %d in"
 		       "%s\n", __FUNCTION__, shost->host_no,
 		       shost->hostt->proc_name);
-	} else {
-		p->write_proc=proc_scsi_write;
-		p->owner = shost->hostt->module;
-	}
+		return;
+	} 
+
+	p->write_proc = proc_scsi_write;
+	p->owner = shost->hostt->module;
 
 }
 
 void scsi_proc_host_rm(struct Scsi_Host *shost)
 {
 	char name[10];
-	sprintf(name,"%d",shost->host_no);
-	remove_proc_entry(name, shost->hostt->proc_dir);
-}
 
-/*
- *  parseHandle *parseInit(char *buf, char *cmdList, int cmdNum); 
- *              gets a pointer to a null terminated data buffer
- *              and a list of commands with blanks as delimiter 
- *      in between. 
- *      The commands have to be alphanumerically sorted. 
- *      cmdNum has to contain the number of commands.
- *              On success, a pointer to a handle structure
- *              is returned, NULL on failure
- *
- *      int parseOpt(parseHandle *handle, char **param);
- *              processes the next parameter. On success, the
- *              index of the appropriate command in the cmdList
- *              is returned, starting with zero.
- *              param points to the null terminated parameter string.
- *              On failure, -1 is returned.
- *
- *      The databuffer buf may only contain pairs of commands
- *          options, separated by blanks:
- *              <Command> <Parameter> [<Command> <Parameter>]*
- */
-
-typedef struct {
-	char *buf,		/* command buffer  */
-	*cmdList,		/* command list    */
-	*bufPos,		/* actual position */
-	**cmdPos,		/* cmdList index   */
-	 cmdNum;		/* cmd number      */
-} parseHandle;
-
-inline int parseFree(parseHandle * handle)
-{				/* free memory     */
-	kfree(handle->cmdPos);
-	kfree(handle);
-
-	return -1;
-}
-
-parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
-{
-	char *ptr;		/* temp pointer    */
-	parseHandle *handle;	/* new handle      */
-
-	if (!buf || !cmdList)	/* bad input ?     */
-		return NULL;
-	handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);
-	if (!handle)
-		return NULL;	/* out of memory   */
-	handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);
-	if (!handle->cmdPos) {
-		kfree(handle);
-		return NULL;	/* out of memory   */
-	}
-	handle->buf = handle->bufPos = buf;	/* init handle     */
-	handle->cmdList = cmdList;
-	handle->cmdNum = cmdNum;
-
-	handle->cmdPos[cmdNum = 0] = cmdList;
-	for (ptr = cmdList; *ptr; ptr++) {	/* scan command string */
-		if (*ptr == ' ') {	/* and insert zeroes   */
-			*ptr++ = 0;
-			handle->cmdPos[++cmdNum] = ptr++;
-		}
-	}
-	return handle;
-}
-
-int parseOpt(parseHandle * handle, char **param)
-{
-	int cmdIndex = 0, cmdLen = 0;
-	char *startPos;
-
-	if (!handle)		/* invalid handle  */
-		return (parseFree(handle));
-	/* skip spaces     */
-	for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
-	if (!*(handle->bufPos))
-		return (parseFree(handle));	/* end of data     */
-
-	startPos = handle->bufPos;	/* store cmd start */
-	for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++) {	/* no string end?  */
-		for (;;) {
-			if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen])
-				break;	/* char matches ?  */
-			else if (memcmp(startPos, (char *) (handle->cmdPos[++cmdIndex]), cmdLen))
-				return (parseFree(handle));	/* unknown command */
-
-			if (cmdIndex >= handle->cmdNum)
-				return (parseFree(handle));	/* unknown command */
-		}
-
-		cmdLen++;	/* next char       */
-	}
-
-	/* Get param. First skip all blanks, then insert zero after param  */
-
-	for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
-	*param = handle->bufPos;
-
-	for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++);
-	*(handle->bufPos++) = 0;
-
-	return (cmdIndex);
+	sprintf(name,"%d", shost->host_no);
+	remove_proc_entry(name, shost->hostt->proc_dir);
+	if (!shost->hostt->present)
+		remove_proc_entry(shost->hostt->proc_name, proc_scsi);
 }
 
-void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
+/* XXX: this shouldn't really be exposed to drivers. */
+void proc_print_scsidevice(Scsi_Device * sdev, char *buffer, int *size, int len)
 {
 
 	int x, y = *size;
@@ -272,35 +159,36 @@
 
 	y = sprintf(buffer + len,
 	     "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
-		    scd->host->host_no, scd->channel, scd->id, scd->lun);
+		    sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 	for (x = 0; x < 8; x++) {
-		if (scd->vendor[x] >= 0x20)
-			y += sprintf(buffer + len + y, "%c", scd->vendor[x]);
+		if (sdev->vendor[x] >= 0x20)
+			y += sprintf(buffer + len + y, "%c", sdev->vendor[x]);
 		else
 			y += sprintf(buffer + len + y, " ");
 	}
 	y += sprintf(buffer + len + y, " Model: ");
 	for (x = 0; x < 16; x++) {
-		if (scd->model[x] >= 0x20)
-			y += sprintf(buffer + len + y, "%c", scd->model[x]);
+		if (sdev->model[x] >= 0x20)
+			y += sprintf(buffer + len + y, "%c", sdev->model[x]);
 		else
 			y += sprintf(buffer + len + y, " ");
 	}
 	y += sprintf(buffer + len + y, " Rev: ");
 	for (x = 0; x < 4; x++) {
-		if (scd->rev[x] >= 0x20)
-			y += sprintf(buffer + len + y, "%c", scd->rev[x]);
+		if (sdev->rev[x] >= 0x20)
+			y += sprintf(buffer + len + y, "%c", sdev->rev[x]);
 		else
 			y += sprintf(buffer + len + y, " ");
 	}
 	y += sprintf(buffer + len + y, "\n");
 
 	y += sprintf(buffer + len + y, "  Type:   %s ",
-		     scd->type < MAX_SCSI_DEVICE_CODE ?
-	       scsi_device_types[(int) scd->type] : "Unknown          ");
+		     sdev->type < MAX_SCSI_DEVICE_CODE ?
+	       scsi_device_types[(int) sdev->type] : "Unknown          ");
 	y += sprintf(buffer + len + y, "               ANSI"
-		     " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1);
-	if (scd->scsi_level == 2)
+		     " SCSI revision: %02x", (sdev->scsi_level - 1) ?
+		     sdev->scsi_level - 1 : 1);
+	if (sdev->scsi_level == 2)
 		y += sprintf(buffer + len + y, " CCS\n");
 	else
 		y += sprintf(buffer + len + y, "\n");
@@ -308,30 +196,474 @@
 	*size = y;
 	return;
 }
+EXPORT_SYMBOL(proc_print_scsidevice);
 
-#else				/* if !CONFIG_PROC_FS */
+/* 
+ * proc_scsi_dev_info_read: dump the scsi_dev_info_list via
+ * /proc/scsi/device_info
+ */
+static int proc_scsi_dev_info_read(char *buffer, char **start, off_t offset,
+				   int length)
+{
+	struct scsi_dev_info_list *devinfo;
+	int size, len = 0;
+	off_t begin = 0;
+	off_t pos = 0;
+
+	list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) {
+		size = sprintf(buffer + len, "'%.8s' '%.16s' 0x%x\n",
+			       devinfo->vendor, devinfo->model, devinfo->flags);
+		len += size;
+		pos = begin + len;
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
+		}
+		if (pos > offset + length)
+			goto stop_output;
+	}
 
-void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
+stop_output:
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);	/* Start slop */
+	if (len > length)
+		len = length;	/* Ending slop */
+	return (len);
+}
+
+/* 
+ * proc_scsi_dev_info_write: allow additions to the scsi_dev_info_list via
+ * /proc.
+ *
+ * Use: echo "vendor:model:flag" > /proc/scsi/device_info
+ *
+ * To add a black/white list entry for vendor and model with an integer
+ * value of flag to the scsi device info list.
+ */
+static int proc_scsi_dev_info_write (struct file * file, const char * buf,
+                              unsigned long length, void *data)
 {
+	char *buffer;
+	int err = length;
+
+	if (!buf || length>PAGE_SIZE)
+		return -EINVAL;
+	if (!(buffer = (char *) __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	if (copy_from_user(buffer, buf, length)) {
+		err =-EFAULT;
+		goto out;
+	}
+
+	if (length < PAGE_SIZE)
+		buffer[length] = '\0';
+	else if (buffer[PAGE_SIZE-1]) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	scsi_dev_info_list_add_str(buffer);
+
+out:
+	free_page((unsigned long)buffer);
+	return err;
 }
 
-#endif				/* CONFIG_PROC_FS */
+static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
+{
+	struct Scsi_Host *shost;
+	Scsi_Device *sdev;
+	int size, len = 0;
+	off_t begin = 0;
+	off_t pos = 0;
+
+	/*
+	 * First, see if there are any attached devices or not.
+	 */
+	for (shost = scsi_host_get_next(NULL); shost;
+	     shost = scsi_host_get_next(shost)) {
+		if (shost->host_queue != NULL) {
+			break;
+		}
+	}
+	size = sprintf(buffer + len, "Attached devices: %s\n",
+			(shost) ? "" : "none");
+	len += size;
+	pos = begin + len;
+	for (shost = scsi_host_get_next(NULL); shost;
+	     shost = scsi_host_get_next(shost)) {
+		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+			proc_print_scsidevice(sdev, buffer, &size, len);
+			len += size;
+			pos = begin + len;
+
+			if (pos < offset) {
+				len = 0;
+				begin = pos;
+			}
+			if (pos > offset + length)
+				goto stop_output;
+		}
+	}
+
+stop_output:
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);	/* Start slop */
+	if (len > length)
+		len = length;	/* Ending slop */
+	return (len);
+}
 
+#ifdef CONFIG_SCSI_LOGGING
 /*
- * Overrides for Emacs so that we get a uniform tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
+ * Function:    scsi_dump_status
+ *
+ * Purpose:     Brain dump of scsi system, used for problem solving.
+ *
+ * Arguments:   level - used to indicate level of detail.
+ *
+ * Notes:       The level isn't used at all yet, but we need to find some
+ *		way of sensibly logging varying degrees of information.
+ *		A quick one-line display of each command, plus the status
+ *		would be most useful.
+ *
+ *              This does depend upon CONFIG_SCSI_LOGGING - I do want some
+ *		way of turning it all off if the user wants a lean and mean
+ *		kernel.  It would probably also be useful to allow the user
+ *		to specify one single host to be dumped.  A second argument
+ *		to the function would be useful for that purpose.
+ *
+ *              FIXME - some formatting of the output into tables would be
+ *		        very handy.
  */
+static void scsi_dump_status(int level)
+{
+	int i;
+	struct Scsi_Host *shpnt;
+	Scsi_Cmnd *SCpnt;
+	Scsi_Device *SDpnt;
+	printk(KERN_INFO "Dump of scsi host parameters:\n");
+	i = 0;
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
+		printk(KERN_INFO " %d %d %d : %d %d\n",
+		       shpnt->host_failed,
+		       shpnt->host_busy,
+		       atomic_read(&shpnt->host_active),
+		       shpnt->host_blocked,
+		       shpnt->host_self_blocked);
+	}
+
+	printk(KERN_INFO "\n\n");
+	printk(KERN_INFO "Dump of scsi command parameters:\n");
+	for (shpnt = scsi_host_get_next(NULL); shpnt;
+	     shpnt = scsi_host_get_next(shpnt)) {
+		printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) "
+			"(ret all flg) (to/cmd to ito) cmd snse result\n");
+		for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
+			for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
+				/*  (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x      */
+				printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
+				       i++,
+
+				       SCpnt->host->host_no,
+				       SCpnt->channel,
+                                       SCpnt->target,
+                                       SCpnt->lun,
+
+                                       SCpnt->request->rq_disk ?
+                                       SCpnt->request->rq_disk->disk_name : "?",
+                                       (unsigned long long)SCpnt->request->sector,
+				       SCpnt->request->nr_sectors,
+				       (long)SCpnt->request->current_nr_sectors,
+				       SCpnt->request->rq_status,
+				       SCpnt->use_sg,
+
+				       SCpnt->retries,
+				       SCpnt->allowed,
+				       SCpnt->flags,
+
+				       SCpnt->timeout_per_command,
+				       SCpnt->timeout,
+				       SCpnt->internal_timeout,
+
+				       SCpnt->cmnd[0],
+				       SCpnt->sense_buffer[2],
+				       SCpnt->result);
+			}
+		}
+	}
+}
+#endif	/* CONFIG_SCSI_LOGGING */ 
+
+static int proc_scsi_gen_write(struct file * file, const char * buf,
+                              unsigned long length, void *data)
+{
+	Scsi_Device *sdev;
+	struct Scsi_Host *shost;
+	char *p;
+	int host, channel, id, lun;
+	char * buffer;
+	int err;
+
+	if (!buf || length>PAGE_SIZE)
+		return -EINVAL;
+
+	buffer = (char *)__get_free_page(GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+	if (copy_from_user(buffer, buf, length)) {
+		err =-EFAULT;
+		goto out;
+	}
+
+	err = -EINVAL;
+
+	if (length < PAGE_SIZE)
+		buffer[length] = '\0';
+	else if (buffer[PAGE_SIZE-1])
+		goto out;
+
+	if (length < 11 || strncmp("scsi", buffer, 4))
+		goto out;
+
+#ifdef CONFIG_SCSI_LOGGING
+	/*
+	 * Usage: echo "scsi dump #N" > /proc/scsi/scsi
+	 * to dump status of all scsi commands.  The number is used to
+	 * specify the level of detail in the dump.
+	 */
+	if (!strncmp("dump", buffer + 5, 4)) {
+		unsigned int level;
+
+		p = buffer + 10;
+
+		if (*p == '\0')
+			goto out;
+
+		level = simple_strtoul(p, NULL, 0);
+		scsi_dump_status(level);
+	}
+	/*
+	 * Usage: echo "scsi log token #N" > /proc/scsi/scsi
+	 * where token is one of [error,scan,mlqueue,mlcomplete,llqueue,
+	 * llcomplete,hlqueue,hlcomplete]
+	 */
+	if (!strncmp("log", buffer + 5, 3)) {
+		char *token;
+		unsigned int level;
+
+		p = buffer + 9;
+		token = p;
+		while (*p != ' ' && *p != '\t' && *p != '\0') {
+			p++;
+		}
+
+		if (*p == '\0') {
+			if (strncmp(token, "all", 3) == 0) {
+				/*
+				 * Turn on absolutely everything.
+				 */
+				scsi_logging_level = ~0;
+			} else if (strncmp(token, "none", 4) == 0) {
+				/*
+				 * Turn off absolutely everything.
+				 */
+				scsi_logging_level = 0;
+			} else {
+				goto out;
+			}
+		} else {
+			*p++ = '\0';
+
+			level = simple_strtoul(p, NULL, 0);
+
+			/*
+			 * Now figure out what to do with it.
+			 */
+			if (strcmp(token, "error") == 0) {
+				SCSI_SET_ERROR_RECOVERY_LOGGING(level);
+			} else if (strcmp(token, "timeout") == 0) {
+				SCSI_SET_TIMEOUT_LOGGING(level);
+			} else if (strcmp(token, "scan") == 0) {
+				SCSI_SET_SCAN_BUS_LOGGING(level);
+			} else if (strcmp(token, "mlqueue") == 0) {
+				SCSI_SET_MLQUEUE_LOGGING(level);
+			} else if (strcmp(token, "mlcomplete") == 0) {
+				SCSI_SET_MLCOMPLETE_LOGGING(level);
+			} else if (strcmp(token, "llqueue") == 0) {
+				SCSI_SET_LLQUEUE_LOGGING(level);
+			} else if (strcmp(token, "llcomplete") == 0) {
+				SCSI_SET_LLCOMPLETE_LOGGING(level);
+			} else if (strcmp(token, "hlqueue") == 0) {
+				SCSI_SET_HLQUEUE_LOGGING(level);
+			} else if (strcmp(token, "hlcomplete") == 0) {
+				SCSI_SET_HLCOMPLETE_LOGGING(level);
+			} else if (strcmp(token, "ioctl") == 0) {
+				SCSI_SET_IOCTL_LOGGING(level);
+			} else {
+				goto out;
+			}
+		}
+
+		printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level);
+	}
+#endif	/* CONFIG_SCSI_LOGGING */
+
+	/*
+	 * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
+	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
+	 * Consider this feature BETA.
+	 *     CAUTION: This is not for hotplugging your peripherals. As
+	 *     SCSI was not designed for this you could damage your
+	 *     hardware !
+	 * However perhaps it is legal to switch on an
+	 * already connected device. It is perhaps not
+	 * guaranteed this device doesn't corrupt an ongoing data transfer.
+	 */
+	if (!strncmp("add-single-device", buffer + 5, 17)) {
+		p = buffer + 23;
+
+		host = simple_strtoul(p, &p, 0);
+		channel = simple_strtoul(p + 1, &p, 0);
+		id = simple_strtoul(p + 1, &p, 0);
+		lun = simple_strtoul(p + 1, &p, 0);
+
+		printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
+		       id, lun);
+
+		for (shost = scsi_host_get_next(NULL); shost;
+		     shost = scsi_host_get_next(shost)) {
+			if (shost->host_no == host) {
+				break;
+			}
+		}
+		err = -ENXIO;
+		if (!shost)
+			goto out;
+
+		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+			if ((sdev->channel == channel
+			     && sdev->id == id
+			     && sdev->lun == lun)) {
+				break;
+			}
+		}
+
+		err = -ENOSYS;
+		if (sdev)
+			goto out;	/* We do not yet support unplugging */
+
+		scan_scsis(shost, 1, channel, id, lun);
+		err = length;
+		goto out;
+	}
+	/*
+	 * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
+	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
+	 *
+	 * Consider this feature pre-BETA.
+	 *
+	 *     CAUTION: This is not for hotplugging your peripherals. As
+	 *     SCSI was not designed for this you could damage your
+	 *     hardware and thoroughly confuse the SCSI subsystem.
+	 *
+	 */
+	else if (!strncmp("remove-single-device", buffer + 5, 20)) {
+		p = buffer + 26;
+
+		host = simple_strtoul(p, &p, 0);
+		channel = simple_strtoul(p + 1, &p, 0);
+		id = simple_strtoul(p + 1, &p, 0);
+		lun = simple_strtoul(p + 1, &p, 0);
+
+
+		for (shost = scsi_host_get_next(NULL); shost;
+		     shost = scsi_host_get_next(shost)) {
+			if (shost->host_no == host) {
+				break;
+			}
+		}
+		err = -ENODEV;
+		if (!shost)
+			goto out;
+
+		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+			if ((sdev->channel == channel
+			     && sdev->id == id
+			     && sdev->lun == lun)) {
+				break;
+			}
+		}
+
+		if (sdev == NULL)
+			goto out;	/* there is no such device attached */
+
+		err = -EBUSY;
+		if (sdev->access_count)
+			goto out;
+
+		scsi_detach_device(sdev);
+
+		if (sdev->attached == 0) {
+			devfs_unregister (sdev->de);
+
+			/* Now we can remove the device structure */
+			if (sdev->next != NULL)
+				sdev->next->prev = sdev->prev;
+
+			if (sdev->prev != NULL)
+				sdev->prev->next = sdev->next;
+
+			if (shost->host_queue == sdev) {
+				shost->host_queue = sdev->next;
+			}
+			blk_cleanup_queue(&sdev->request_queue);
+			if (sdev->inquiry)
+				kfree(sdev->inquiry);
+			kfree((char *) sdev);
+		} else {
+			goto out;
+		}
+		err = 0;
+	}
+out:
+	
+	free_page((unsigned long)buffer);
+	return err;
+}
+
+int __init scsi_init_procfs(void)
+{
+	struct proc_dir_entry *pde;
+
+	proc_scsi = proc_mkdir("scsi", 0);
+	if (!proc_scsi)
+		goto err1;
+
+	pde = create_proc_info_entry("scsi/scsi", 0, 0, scsi_proc_info);
+	if (!pde)
+		goto err2;
+	pde->write_proc = proc_scsi_gen_write;
+
+	pde = create_proc_info_entry("scsi/device_info", 0, 0,
+					  proc_scsi_dev_info_read);
+	if (!pde)
+		goto err3;
+	pde->write_proc = proc_scsi_dev_info_write;
+	return 0;
+
+err3:
+	remove_proc_entry("scsi/scsi", 0);
+err2:
+	remove_proc_entry("scsi", 0);
+err1:
+	return -ENOMEM;
+}
+
+void __exit scsi_exit_procfs(void)
+{
+	remove_proc_entry("scsi/device_info", 0);
+	remove_proc_entry("scsi/scsi", 0);
+	remove_proc_entry("scsi", 0);
+}
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/scsi_scan.c	Sun Nov 17 20:30:15 2002
@@ -54,18 +54,16 @@
 #define BLIST_INQUIRY_36	0x400	/* override additional length field */
 #define BLIST_INQUIRY_58	0x800	/* ... for broken inquiry responses */
 
-struct dev_info {
-	const char *vendor;
-	const char *model;
-	const char *revision;	/* revision known to be bad, unused */
-	unsigned flags;
-};
-
 /*
- * device_list: devices that require settings that differ from the
- * default, includes black-listed (broken) devices.
+ * scsi_static_device_list: deprecated list of devices that require
+ * settings that differ from the default, includes black-listed (broken)
+ * devices. The entries here are added to the tail of scsi_dev_info_list
+ * via scsi_dev_info_list_init.
+ *
+ * Do not add to this list, use the command line or proc interface to add
+ * to the scsi_dev_info_list. This table will eventually go away.
  */
-static struct dev_info device_list[] = {
+struct dev_info scsi_static_device_list[] __initdata = {
 	/*
 	 * The following devices are known not to tolerate a lun != 0 scan
 	 * for one reason or another. Some will respond to all luns,
@@ -183,6 +181,7 @@
 	{"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN},
 	{"HP", "C1557A", NULL, BLIST_FORCELUN},
 	{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
+	{ NULL, NULL, NULL, 0 },
 };
 
 #define ALLOC_FAILURE_MSG	KERN_ERR "%s: Allocation failure during" \
@@ -427,62 +426,6 @@
 }
 
 /**
- * get_device_flags - get device specific flags from the device_list
- * @vendor:	vendor name
- * @model:	model name
- *
- * Description:
- *     Search device_list for an entry matching @vendor and @model, if
- *     found, return the matching flags value, else return 0.
- *     Partial matches count as success - good for @model, but maybe not
- *     @vendor.
- **/
-static int get_device_flags(unsigned char *vendor, unsigned char *model)
-{
-	int i;
-	size_t max;
-
-	for (i = 0; i < ARRAY_SIZE(device_list); i++) {
-		/*
-		 * XXX why skip leading spaces? If an odd INQUIRY value,
-		 * that should have been part of the device_list[] entry,
-		 * such as "  FOO" rather than "FOO". Since this code is
-		 * already here, and we don't know what device it is
-		 * trying to work with, leave it as-is.
-		 */
-		max = 8;	/* max length of vendor */
-		while ((max > 0) && *vendor == ' ') {
-			max--;
-			vendor++;
-		}
-		/*
-		 * XXX removing the following strlen() would be good,
-		 * using it means that for a an entry not in the list, we
-		 * scan every byte of every vendor listed in
-		 * device_list[], and never match a single one (and still
-		 * have to compare at least the first byte of each
-		 * vendor).
-		 */
-		if (memcmp(device_list[i].vendor, vendor,
-			    min(max, strlen(device_list[i].vendor))))
-			continue;
-		/*
-		 * Skip spaces again.
-		 */
-		max = 16;	/* max length of model */
-		while ((max > 0) && *model == ' ') {
-			max--;
-			model++;
-		}
-		if (memcmp(device_list[i].model, model,
-			   min(max, strlen(device_list[i].model))))
-			continue;
-		return device_list[i].flags;
-	}
-	return 0;
-}
-
-/**
  * scsi_initialize_merge_fn() -Æ£initialize merge function for a host
  * @sd:		host descriptor
  */
@@ -1092,12 +1035,12 @@
  * Notes:
  *     If a device returns the same serial number for different LUNs or
  *     even for different LUNs on different devices, special handling must
- *     be added to get an id, or a new black list flag must to added and
- *     used in device_list[] (so we use the default name, or add a way to
- *     prefix the id/name with SCSI_UID_UNKNOWN - and change the define to
- *     something meaningful like SCSI_UID_NOT_UNIQUE). Complete user level
- *     scanning would be nice for such devices, so we do not need device
- *     specific code in the kernel.
+ *     be added to get an id, or a new black list flag must be added (so
+ *     we use the default name, or add a way to prefix the id/name with
+ *     SCSI_UID_UNKNOWN - and change the define to something meaningful
+ *     like SCSI_UID_NOT_UNIQUE). Complete user level scanning would be
+ *     nice for such devices, so we do not need device specific code in
+ *     the kernel.
  **/
 static void scsi_load_identifier(Scsi_Device *sdev, Scsi_Request *sreq)
 {
@@ -1176,7 +1119,7 @@
  *     If the INQUIRY is successful, sreq->sr_result is zero and: the
  *     INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
  *     are copied to the Scsi_Device at @sreq->sr_device (sdev);
- *     any device_list flags value is stored in *@bflags.
+ *     any flags value is stored in *@bflags.
  **/
 static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
 			   int *bflags)
@@ -1225,7 +1168,7 @@
 	 * argument.
 	 */
 	BUG_ON(bflags == NULL);
-	*bflags = get_device_flags(&inq_result[8], &inq_result[16]);
+	*bflags = scsi_get_device_flags(&inq_result[8], &inq_result[16]);
 
 	possible_inq_resp_len = (unsigned char) inq_result[4] + 5;
 	if (BLIST_INQUIRY_36 & *bflags)
@@ -1306,7 +1249,7 @@
  * @sdevnew:	store the address of the newly allocated Scsi_Device
  * @sreq:	scsi request used when getting an identifier
  * @inq_result:	holds the result of a previous INQUIRY to the LUN
- * @bflags:	flags value from device_list
+ * @bflags:	black/white list flag
  *
  * Description:
  *     Allocate and initialize a Scsi_Device matching sdevscan. Optionally
@@ -1323,7 +1266,6 @@
 {
 	Scsi_Device *sdev;
 	char devname[64];
-	extern devfs_handle_t scsi_devfs_handle;
 
 	sdev = scsi_alloc_sdev(sdevscan->host, sdevscan->channel,
 				     sdevscan->id, sdevscan->lun);
@@ -1445,13 +1387,13 @@
 	 */
 	device_create_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
 
-	sprintf(devname, "host%d/bus%d/target%d/lun%d",
+	sprintf(devname, "scsi/host%d/bus%d/target%d/lun%d",
 		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 	if (sdev->de)
 		printk(KERN_WARNING "scsi devfs dir: \"%s\" already exists\n",
 		       devname);
 	else
-		sdev->de = devfs_mk_dir(scsi_devfs_handle, devname, NULL);
+		sdev->de = devfs_mk_dir(NULL, devname, NULL);
 	/*
 	 * End driverfs/devfs code.
 	 */
@@ -1478,8 +1420,6 @@
 	 * function */
 	sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
 
-	scsi_detect_device(sdev);
-
 	if (sdevnew != NULL)
 		*sdevnew = sdev;
 
@@ -1608,7 +1548,7 @@
 /**
  * scsi_sequential_lun_scan - sequentially scan a SCSI target
  * @sdevscan:	scan the host, channel, and id of this Scsi_Device
- * @bflags:	flags from device_list for LUN 0
+ * @bflags:	black/white list flag for LUN 0
  * @lun0_res:	result of scanning LUN 0
  *
  * Description:
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/scsi_syms.c	Sun Nov 17 20:30:14 2002
@@ -74,9 +74,6 @@
 
 EXPORT_SYMBOL(scsi_sleep);
 
-EXPORT_SYMBOL(proc_print_scsidevice);
-EXPORT_SYMBOL(proc_scsi);
-
 EXPORT_SYMBOL(scsi_io_completion);
 EXPORT_SYMBOL(scsi_end_request);
 
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/scsi/sd.c	Sun Nov 17 20:30:15 2002
@@ -94,7 +94,6 @@
 static void sd_rw_intr(struct scsi_cmnd * SCpnt);
 
 static int sd_attach(struct scsi_device *);
-static int sd_detect(struct scsi_device *);
 static void sd_detach(struct scsi_device *);
 static int sd_init_command(struct scsi_cmnd *);
 static int sd_synchronize_cache(struct scsi_disk *, int);
@@ -104,10 +103,10 @@
 
 static struct Scsi_Device_Template sd_template = {
 	.module		= THIS_MODULE,
+	.list		= LIST_HEAD_INIT(sd_template.list),
 	.name		= "disk",
 	.tag		= "sd",
 	.scsi_type	= TYPE_DISK,
-	.detect		= sd_detect,
 	.attach		= sd_attach,
 	.detach		= sd_detach,
 	.init_command	= sd_init_command,
@@ -453,10 +452,8 @@
 	 * The following code can sleep.
 	 * Module unloading must be prevented
 	 */
-	if (sdp->host->hostt->module)
-		__MOD_INC_USE_COUNT(sdp->host->hostt->module);
-	if (sd_template.module)
-		__MOD_INC_USE_COUNT(sd_template.module);
+	if(!try_module_get(sdp->host->hostt->module))
+		return -ENOMEM;
 	sdp->access_count++;
 
 	if (sdp->removable) {
@@ -498,10 +495,7 @@
 
 error_out:
 	sdp->access_count--;
-	if (sdp->host->hostt->module)
-		__MOD_DEC_USE_COUNT(sdp->host->hostt->module);
-	if (sd_template.module)
-		__MOD_DEC_USE_COUNT(sd_template.module);
+	module_put(sdp->host->hostt->module);
 	return retval;	
 }
 
@@ -536,10 +530,7 @@
 			if (scsi_block_when_processing_errors(sdp))
 				scsi_set_medium_removal(sdp, SCSI_REMOVAL_ALLOW);
 	}
-	if (sdp->host->hostt->module)
-		__MOD_DEC_USE_COUNT(sdp->host->hostt->module);
-	if (sd_template.module)
-		__MOD_DEC_USE_COUNT(sd_template.module);
+	module_put(sdp->host->hostt->module);
 
 	return 0;
 }
@@ -758,7 +749,6 @@
 sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
 	       struct scsi_request *SRpnt, unsigned char *buffer) {
 	unsigned char cmd[10];
-	struct scsi_device *sdp = sdkp->device;
 	unsigned long spintime_value = 0;
 	int the_result, retries, spintime;
 
@@ -1166,23 +1156,6 @@
 }
 
 /**
- *	sd_detect - called at the start of driver initialization, once 
- *	for each scsi device (not just disks) present.
- *
- *	Returns 0 if not interested in this scsi device (e.g. scanner);
- *	1 if this device is of interest (e.g. a disk).
- *
- *	Note: this function is invoked from the scsi mid-level.
- **/
-static int sd_detect(struct scsi_device * sdp)
-{
-	SCSI_LOG_HLQUEUE(3, printk("sd_detect: type=%d\n", sdp->type));
-	if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD)
-		return 0;
-	return 1;
-}
-
-/**
  *	sd_attach - called during driver initialization and whenever a
  *	new scsi device is attached to the system. It is called once
  *	for each scsi device (not just disks) present.
@@ -1236,16 +1209,18 @@
 	sdkp->driver = &sd_template;
 	sdkp->disk = gd;
 
-	sd_init_onedisk(sdkp, gd);
-
 	gd->de = sdp->de;
 	gd->major = SD_MAJOR(dsk_nr>>4);
 	gd->first_minor = (dsk_nr & 15)<<4;
+	gd->minors = 16;
 	gd->fops = &sd_fops;
 	if (dsk_nr > 26)
 		sprintf(gd->disk_name, "sd%c%c",'a'+dsk_nr/26-1,'a'+dsk_nr%26);
 	else
 		sprintf(gd->disk_name, "sd%c",'a'+dsk_nr%26);
+
+	sd_init_onedisk(sdkp, gd);
+
 	gd->driverfs_dev = &sdp->sdev_driverfs_dev;
 	gd->flags = GENHD_FL_DRIVERFS | GENHD_FL_DEVFS;
 	if (sdp->removable)
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/sg.c	Sun Nov 17 20:30:14 2002
@@ -111,7 +111,6 @@
 #define SG_DEV_ARR_LUMP 6	/* amount to over allocate sg_dev_arr by */
 
 static int sg_attach(Scsi_Device *);
-static int sg_detect(Scsi_Device *);
 static void sg_detach(Scsi_Device *);
 
 static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
@@ -121,10 +120,10 @@
 
 static struct Scsi_Device_Template sg_template = {
 	.module = THIS_MODULE,
+	.list = LIST_HEAD_INIT(sg_template.list),
 	.name = "generic",
 	.tag = "sg",
 	.scsi_type = 0xff,
-	.detect = sg_detect,
 	.attach = sg_attach,
 	.detach = sg_detach
 };
@@ -233,7 +232,6 @@
 #endif
 
 static Sg_device **sg_dev_arr = NULL;
-static int sg_dev_noticed;
 static int sg_dev_max;
 static int sg_nr_dev;
 
@@ -261,8 +259,8 @@
 
 	/* This driver's module count bumped by fops_get in <linux/fs.h> */
 	/* Prevent the device driver from vanishing while we sleep */
-	if (sdp->device->host->hostt->module)
-		__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
+	if (!try_module_get(sdp->device->host->hostt->module))
+		return -ENXIO;
 	sdp->device->access_count++;
 
 	if (!((flags & O_NONBLOCK) ||
@@ -317,8 +315,7 @@
 
       error_out:
 	sdp->device->access_count--;
-	if ((!sdp->detached) && sdp->device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
+	module_put(sdp->device->host->hostt->module);
 	return retval;
 }
 
@@ -336,9 +333,7 @@
 	if (0 == sg_remove_sfp(sdp, sfp)) {	/* Returns 1 when sdp gone */
 		if (!sdp->detached) {
 			sdp->device->access_count--;
-			if (sdp->device->host->hostt->module)
-				__MOD_DEC_USE_COUNT(sdp->device->host->hostt->
-						    module);
+			module_put(sdp->device->host->hostt->module);
 		}
 		sdp->exclude = 0;
 		wake_up_interruptible(&sdp->o_excl_wait);
@@ -1304,11 +1299,8 @@
 			SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n"));
 			if (0 == sg_remove_sfp(sdp, sfp)) {	/* device still present */
 				sdp->device->access_count--;
-				if (sdp->device->host->hostt->module)
-					__MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
+				module_put(sdp->device->host->hostt->module);
 			}
-			if (sg_template.module)
-				__MOD_DEC_USE_COUNT(sg_template.module);
 			sfp = NULL;
 		}
 	} else if (srp && srp->orphan) {
@@ -1338,13 +1330,6 @@
 	.fasync = sg_fasync,
 };
 
-static int
-sg_detect(Scsi_Device * scsidp)
-{
-	sg_dev_noticed++;
-	return 1;
-}
-
 #ifndef MODULE
 static int __init
 sg_def_reserved_size_setup(char *str)
@@ -1539,12 +1524,7 @@
 				}
 				if (sfp->closed) {
 					sdp->device->access_count--;
-					if (sg_template.module)
-						__MOD_DEC_USE_COUNT(sg_template.module);
-					if (sdp->device->host->hostt->module)
-						__MOD_DEC_USE_COUNT(
-							sdp->device->host->
-							 hostt->module);
+					module_put(sdp->device->host->hostt->module);
 					__sg_remove_sfp(sdp, sfp);
 				} else {
 					delay = 1;
@@ -1563,7 +1543,6 @@
 		}
 		scsi_slave_detach(scsidp);
 		sg_nr_dev--;
-		sg_dev_noticed--;	/* from <dan@lectra.fr> */
 		break;
 	}
 	write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
@@ -2530,13 +2509,12 @@
 		}
 		write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
 	} else {
-		sfp->closed = 1;	/* flag dirty state on this fd */
-		sdp->device->access_count++;
 		/* MOD_INC's to inhibit unloading sg and associated adapter driver */
-		if (sg_template.module)
-			__MOD_INC_USE_COUNT(sg_template.module);
-		if (sdp->device->host->hostt->module)
-			__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
+		/* only bump the access_count if we actually succeeded in
+		 * throwing another counter on the host module */
+		if(try_module_get(sdp->device->host->hostt->module))
+			sdp->device->access_count++;
+		sfp->closed = 1;	/* flag dirty state on this fd */
 		SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
 				  dirty));
 	}
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/scsi/sr.c	Sun Nov 17 20:30:12 2002
@@ -66,16 +66,15 @@
 	 CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_GENERIC_PACKET)
 
 static int sr_attach(struct scsi_device *);
-static int sr_detect(struct scsi_device *);
 static void sr_detach(struct scsi_device *);
 static int sr_init_command(struct scsi_cmnd *);
 
 static struct Scsi_Device_Template sr_template = {
 	.module		= THIS_MODULE,
+	.list		= LIST_HEAD_INIT(sr_template.list),
 	.name		= "cdrom",
 	.tag		= "sr",
 	.scsi_type	= TYPE_ROM,
-	.detect		= sr_detect,
 	.attach		= sr_attach,
 	.detach		= sr_detach,
 	.init_command	= sr_init_command
@@ -130,10 +129,7 @@
 	if (cd->device->sector_size > 2048)
 		sr_set_blocklength(cd, 2048);
 	cd->device->access_count--;
-	if (cd->device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(cd->device->host->hostt->module);
-	if (sr_template.module)
-		__MOD_DEC_USE_COUNT(sr_template.module);
+	module_put(cd->device->host->hostt->module);
 }
 
 static struct cdrom_device_ops sr_dops = {
@@ -472,11 +468,9 @@
 	if (!scsi_block_when_processing_errors(cd->device)) {
 		return -ENXIO;
 	}
+	if(!try_module_get(cd->device->host->hostt->module))
+		return -ENXIO;
 	cd->device->access_count++;
-	if (cd->device->host->hostt->module)
-		__MOD_INC_USE_COUNT(cd->device->host->hostt->module);
-	if (sr_template.module)
-		__MOD_INC_USE_COUNT(sr_template.module);
 
 	/* If this device did not have media in the drive at boot time, then
 	 * we would have been unable to get the sector size.  Check to see if
@@ -487,14 +481,6 @@
 		get_sectorsize(cd);
 
 	return 0;
-}
-
-static int sr_detect(struct scsi_device * SDp)
-{
-
-	if (SDp->type != TYPE_ROM && SDp->type != TYPE_WORM)
-		return 0;
-	return 1;
 }
 
 static int sr_attach(struct scsi_device *sdev)
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/st.c	Sun Nov 17 20:30:14 2002
@@ -1,6 +1,6 @@
 /*
    SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
-   file README.st for more information.
+   file Documentation/scsi/st.txt for more information.
 
    History:
    Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
@@ -170,15 +170,14 @@
 static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
 
 static int st_attach(Scsi_Device *);
-static int st_detect(Scsi_Device *);
 static void st_detach(Scsi_Device *);
 
 static struct Scsi_Device_Template st_template = {
 	.module =	THIS_MODULE,
+	.list =		LIST_HEAD_INIT(st_template.list),
 	.name =		"tape", 
 	.tag =		"st", 
 	.scsi_type =	TYPE_TAPE,
-	.detect =	st_detect, 
 	.attach =	st_attach, 
 	.detach =	st_detach
 };
@@ -992,13 +991,13 @@
 		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
 		return (-EBUSY);
 	}
+	if(!try_module_get(STp->device->host->hostt->module))
+		return (-ENXIO);
+	STp->device->access_count++;
 	STp->in_use = 1;
 	write_unlock(&st_dev_arr_lock);
 	STp->rew_at_close = STp->autorew_dev = (minor(inode->i_rdev) & 0x80) == 0;
 
-	if (STp->device->host->hostt->module)
-		__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
-	STp->device->access_count++;
 
 	if (!scsi_block_when_processing_errors(STp->device)) {
 		retval = (-ENXIO);
@@ -1040,8 +1039,7 @@
 	normalize_buffer(STp->buffer);
 	STp->in_use = 0;
 	STp->device->access_count--;
-	if (STp->device->host->hostt->module)
-	    __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
+	module_put(STp->device->host->hostt->module);
 	return retval;
 
 }
@@ -1175,8 +1173,7 @@
 	STp->in_use = 0;
 	write_unlock(&st_dev_arr_lock);
 	STp->device->access_count--;
-	if (STp->device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
+	module_put(STp->device->host->hostt->module);
 
 	return result;
 }
@@ -3576,7 +3573,7 @@
 }
 
 #ifndef MODULE
-/* Set the boot options. Syntax is defined in README.st.
+/* Set the boot options. Syntax is defined in Documenation/scsi/st.txt.
  */
 static int __init st_setup(char *str)
 {
@@ -3874,7 +3871,7 @@
 				S_IFCHR | S_IRUGO | S_IWUGO,
 				&st_fops, NULL);
 	}
-	devfs_register_tape (tpnt->de_r[0]);
+	disk->number = devfs_register_tape(SDp->de);
 
 	printk(KERN_WARNING
 	"Attached scsi tape %s at scsi%d, channel %d, id %d, lun %d\n",
@@ -3885,13 +3882,6 @@
 	return 0;
 };
 
-static int st_detect(Scsi_Device * SDp)
-{
-	if (SDp->type != TYPE_TAPE || st_incompatible(SDp))
-		return 0;
-	return 1;
-}
-
 static void st_detach(Scsi_Device * SDp)
 {
 	Scsi_Tape *tpnt;
@@ -3908,6 +3898,7 @@
 				devfs_unregister (tpnt->de_n[mode]);
 				tpnt->de_n[mode] = NULL;
 			}
+			devfs_unregister_tape(tpnt->disk->number);
 			scsi_tapes[i] = 0;
 			scsi_slave_detach(SDp);
 			st_nr_dev--;
diff -Nru a/drivers/scsi/sym53c8xx_2/ChangeLog.txt b/drivers/scsi/sym53c8xx_2/ChangeLog.txt
--- a/drivers/scsi/sym53c8xx_2/ChangeLog.txt	Sun Nov 17 20:30:13 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,148 +0,0 @@
-Sat Dec 30 21:30 2000 Gerard Roudier 
-	* version sym-2.1.0-20001230
-	- Initial release of SYM-2.
-
-Mon Jan 08 21:30 2001 Gerard Roudier 
-	* version sym-2.1.1-20010108
-	- Change a couple of defines containing ncr or NCR by their 
-	  equivalent containing sym or SYM instead.
-
-Sun Jan 14 22:30 2001 Gerard Roudier 
-	* version sym-2.1.2-20010114
-	- Fix a couple of printfs:
-	  * Add the target number to the display of transfer parameters.
-	  * Make the display of TCQ and queue depth clearer.
-
-Wed Jan 17 23:30 2001 Gerard Roudier 
-	* version sym-2.1.3-20010117
-	- Wrong residual values were returned in some situations.
-	  This broke cdrecord with linux-2.4.0, for example.
-
-Sat Jan 20 18:00 2001 Gerard Roudier 
-	* version sym-2.1.4-20010120
-	- Add year 2001 to Copyright.
-	- A tiny bug in the dma memory freeing path has been fixed.
-	  (Driver unload failed with a bad address reference).
-
-Wed Jan 24 21:00 2001 Gerard Roudier 
-	* version sym-2.1.5-20010124
-	- Make the driver work under Linux-2.4.x when statically linked 
-	  with the kernel.
-	- Check against memory allocation failure for SCRIPTZ and add the 
-	  missing free of this memory on instance detach.
-	- Check against GPIO3 pulled low for HVD controllers (driver did 
-	  just the opposite).
-	  Misdetection of BUS mode was triggerred on module reload only, 
-	  since BIOS settings were trusted instead on first load.
-
-Wed Feb 7 21:00 2001 Gerard Roudier 
-	* version sym-2.1.6-20010207
-	- Call pci_enable_device() as wished by kernel maintainers.
-	- Change the sym_queue_scsiio() interface.
-	  This is intended to simplify portability.
-	- Move the code intended to deal with the dowloading of SCRIPTS 
-	  from SCRIPTS :) in the patch method (was wrongly placed in 
-	  the SCRIPTS setup method).
-	- Add a missing cpu_to_scr()  (np->abort_tbl.addr)
-	- Remove a wrong cpu_to_scr() (np->targtbl_ba)
-	- Cleanup a bit the PPR failure recovery code.
-
-Sat Mar 3 21:00 2001 Gerard Roudier 
-	- Add option SYM_OPT_ANNOUNCE_TRANSFER_RATE and move the 
-	  corresponding code to file sym_misc.c.
-	  Also move the code that sniffes INQUIRY to sym_misc.c.
-	  This allows to share the corresponding code with NetBSD 
-	  without polluating the core driver source (sym_hipd.c).
-	- Add optionnal code that handles IO timeouts from the driver.
-	  (not used under Linux, but required for NetBSD)
-	- Donnot assume any longer that PAGE_SHIFT and PAGE_SIZE are 
-	  defined at compile time, as at least NetBSD uses variables 
-	  in memory for that.
-	- Refine a work-around for the C1010-33 that consists in 
-	  disabling internal LOAD/STORE. Was applied up to revision 1.
-	  Is now only applied to revision 0.
-	- Some code reorganisations due to code moves between files.
-
-Tues Apr 10 21:00 2001 Gerard Roudier 
-	* version sym-2.1.9-20010412
-	- Reset 53C896 and 53C1010 chip according to the manual.
-	  (i.e.: set the ABRT bit in ISTAT if SCRIPTS are running)
-	- Set #LUN in request sense only if scsi version <= 2 and
-	  #LUN <= 7.
-	- Set busy_itl in LCB to 1 if the LCB is allocated and a 
-	  SCSI command is active. This is a simplification.
-	- In sym_hcb_free(), donnot scan the free_ccbq if no CCBs 
-	  has been allocated. This fixes a panic if attach failed.
-	- Add DT/ST (double/simple transition) in the transfer 
-	  negotiation announce.
-	- Forces the max number of tasks per LUN to at least 64.
-	- Use pci_set_dma_mask() for linux-2.4.3 and above.
-	- A couple of comments fixes.
-
-Wed May 22:00 2001 Gerard Roudier 
-	* version sym-2.1.10-20010509
-	- Mask GPCNTL against 0x1c (was 0xfc) for the reading of the NVRAM.
-	  This ensure LEDC bit will not be set on 896 and later chips.
-	  Fix sent by Chip Salzenberg <chip@perlsupport.com>.
-	- Define the number of PQS BUSes supported.
-	  Fix sent by Stig Telfer <stig@api-networks.com>
-	- Miscellaneous common code rearrangements due to NetBSD accel 
-	  ioctl support, without impact on Linux (hopefully).
-
-Mon July 2 12:00 2001 Gerard Roudier 
-	* version sym-2.1.11-20010702
-	- Add Tekram 390 U2B/U2W SCSI LED handling.
-	  Submitted by Chip Salzenberg <chip@valinux.com>
-	- Add call to scsi_set_pci_device() for kernels >= 2.4.4.
-	- Check pci dma mapping failures and complete the IO with some 
-	  error when such mapping fails.
-	- Fill in instance->max_cmd_len for kernels > 2.4.0.
-	- A couple of tiny fixes ...
-
-Sun Sep 9 18:00 2001 Gerard Roudier 
-	* version sym-2.1.12-20010909
-	- Change my email address.
-	- Add infrastructure for the forthcoming 64 bit DMA adressing support.
-	  (Based on PCI 64 bit patch from David S. Miller)
-	- Donnot use anymore vm_offset_t type.
-
-Sat Sep 15 20:00 2001 Gerard Roudier 
-	* version sym-2.1.13-20010916
-	- Add support for 64 bit DMA addressing using segment registers.
-	  16 registers for up to 4 GB x 16 -> 64 GB.
-
-Sat Sep 22 12:00 2001 Gerard Roudier 
-	* version sym-2.1.14-20010922
-	- Complete rewrite of the eh handling. The driver is now using a 
-	  semaphore in order to behave synchronously as required by the eh 
-	  threads. A timer is also used to prevent from waiting indefinitely.
-
-Sun Sep 30 17:00 2001 Gerard Roudier 
-	* version sym-2.1.15-20010930
-	- Include <linux/module.h> unconditionnaly as expected by latest
-	  kernels.
-	- Use del_timer_sync() for recent kernels to kill the driver timer 
-	  on module release.
-
-Sun Oct 28 15:00 2001 Gerard Roudier 
-	* version sym-2.1.16-20011028
-	- Slightly simplify driver configuration.
-	- Prepare a new patch against linux-2.4.13.
-
-Sat Nov 17 10:00 2001 Gerard Roudier 
-	* version sym-2.1.17
-	- Fix a couple of gcc/gcc3 warnings.
-	- Allocate separately from the HCB the array for CCBs hashed by DSA.
-	  All driver memory allocations are now not greater than 1 PAGE 
-	  even on PPC64 / 4KB PAGE surprising setup.
-
-Sat Dec 01 18:00 2001 Gerard Roudier 
-	* version sym-2.1.17a
-	- Use u_long instead of U32 for the IO base cookie. This is more 
-	  consistent with what archs are expecting.
-	- Use MMIO per default for Power PC instead of some fake normal IO,
-	  as Paul Mackerras stated that MMIO works fine now on this arch.
-
-
-
-
diff -Nru a/drivers/scsi/sym53c8xx_2/Documentation.txt b/drivers/scsi/sym53c8xx_2/Documentation.txt
--- a/drivers/scsi/sym53c8xx_2/Documentation.txt	Sun Nov 17 20:30:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1149 +0,0 @@
-The Linux SYM-2 driver documentation file
-
-Written by Gerard Roudier <groudier@free.fr>
-21 Rue Carnot
-95170 DEUIL LA BARRE - FRANCE
-
-Decembre 28 2000
-===============================================================================
-
-1.  Introduction
-2.  Supported chips and SCSI features
-3.  Advantages of this driver for newer chips.
-      3.1 Optimized SCSI SCRIPTS
-      3.2 New features appeared with the SYM53C896
-4.  Memory mapped I/O versus normal I/O
-5.  Tagged command queueing
-6.  Parity checking
-7.  Profiling information
-8.  Control commands
-      8.1  Set minimum synchronous period
-      8.2  Set wide size
-      8.3  Set maximum number of concurrent tagged commands
-      8.4  Set debug mode
-      8.5  Set flag (no_disc)
-      8.6  Set verbose level
-      8.7  Reset all logical units of a target
-      8.8  Abort all tasks of all logical units of a target
-9.  Configuration parameters
-10. Boot setup commands
-      10.1 Syntax
-      10.2 Available arguments
-             10.2.1  Master parity checking
-             10.2.2  Scsi parity checking
-             10.2.3  Default number of tagged commands
-             10.2.4  Default synchronous period factor
-             10.2.5  Verbosity level
-             10.2.6  Debug mode
-             10.2.7  Burst max
-             10.2.8  LED support
-             10.2.9  Max wide
-             10.2.10 Differential mode
-             10.2.11 IRQ mode
-             10.2.12 Reverse probe
-             10.2.13 Fix up PCI configuration space
-             10.2.14 Serial NVRAM
-             10.2.15 Check SCSI BUS 
-             10.2.16 Exclude a host from being attached
-             10.2.17 Suggest a default SCSI id for hosts
-      10.3 PCI configuration fix-up boot option
-      10.4 Serial NVRAM support boot option
-      10.5 SCSI BUS checking boot option
-11. SCSI problem troubleshooting
-      15.1 Problem tracking
-      15.2 Understanding hardware error reports
-12. Serial NVRAM support (by Richard Waltham)
-      17.1 Features
-      17.2 Symbios NVRAM layout
-      17.3 Tekram  NVRAM layout
-
-===============================================================================
-
-1. Introduction
-
-This driver supports the whole SYM53C8XX family of PCI-SCSI controllers.
-It also support the subset of LSI53C10XX PCI-SCSI controllers that are based 
-on the SYM53C8XX SCRIPTS language.
-
-It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code 
-with the FreeBSD SYM-2 driver. The `glue' that allows this driver to work 
-under Linux is contained in 2 files named sym_glue.h and sym_glue.c.
-Other drivers files are intended not to depend on the Operating System 
-on which the driver is used.
-
-The history of this driver can be summerized as follows:
-
-1993: ncr driver written for 386bsd and FreeBSD by:
-          Wolfgang Stanglmeier        <wolf@cologne.de>
-          Stefan Esser                <se@mi.Uni-Koeln.de>
-
-1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx.
-          Gerard Roudier
-
-1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that 
-      adds full support for the 896 but drops support for early NCR devices.
-          Gerard Roudier
-
-1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010 
-      33 MHz and 66MHz Ultra-3 controllers. The new driver is named `sym'.
-          Gerard Roudier
-
-2000: Add support for early NCR devices to FreeBSD `sym' driver.
-      Break the driver into several sources and separate the OS glue 
-      code from the core code that can be shared among different O/Ses.
-      Write a glue code for Linux.
-          Gerard Roudier
-
-This README file addresses the Linux version of the driver. Under FreeBSD, 
-the driver documentation is the sym.8 man page.
-
-Information about new chips is available at LSILOGIC web server:
-
-          http://www.lsilogic.com/
-
-SCSI standard documentations are available at T10 site:
-
-          http://www.t10.org/
-
-Useful SCSI tools written by Eric Youngdale are part of most Linux 
-distributions:
-   scsiinfo:    command line tool
-   scsi-config: TCL/Tk tool using scsiinfo
-
-2. Supported chips and SCSI features
-
-The following features are supported for all chips:
-
-	Synchronous negotiation
-	Disconnection
-	Tagged command queuing
-	SCSI parity checking
-	PCI Master parity checking
-
-Other features depends on chip capabilities.
-The driver notably uses optimized SCRIPTS for devices that support 
-LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that 
-support the corresponding feature.
-
-The following table shows some characteristics of the chip family.
-
-       On board                                   LOAD/STORE   HARDWARE
-Chip   SDMS BIOS   Wide   SCSI std.   Max. sync   SCRIPTS      PHASE MISMATCH
-----   ---------   ----   ---------   ----------  ----------   --------------
-810        N         N      FAST10    10 MB/s        N             N
-810A       N         N      FAST10    10 MB/s        Y             N
-815        Y         N      FAST10    10 MB/s        N             N
-825        Y         Y      FAST10    20 MB/s        N             N
-825A       Y         Y      FAST10    20 MB/s        Y             N
-860        N         N      FAST20    20 MB/s        Y             N
-875        Y         Y      FAST20    40 MB/s        Y             N
-875A       Y         Y      FAST20    40 MB/s        Y             Y
-876        Y         Y      FAST20    40 MB/s        Y             N
-895        Y         Y      FAST40    80 MB/s        Y             N
-895A       Y         Y      FAST40    80 MB/s        Y             Y
-896        Y         Y      FAST40    80 MB/s        Y             Y
-897        Y         Y      FAST40    80 MB/s        Y             Y
-1510D      Y         Y      FAST40    80 MB/s        Y             Y
-1010       Y         Y      FAST80   160 MB/s        Y             Y
-1010_66*   Y         Y      FAST80   160 MB/s        Y             Y
-
-* Chip supports 33MHz and 66MHz PCI bus clock.
-
-
-Summary of other supported features:
-
-Module:                allow to load the driver
-Memory mapped I/O:     increases performance
-Control commands:      write operations to the proc SCSI file system
-Debugging information: written to syslog (expert only)
-Scatter / gather
-Shared interrupt
-Boot setup commands
-Serial NVRAM:          Symbios and Tekram formats
-
-
-3. Advantages of this driver for newer chips.
-
-3.1 Optimized SCSI SCRIPTS.
-
-All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions 
-named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register 
-to/from memory much faster that the MOVE MEMORY instruction that is supported 
-by the 53c7xx and 53c8xx family.
-
-The LOAD/STORE instructions support absolute and DSA relative addressing 
-modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead 
-of MOVE MEMORY instructions.
-
-Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this 
-driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in 
-order to provide support for the entire SYM53C8XX chips family.
-
-3.2 New features appeared with the SYM53C896
-
-Newer chips (see above) allows handling of the phase mismatch context from 
-SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor 
-until the C code has saved the context of the transfer).
-
-The 896 and 1010 chips support 64 bit PCI transactions and addressing, 
-while the 895A supports 32 bit PCI transactions and 64 bit addressing.
-The SCRIPTS processor of these chips is not true 64 bit, but uses segment 
-registers for bit 32-63. Another interesting feature is that LOAD/STORE 
-instructions that address the on-chip RAM (8k) remain internal to the chip.
-
-4. Memory mapped I/O versus normal I/O
-
-Memory mapped I/O has less latency than normal I/O and is the recommended 
-way for doing IO with PCI devices. Memory mapped I/O seems to work fine on 
-most hardware configurations, but some poorly designed chipsets may break 
-this feature. A configuration option is provided for normal I/O to be 
-used but the driver defaults to MMIO.
-
-5. Tagged command queueing
-
-Queuing more than 1 command at a time to a device allows it to perform 
-optimizations based on actual head positions and its mechanical 
-characteristics. This feature may also reduce average command latency.
-In order to really gain advantage of this feature, devices must have 
-a reasonnable cache size (No miracle is to be expected for a low-end 
-hard disk with 128 KB or less).
-Some kown old SCSI devices do not properly support tagged command queuing.
-Generally, firmware revisions that fix this kind of problems are available 
-at respective vendor web/ftp sites.
-All I can say is that I never have had problem with tagged queuing using 
-this driver and its predecessors. Hard disks that behaved correctly for 
-me using tagged commands are the following:
-
-- IBM S12 0662
-- Conner 1080S
-- Quantum Atlas I
-- Quantum Atlas II
-- Seagate Cheetah I
-- Quantum Viking II
-- IBM DRVS
-- Quantum Atlas IV
-- Seagate Cheetah II
-
-If your controller has NVRAM, you can configure this feature per target 
-from the user setup tool. The Tekram Setup program allows to tune the 
-maximum number of queued commands up to 32. The Symbios Setup only allows 
-to enable or disable this feature.
-
-The maximum number of simultaneous tagged commands queued to a device
-is currently set to 16 by default.  This value is suitable for most SCSI
-disks.  With large SCSI disks (>= 2GB, cache >= 512KB, average seek time
-<= 10 ms), using a larger value may give better performances.
-
-This driver supports up to 255 commands per device, and but using more than 
-64 is generally not worth-while, unless you are using a very large disk or 
-disk arrays. It is noticeable that most of recent hard disks seem not to 
-accept more than 64 simultaneous commands. So, using more than 64 queued 
-commands is probably just resource wasting.
-
-If your controller does not have NVRAM or if it is managed by the SDMS 
-BIOS/SETUP, you can configure tagged queueing feature and device queue 
-depths from the boot command-line. For example:
-
-  sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32
-
-will set tagged commands queue depths as follow:
-
-- target 2  all luns  on controller 0 --> 15
-- target 3  all luns  on controller 0 --> 15
-- target 4  all luns  on controller 0 -->  7
-- target 1  lun 0     on controller 1 --> 32
-- all other target/lun                -->  4
-
-In some special conditions, some SCSI disk firmwares may return a
-QUEUE FULL status for a SCSI command. This behaviour is managed by the
-driver using the following heuristic:
-
-- Each time a QUEUE FULL status is returned, tagged queue depth is reduced 
-  to the actual number of disconnected commands. 
-
-- Every 200 successfully completed SCSI commands, if allowed by the
-  current limit, the maximum number of queueable commands is incremented.
-
-Since QUEUE FULL status reception and handling is resource wasting, the 
-driver notifies by default this problem to user by indicating the actual 
-number of commands used and their status, as well as its decision on the 
-device queue depth change.
-The heuristic used by the driver in handling QUEUE FULL ensures that the 
-impact on performances is not too bad. You can get rid of the messages by 
-setting verbose level to zero, as follow:
-
-1st method: boot your system using 'sym53c8xx=verb:0' option.
-2nd method: apply "setverbose 0" control command to the proc fs entry 
-            corresponding to your controller after boot-up.
-
-6. Parity checking
-
-The driver supports SCSI parity checking and PCI bus master parity
-checking. These features must be enabled in order to ensure safe data
-transfers. However, some flawed devices or mother boards will have
-problems with parity. You can disable either PCI parity or SCSI parity 
-checking by entering appropriate options from the boot command line.
-(See 10: Boot setup commands).
-
-7. Profiling information
-
-This driver does not provide profiling informations as did its predecessors.
-This feature was not this useful and added complexity to the code. 
-As the driver code got more complex, I have decided to remove everything 
-that didn't seem actually useful.
-
-8. Control commands
-
-Control commands can be sent to the driver with write operations to
-the proc SCSI file system. The generic command syntax is the
-following:
-
-      echo "<verb> <parameters>" >/proc/scsi/sym53c8xx/0
-      (assumes controller number is 0)
-
-Using "all" for "<target>" parameter with the commands below will
-apply to all targets of the SCSI chain (except the controller).
-
-Available commands:
-
-8.1 Set minimum synchronous period factor
-
-    setsync <target> <period factor>
-
-    target:    target number
-    period:    minimum synchronous period.
-               Maximum speed = 1000/(4*period factor) except for special
-               cases below.
-
-    Specify a period of 0, to force asynchronous transfer mode.
-
-       9 means 12.5 nano-seconds synchronous period
-      10 means 25 nano-seconds synchronous period
-      11 means 30 nano-seconds synchronous period
-      12 means 50 nano-seconds synchronous period
-
-8.2 Set wide size
-
-    setwide <target> <size>
-
-    target:    target number
-    size:      0=8 bits, 1=16bits
-
-8.3 Set maximum number of concurrent tagged commands
- 
-    settags <target> <tags>
-
-    target:    target number
-    tags:      number of concurrent tagged commands
-               must not be greater than configured (default: 16)
-
-8.4 Set debug mode
-
-    setdebug <list of debug flags>
-
-    Available debug flags:
-        alloc:   print info about memory allocations (ccb, lcb)
-        queue:   print info about insertions into the command start queue
-        result:  print sense data on CHECK CONDITION status
-        scatter: print info about the scatter process
-        scripts: print info about the script binding process
-	tiny:    print minimal debugging information
-	timing:  print timing information of the NCR chip
-	nego:    print information about SCSI negotiations
-	phase:   print information on script interruptions
-
-    Use "setdebug" with no argument to reset debug flags.
-
-
-8.5 Set flag (no_disc)
- 
-    setflag <target> <flag>
-
-    target:    target number
-
-    For the moment, only one flag is available:
-
-        no_disc:   not allow target to disconnect.
-
-    Do not specify any flag in order to reset the flag. For example:
-    - setflag 4
-      will reset no_disc flag for target 4, so will allow it disconnections.
-    - setflag all
-      will allow disconnection for all devices on the SCSI bus.
-
-
-8.6 Set verbose level
-
-    setverbose #level
-
-    The driver default verbose level is 1. This command allows to change 
-    th driver verbose level after boot-up.
-
-8.7 Reset all logical units of a target
-
-    resetdev <target>
-
-    target:    target number
-    The driver will try to send a BUS DEVICE RESET message to the target.
-
-8.8 Abort all tasks of all logical units of a target
-
-    cleardev <target>
-
-    target:    target number
-    The driver will try to send a ABORT message to all the logical units 
-    of the target.
-
-
-9. Configuration parameters
-
-Under kernel configuration tools (make menuconfig, for example), it is 
-possible to change some default driver configuration parameters.
-If the firmware of all your devices is perfect enough, all the
-features supported by the driver can be enabled at start-up. However,
-if only one has a flaw for some SCSI feature, you can disable the
-support by the driver of this feature at linux start-up and enable
-this feature after boot-up only for devices that support it safely.
-
-Configuration parameters:
-
-Use normal IO                         (default answer: n)
-    Answer "y" if you suspect your mother board to not allow memory mapped I/O.
-    May slow down performance a little.
-
-Default tagged command queue depth    (default answer: 16)
-    Entering 0 defaults to tagged commands not being used.
-    This parameter can be specified from the boot command line.
-
-Maximum number of queued commands     (default answer: 32)
-    This option allows you to specify the maximum number of tagged commands 
-    that can be queued to a device. The maximum supported value is 255.
-
-Synchronous transfers frequency       (default answer: 80)
-    This option allows you to specify the frequency in MHz the driver 
-    will use at boot time for synchronous data transfer negotiations.
-    0 means "asynchronous data transfers".
-
-10. Boot setup commands
-
-10.1 Syntax
-
-Setup commands can be passed to the driver either at boot time or as a 
-string variable using 'insmod'.
-
-A boot setup command for this driver begins with the driver name "sym53c8xx=".
-The kernel syntax parser then expects an optionnal list of integers separated 
-with comma followed by an optional list of  comma-separated strings.
-
-Example of boot setup command under lilo prompt:
-
-lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
-
-- enable tagged commands, up to 4 tagged commands queued.
-- set synchronous negotiation speed to 10 Mega-transfers / second.
-- set DEBUG_NEGO flag.
-
-Since comma seems not to be allowed when defining a string variable using  
-'insmod', the driver also accepts <space> as option separator. 
-The following command will install driver module with the same options as 
-above.
-
-    insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200"
-
-The integer list of arguments is discarded by the driver. 
-
-Each string argument must be specified as "keyword:value". Only lower-case 
-characters and digits are allowed.
-
-10.2 Available arguments
-
-10.2.1  Master parity checking
-        mpar:y     enabled
-        mpar:n     disabled
-
-10.2.2  Scsi parity checking
-        spar:y     enabled
-        spar:n     disabled
-
-10.2.3  Default number of tagged commands
-        tags:0     (or tags:1 ) tagged command queuing disabled
-        tags:#tags (#tags  > 1) tagged command queuing enabled
-  #tags will be truncated to the max queued commands configuration parameter.
-  This option also allows to specify a command queue depth for each device 
-  that support tagged command queueing.
-  Example:
-      sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
-               will set devices queue depth as follow:
-      - controller #0 target #2 and target #3                  -> 16 commands,
-      - controller #0 target #5                                -> 24 commands,
-      - controller #1 target #1 logical unit #2                -> 32 commands,
-      - all other logical units (all targets, all controllers) -> 10 commands.
-
-10.2.4  Default synchronous period factor
-        sync:255     disabled (asynchronous transfer mode)
-        sync:#factor
-  #factor =  9     Ultra-3 SCSI 80 Mega-transfers / second (Wide only)
-  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
-  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
-  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
-  #factor < 50     Fast    SCSI-2
-
-  In all cases, the driver will use the minimum transfer period supported by 
-  controllers according to SYM53C8XX chip type.
-
-10.2.5  Verbosity level
-        verb:0     minimal
-        verb:1     normal
-        verb:2     too much
-
-10.2.6 Debug mode
-        debug:0	 clear debug flags
-        debug:#x   set debug flags
-  #x is an integer value combining the following power-of-2 values:
-  DEBUG_ALLOC       0x1
-  DEBUG_PHASE       0x2
-  DEBUG_POLL        0x4
-  DEBUG_QUEUE       0x8
-  DEBUG_RESULT     0x10
-  DEBUG_SCATTER    0x20
-  DEBUG_SCRIPT     0x40
-  DEBUG_TINY       0x80
-  DEBUG_TIMING    0x100
-  DEBUG_NEGO      0x200
-  DEBUG_TAGS      0x400
-  DEBUG_FREEZE    0x800
-  DEBUG_RESTART  0x1000
-
-  You can play safely with DEBUG_NEGO. However, some of these flags may 
-  generate bunches of syslog messages. 
-
-10.2.7 Burst max
-        burst:0    burst disabled
-        burst:255  get burst length from initial IO register settings.
-        burst:#x   burst enabled (1<<#x burst transfers max)
-  #x is an integer value which is log base 2 of the burst transfers max.
-  By default the driver uses the maximum value supported by the chip.
-
-10.2.8 LED support
-        led:1      enable  LED support
-        led:0      disable LED support
-  Donnot enable LED support if your scsi board does not use SDMS BIOS.
-  (See 'Configuration parameters')
-
-10.2.9 Max wide
-        wide:1      wide scsi enabled
-        wide:0      wide scsi disabled
-  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
-  If you have connected a wide device with a 50 pins to 68 pins cable 
-  converter, any accepted wide negotiation will break further data transfers.
-  In such a case, using "wide:0" in the bootup command will be helpfull. 
-
-10.2.10 Differential mode
-        diff:0	never set up diff mode
-        diff:1	set up diff mode if BIOS set it
-        diff:2	always set up diff mode
-        diff:3	set diff mode if GPIO3 is not set
-
-10.2.11 IRQ mode
-        irqm:0     always open drain
-        irqm:1     same as initial settings (assumed BIOS settings)
-        irqm:2     always totem pole
-
-10.2.12 Reverse probe
-        revprob:n   probe chip ids from the PCI configuration in this order:
-                    810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A,
-                    1510D, 1010-33, 1010-66.
-        revprob:y   probe chip ids in the reverse order.
-
-10.2.13 Fix up PCI configuration space
-        pcifix:<option bits>
-
-    Available option bits:
-        0x0:   No attempt to fix PCI configuration space registers values.
-        0x1:   Set PCI cache-line size register if not set.
-        0x2:   Set write and invalidate bit in PCI command register.
-
-10.2.14 Serial NVRAM
-        nvram:n     do not look for serial NVRAM
-        nvram:y     test controllers for onboard serial NVRAM
-        (alternate binary form)
-        mvram=<bits options>
-        0x01   look for NVRAM  (equivalent to nvram=y)
-        0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-        0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-        0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-        0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-10.2.15 Check SCSI BUS 
-        buschk:<option bits>
-
-    Available option bits:
-        0x0:   No check.
-        0x1:   Check and donnot attach the controller on error.  
-        0x2:   Check and just warn on error.
-
-10.2.16 Exclude a host from being attached
-        excl=<io_address>
-
-    Prevent host at a given io address from being attached.
-    For example 'sym53c8xx=excl:0xb400,excl:0xc000' indicate to the 
-    driver not to attach hosts at address 0xb400 and 0xc000.
-
-10.2.17 Suggest a default SCSI id for hosts
-        hostid:255	no id suggested.
-        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
-
-    If a host SCSI id is available from the NVRAM, the driver will ignore 
-    any value suggested as boot option. Otherwise, if a suggested value 
-    different from 255 has been supplied, it will use it. Otherwise, it will 
-    try to deduce the value previously set in the hardware and use value 
-    7 if the hardware value is zero.
-
-10.3 PCI configuration fix-up boot option
-
-pcifix:<option bits>
-
-Available option bits:
-    0x1:     Set PCI cache-line size register if not set.
-    0x2:     Set write and invalidate bit in PCI command register.
-
-Use 'pcifix:3' in order to allow the driver to fix both PCI features.
-
-Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
-and PCI write and invalidate commands. These features require the 
-cache line size register to be properly set in the PCI configuration 
-space of the chips. On the other hand, chips will use PCI write and 
-invalidate commands only if the corresponding bit is set to 1 in the 
-PCI command register.
-
-Not all PCI bioses set the PCI cache line register and the PCI write and 
-invalidate bit in the PCI configuration space of 53C8XX chips.
-Optimized PCI accesses may be broken for some PCI/memory controllers or 
-make problems with some PCI boards.
-
-10.4 Serial NVRAM support boot option
-
-nvram:n     do not look for serial NVRAM
-nvram:y     test controllers for onboard serial NVRAM
-
-This option can also been entered as an hexadecimal value that allows 
-to control what information the driver will get from the NVRAM and what 
-information it will ignore.
-For details see '17. Serial NVRAM support'.
-
-When this option is enabled, the driver tries to detect all boards using 
-a Serial NVRAM. This memory is used to hold user set up parameters.
-
-The parameters the driver is able to get from the NVRAM depend on the 
-data format used, as follow:
-
-                                 Tekram format      Symbios format
-General and host parameters
-    Boot order                         N                   Y
-    Host SCSI ID                       Y                   Y
-    SCSI parity checking               Y                   Y
-    Verbose boot messages              N                   Y
-SCSI devices parameters
-    Synchronous transfer speed         Y                   Y
-    Wide 16 / Narrow                   Y                   Y
-    Tagged Command Queuing enabled     Y                   Y
-    Disconnections enabled             Y                   Y
-    Scan at boot time                  N                   Y
-
-In order to speed up the system boot, for each device configured without 
-the "scan at boot time" option, the driver forces an error on the 
-first TEST UNIT READY command received for this device.
-
-Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
-hard disks. In such a situation you cannot configure the NVRAM with 
-optimized parameters value.
-
-The 'nvram' boot option can be entered in hexadecimal form in order 
-to ignore some options configured in the NVRAM, as follow:
-
-mvram=<bits options>
-      0x01   look for NVRAM  (equivalent to nvram=y)
-      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-Option 0x80 is disabled by default.
-Result is that, by default (option not set), the sym53c8xx driver will not 
-attach controllers set to OFF in the NVRAM.
-
-10.5 SCSI BUS checking boot option.
-
-When this option is set to a non-zero value, the driver checks SCSI lines 
-logic state, 100 micro-seconds after having asserted the SCSI RESET line.
-The driver just reads SCSI lines and checks all lines read FALSE except RESET.
-Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI 
-RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem.
-Unfortunately, the following common SCSI BUS problems are not detected:
-- Only 1 terminator installed.
-- Misplaced terminators.
-- Bad quality terminators.
-On the other hand, either bad cabling, broken devices, not conformant 
-devices, ... may cause a SCSI signal to be wrong when te driver reads it.
-
-15. SCSI problem troubleshooting
-
-15.1 Problem tracking
-
-Most SCSI problems are due to a non conformant SCSI bus or too buggy
-devices.  If infortunately you have SCSI problems, you can check the
-following things:
-
-- SCSI bus cables
-- terminations at both end of the SCSI chain
-- linux syslog messages (some of them may help you)
-
-If you donnot find the source of problems, you can configure the
-driver or devices in the NVRAM with minimal features.
-
-- only asynchronous data transfers
-- tagged commands disabled
-- disconnections not allowed
-
-Now, if your SCSI bus is ok, your system has every chance to work
-with this safe configuration but performances will not be optimal.
-
-If it still fails, then you can send your problem description to
-appropriate mailing lists or news-groups.  Send me a copy in order to
-be sure I will receive it.  Obviously, a bug in the driver code is
-possible.
-
-  My cyrrent email address: Gerard Roudier <groudier@free.fr>
-
-Allowing disconnections is important if you use several devices on
-your SCSI bus but often causes problems with buggy devices.
-Synchronous data transfers increases throughput of fast devices like
-hard disks.  Good SCSI hard disks with a large cache gain advantage of
-tagged commands queuing.
-
-15.2 Understanding hardware error reports
-
-When the driver detects an unexpected error condition, it may display a 
-message of the following pattern.
-
-sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
-sym0: script cmd = 19000000
-sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00.
-
-Some fields in such a message may help you understand the cause of the 
-problem, as follows:
-
-sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000).
-.....A.........B.C....D.E..F....G.H..I.......J.....K...L.......
-
-Field A : target number.
-  SCSI ID of the device the controller was talking with at the moment the 
-  error occurs.
-
-Field B : DSTAT io register (DMA STATUS)
-  Bit 0x40 : MDPE Master Data Parity Error
-             Data parity error detected on the PCI BUS.
-  Bit 0x20 : BF   Bus Fault
-             PCI bus fault condition detected
-  Bit 0x01 : IID  Illegal Instruction Detected
-             Set by the chip when it detects an Illegal Instruction format 
-             on some condition that makes an instruction illegal.
-  Bit 0x80 : DFE Dma Fifo Empty
-             Pure status bit that does not indicate an error.
-  If the reported DSTAT value contains a combination of MDPE (0x40), 
-  BF (0x20), then the cause may be likely due to a PCI BUS problem.
-
-Field C : SIST io register (SCSI Interrupt Status)
-  Bit 0x08 : SGE  SCSI GROSS ERROR
-             Indicates that the chip detected a severe error condition 
-             on the SCSI BUS that prevents the SCSI protocol from functionning
-             properly.
-  Bit 0x04 : UDC  Undexpected Disconnection
-             Indicates that the device released the SCSI BUS when the chip 
-             was not expecting this to happen. A device may behave so to 
-             indicate the SCSI initiator that an error condition not reportable              using the SCSI protocol has occured.
-  Bit 0x02 : RST  SCSI BUS Reset
-             Generally SCSI targets donnot reset the SCSI BUS, although any 
-             device on the BUS can reset it at any time.
-  Bit 0x01 : PAR  Parity
-             SCSI parity error detected.
-  On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and 
-  PAR (0x01) may be detected by the chip. If your SCSI system sometimes 
-  encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI 
-  BUS problem is likely the cause of these errors.
-
-For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file 
-that contains some minimal comments on IO register bits.
-Field D : SOCL  Scsi Output Control Latch
-          This register reflects the state of the SCSI control lines the 
-          chip want to drive or compare against.
-Field E : SBCL  Scsi Bus Control Lines
-          Actual value of control lines on the SCSI BUS.
-Field F : SBDL  Scsi Bus Data Lines
-          Actual value of data lines on the SCSI BUS.
-Field G : SXFER  SCSI Transfer
-          Contains the setting of the Synchronous Period for output and 
-          the current Synchronous offset (offset 0 means asynchronous).
-Field H : SCNTL3 Scsi Control Register 3
-          Contains the setting of timing values for both asynchronous and 
-          synchronous data transfers. 
-Field I : SCNTL4 Scsi Control Register 4
-          Only meaninful for 53C1010 Ultra3 controllers.
-
-Understanding Fields J, K, L and dumps requires to have good knowledge of 
-SCSI standards, chip cores functionnals and internal driver data structures.
-You are not required to decode and understand them, unless you want to help 
-maintain the driver code.
-
-17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk)
-
-17.1 Features
-
-Enabling serial NVRAM support enables detection of the serial NVRAM included
-on Symbios and some Symbios compatible host adaptors, and Tekram boards. The 
-serial NVRAM is used by Symbios and Tekram to hold set up parameters for the 
-host adaptor and it's attached drives.
-
-The Symbios NVRAM also holds data on the boot order of host adaptors in a
-system with more than one host adaptor. This enables the order of scanning
-the cards for drives to be changed from the default used during host adaptor
-detection.
-
-This can be done to a limited extent at the moment using "reverse probe" but
-this only changes the order of detection of different types of cards. The
-NVRAM boot order settings can do this as well as change the order the same
-types of cards are scanned in, something "reverse probe" cannot do.
-
-Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
-and this is used to distinguish between Symbios compatible and Tekram host 
-adaptors. This is used to disable the Symbios compatible "diff" setting
-incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT 
-configuration parameter is set enabling both Symbios and Tekram boards to be 
-used together with the Symbios cards using all their features, including
-"diff" support. ("led pin" support for Symbios compatible cards can remain
-enabled when using Tekram cards. It does nothing useful for Tekram host
-adaptors but does not cause problems either.)
-
-
-17.2 Symbios NVRAM layout
-
-typical data at NVRAM address 0x100 (53c810a NVRAM)
------------------------------------------------------------
-00 00
-64 01
-8e 0b
-
-00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 
-
-04 00 0f 00 00 10 00 50 00 00 01 00 00 62 
-04 00 03 00 00 10 00 58 00 00 01 00 00 63 
-04 00 01 00 00 10 00 48 00 00 01 00 00 61 
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 
-
-0f 00 08 08 64 00 0a 00
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 
-
-fe fe
-00 00
-00 00
------------------------------------------------------------
-NVRAM layout details
-
-NVRAM Address 0x000-0x0ff not used
-              0x100-0x26f initialised data
-              0x270-0x7ff not used
-
-general layout
-
-        header  -   6 bytes,
-        data    - 356 bytes (checksum is byte sum of this data)
-        trailer -   6 bytes
-                  ---
-        total     368 bytes
-
-data area layout
-
-        controller set up  -  20 bytes
-        boot configuration -  56 bytes (4x14 bytes)
-        device set up      - 128 bytes (16x8 bytes)
-        unused (spare?)    - 152 bytes (19x8 bytes)
-                             ---
-        total                356 bytes
-
------------------------------------------------------------
-header
-
-00 00   - ?? start marker
-64 01   - byte count (lsb/msb excludes header/trailer)
-8e 0b   - checksum (lsb/msb excludes header/trailer)
------------------------------------------------------------
-controller set up
-
-00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00
-                   |     |           |     |
-                   |     |           |      -- host ID
-                   |     |           |
-                   |     |            --Removable Media Support
-                   |     |               0x00 = none
-                   |     |               0x01 = Bootable Device
-                   |     |               0x02 = All with Media
-                   |     |
-                   |      --flag bits 2
-                   |        0x00000001= scan order hi->low
-                   |            (default 0x00 - scan low->hi)
-                    --flag bits 1
-                       0x00000001 scam enable
-                       0x00000010 parity enable
-                       0x00000100 verbose boot msgs
-
-remaining bytes unknown - they do not appear to change in my
-current set up for any of the controllers.
-
-default set up is identical for 53c810a and 53c875 NVRAM
-(Removable Media added Symbios BIOS version 4.09)
------------------------------------------------------------
-boot configuration
-
-boot order set by order of the devices in this table
-
-04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller
-04 00 03 00 00 10 00 58 00 00 01 00 00 63    2nd controller
-04 00 01 00 00 10 00 48 00 00 01 00 00 61    3rd controller
-00 00 00 00 00 00 00 00 00 00 00 00 00 00    4th controller
-       |  |  |  |     |        |     |  |
-       |  |  |  |     |        |      ---- PCI io port adr
-       |  |  |  |     |         --0x01 init/scan at boot time
-       |  |  |  |      --PCI device/function number (0xdddddfff)
-       |  |   ----- ?? PCI vendor ID (lsb/msb)
-        ----PCI device ID (lsb/msb)
-
-?? use of this data is a guess but seems reasonable
-
-remaining bytes unknown - they do not appear to change in my
-current set up
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-device set up (up to 16 devices - includes controller)
-
-0f 00 08 08 64 00 0a 00 - id 0
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 
-0f 00 08 08 64 00 0a 00 - id 15
- |     |  |  |     |  |
- |     |  |  |      ----timeout (lsb/msb)
- |     |  |   --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28)
- |     |  |                  (0x30 20 Mtrans/sec- fast 20)
- |     |  |                  (0x64 10 Mtrans/sec- fast )
- |     |  |                  (0xc8  5 Mtrans/sec)
- |     |  |                  (0x00  asynchronous)
- |     |   -- ?? max sync offset (0x08 in NVRAM on 53c810a) 
- |     |                         (0x10 in NVRAM on 53c875)
- |      --device bus width (0x08 narrow)
- |                         (0x10 16 bit wide)
-  --flag bits
-    0x00000001 - disconnect enabled
-    0x00000010 - scan at boot time
-    0x00000100 - scan luns
-    0x00001000 - queue tags enabled
-
-remaining bytes unknown - they do not appear to change in my
-current set up
-
-?? use of this data is a guess but seems reasonable 
-(but it could be max bus width)
-
-default set up for 53c810a NVRAM
-default set up for 53c875 NVRAM - bus width     - 0x10
-                                - sync offset ? - 0x10
-                                - sync period   - 0x30
------------------------------------------------------------
-?? spare device space (32 bit bus ??)
-
-00 00 00 00 00 00 00 00  (19x8bytes)
-.
-.
-00 00 00 00 00 00 00 00
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-trailer
-
-fe fe   - ? end marker ?
-00 00
-00 00
-
-default set up is identical for 53c810a and 53c875 NVRAM
------------------------------------------------------------
-
-
-
-17.3 Tekram NVRAM layout
-
-nvram 64x16 (1024 bit)
-
-Drive settings
-
-Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID)
-              (addr 0x0yyyy1 = 0x0000)
-
-    x x x x  x x x x  x x x x  x x x x
-               | | |      | |  | | | |
-               | | |      | |  | | |  ----- parity check   0 - off
-               | | |      | |  | | |                       1 - on
-               | | |      | |  | | |
-               | | |      | |  | |  ------- sync neg       0 - off
-               | | |      | |  | |                         1 - on
-               | | |      | |  | |
-               | | |      | |  |  --------- disconnect     0 - off
-               | | |      | |  |                           1 - on
-               | | |      | |  |
-               | | |      | |   ----------- start cmd      0 - off
-               | | |      | |                              1 - on
-               | | |      | |
-               | | |      |  -------------- tagged cmds    0 - off
-               | | |      |                                1 - on
-               | | |      | 
-               | | |       ---------------- wide neg       0 - off
-               | | |                                       1 - on
-               | | |
-                --------------------------- sync rate      0 - 10.0 Mtrans/sec
-                                                           1 -  8.0
-                                                           2 -  6.6
-                                                           3 -  5.7
-                                                           4 -  5.0
-                                                           5 -  4.0
-                                                           6 -  3.0
-                                                           7 -  2.0
-                                                           7 -  2.0
-                                                           8 - 20.0
-                                                           9 - 16.7
-                                                           a - 13.9
-                                                           b - 11.9
-
-Global settings
-
-Host flags 0 (addr 0x100000, 32) 
-
-    x x x x  x x x x  x x x x  x x x x
-    | | | |  | | | |           | | | |
-    | | | |  | | | |            ----------- host ID    0x00 - 0x0f
-    | | | |  | | | |
-    | | | |  | | |  ----------------------- support for    0 - off
-    | | | |  | | |                          > 2 drives     1 - on
-    | | | |  | | | 
-    | | | |  | |  ------------------------- support drives 0 - off
-    | | | |  | |                            > 1Gbytes      1 - on
-    | | | |  | |
-    | | | |  |  --------------------------- bus reset on   0 - off
-    | | | |  |                                power on     1 - on
-    | | | |  |
-    | | | |   ----------------------------- active neg     0 - off
-    | | | |                                                1 - on
-    | | | |
-    | | |  -------------------------------- imm seek       0 - off
-    | | |                                                  1 - on
-    | | |
-    | |  ---------------------------------- scan luns      0 - off
-    | |                                                    1 - on
-    | |
-     -------------------------------------- removable      0 - disable
-                                            as BIOS dev    1 - boot device
-                                                           2 - all
-
-Host flags 1 (addr 0x100001, 33)
-
-    x x x x  x x x x  x x x x  x x x x
-               | | |             | | | 
-               | | |              --------- boot delay     0 -   3 sec
-               | | |                                       1 -   5
-               | | |                                       2 -  10
-               | | |                                       3 -  20
-               | | |                                       4 -  30
-               | | |                                       5 -  60
-               | | |                                       6 - 120
-               | | |
-                --------------------------- max tag cmds   0 -  2
-                                                           1 -  4
-                                                           2 -  8
-                                                           3 - 16
-                                                           4 - 32
-
-Host flags 2 (addr 0x100010, 34)
-
-    x x x x  x x x x  x x x x  x x x x
-                                     |
-                                      ----- F2/F6 enable   0 - off ???
-                                                           1 - on  ???
-
-checksum (addr 0x111111)
-
-checksum = 0x1234 - (sum addr 0-63)
-
-----------------------------------------------------------------------------
-
-default nvram data:
-
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000
-0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 
-
-0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
-0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc
-
-
-===============================================================================
-End of Linux SYM-2 driver documentation file
diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/scsi/tmscsim.c	Sun Nov 17 20:30:16 2002
@@ -1,17 +1,18 @@
-/***********************************************************************
- *	FILE NAME : TMSCSIM.C					       *
- *	     BY   : C.L. Huang,  ching@tekram.com.tw		       *
- *	Description: Device Driver for Tekram DC-390(T) PCI SCSI       *
- *		     Bus Master Host Adapter			       *
- * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.		       *
- ***********************************************************************/
-/* (C) Copyright: put under GNU GPL in 10/96  (see README.tmscsim)	*
-*************************************************************************/
-/* $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $		*/
-/*	Enhancements and bugfixes by					*
+/************************************************************************
+ *	FILE NAME : TMSCSIM.C						*
+ *	     BY   : C.L. Huang,  ching@tekram.com.tw			*
+ *	Description: Device Driver for Tekram DC-390(T) PCI SCSI	*
+ *		     Bus Master Host Adapter				*
+ * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.			*
+ ************************************************************************
+ * (C) Copyright: put under GNU GPL in 10/96				*
+ *				(see Documentation/scsi/tmscsim.txt)	*
+ ************************************************************************
+ * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $		*
+ *	Enhancements and bugfixes by					*
  *	Kurt Garloff <kurt@garloff.de>	<garloff@suse.de>		*
- ***********************************************************************/
-/*	HISTORY:							*
+ ************************************************************************
+ *	HISTORY:							*
  *									*
  *	REV#	DATE	NAME	DESCRIPTION				*
  *	1.00  96/04/24	CLH	First release				*
@@ -1521,7 +1522,7 @@
     DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
     PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat);
     printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
-    printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n");
+    printk ("DC390: In case of driver trouble read linux/Documentation/scsi/tmscsim.txt\n");
 };
 
 
diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
--- a/drivers/scsi/wd33c93.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/scsi/wd33c93.c	Sun Nov 17 20:30:15 2002
@@ -1853,7 +1853,6 @@
    printk("\n");
    printk("           Version %s - %s, Compiled %s at %s\n",
                WD33C93_VERSION,WD33C93_DATE,__DATE__,__TIME__);
-   MOD_INC_USE_COUNT;
 }
 
 
@@ -2031,7 +2030,6 @@
 #endif
 void wd33c93_release(void)
 {
-   MOD_DEC_USE_COUNT;
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/serial/Kconfig	Sun Nov 17 20:30:15 2002
@@ -317,6 +317,44 @@
 	  mouse on (PCI) UltraSPARC systems.  Say Y or M if you want to be able
 	  to these serial ports.
 
+config SERIAL_MUX
+	tristate "Serial MUX support"
+	depends on PARISC
+	default y
+	---help---
+	  Saying Y here will enable the hardware MUX serial driver for
+	  the Nova and K class systems.  The hardware MUX is not 8250/16550 
+	  compatible therefore the /dev/ttyB0 device is shared between the 
+	  Serial MUX and the PDC software console.  The following steps 
+	  need to be completed to use the Serial MUX:
+
+	    1. create the device entry (mknod /dev/ttyB0 c 11 0)
+	    2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
+	    3. Add device ttyB0 to /etc/securetty (if you want to log on as
+		 root on this console.)
+	    4. Change the kernel command console parameter to: console=ttyB0
+
+config SERIAL_MUX_CONSOLE
+        bool "Support for console on serial MUX"
+        depends on SERIAL_MUX
+        default y
+
+config PDC_CONSOLE
+	bool "PDC software console support"
+	depends on PARISC && !SERIAL_MUX
+	default n
+	help
+	  Saying Y here will enable the software based PDC console to be 
+	  used as the system console.  This is useful for machines in 
+	  which the hardware based console has not been written yet.  The
+	  following steps must be competed to use the PDC console:
+
+	    1. create the device entry (mknod /dev/ttyB0 c 11 0)
+	    2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
+	    3. Add device ttyB0 to /etc/securetty (if you want to log on as
+		 root on this console.)
+	    4. Change the kernel command console parameter to: console=ttyB0
+
 config SERIAL_SUNSAB
 	tristate "Sun Siemens SAB82532 serial support"
 	depends on (SPARC32 || SPARC64) && PCI
@@ -336,12 +374,12 @@
 
 config SERIAL_CORE
 	tristate
-	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m)
-	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART
+	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m)
+	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART
 
 config SERIAL_CORE_CONSOLE
 	bool
-	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE
+	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE
 	default y
 
 config SERIAL_68328
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	Sun Nov 17 20:30:14 2002
+++ b/drivers/serial/Makefile	Sun Nov 17 20:30:14 2002
@@ -24,6 +24,7 @@
 obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
 obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
 obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
+obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
 obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
diff -Nru a/drivers/serial/mux.c b/drivers/serial/mux.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/serial/mux.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,499 @@
+/*
+** mux.c:
+**	serial driver for the Mux console found in some PA-RISC servers.
+**
+**	(c) Copyright 2002 Ryan Bradetich
+**	(c) Copyright 2002 Hewlett-Packard Company
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This Driver currently only supports the console (port 0) on the MUX.
+** Additional work will be needed on this driver to enable the full
+** functionality of the MUX.
+**
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#define MUX_NR 1
+
+#define MUX_OFFSET 0x800
+#define MUX_LINE_OFFSET 0x80
+
+#define MUX_FIFO_SIZE 255
+#define MUX_MIN_FREE_SIZE 32
+
+#define MUX_FIFO_DRAIN_DELAY 1
+#define MUX_POLL_DELAY (30 * HZ / 1000) 
+
+#define IO_COMMAND_REG_OFFSET 0x30
+#define IO_STATUS_REG_OFFSET 0x34
+#define IO_DATA_REG_OFFSET 0x3c
+#define IO_DCOUNT_REG_OFFSET 0x40
+#define IO_UCOUNT_REG_OFFSET 0x44
+#define IO_FIFOS_REG_OFFSET 0x48
+
+#define MUX_EOFIFO(status) ((status & 0xF000) == 0xF000)
+#define MUX_STATUS(status) ((status & 0xF000) == 0x8000)
+#define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
+
+
+static struct uart_port mux_ports[MUX_NR];
+static struct timer_list mux_timer;
+
+#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET)
+#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET)
+
+/**
+ * mux_tx_empty - Check if the transmitter fifo is empty.
+ * @port: Ptr to the uart_port.
+ *
+ * This function test if the transmitter fifo for the port
+ * described by 'port' is empty.  If it is empty, this function
+ * should return TIOCSER_TEMT, otherwise return 0.
+ */
+static unsigned int mux_tx_empty(struct uart_port *port)
+{
+	unsigned int cnt = __raw_readl((unsigned long)port->membase 
+				+ IO_DCOUNT_REG_OFFSET);
+
+	return cnt ? 0 : TIOCSER_TEMT;
+} 
+
+/**
+ * mux_set_mctrl - Set the current state of the modem control inputs.
+ * @ports: Ptr to the uart_port.
+ * @mctrl: Modem control bits.
+ *
+ * The Serial MUX does not support CTS, DCD or DSR so this function
+ * is ignored.
+ */
+static void mux_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+/**
+ * mux_get_mctrl - Returns the current state of modem control inputs.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial MUX does not support CTS, DCD or DSR so these lines are
+ * treated as permanently active.
+ */
+static unsigned int mux_get_mctrl(struct uart_port *port)
+{ 
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/**
+ * mux_stop_tx - Stop transmitting characters.
+ * @port: Ptr to the uart_port.
+ * @tty_stop: tty layer issue this command?
+ *
+ * The Serial MUX does not support this function.
+ */
+static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+}
+
+/**
+ * mux_start_tx - Start transmitting characters.
+ * @port: Ptr to the uart_port.
+ * @tty_start: tty layer issue this command?
+ *
+ * The Serial Mux does not support this function.
+ */
+static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+}
+
+/**
+ * mux_stop_rx - Stop receiving characters.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial Mux does not support this function.
+ */
+static void mux_stop_rx(struct uart_port *port)
+{
+}
+
+/**
+ * mux_enable_ms - Enable modum status interrupts.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial Mux does not support this function.
+ */
+static void mux_enable_ms(struct uart_port *port)
+{
+}
+
+/**
+ * mux_break_ctl - Control the transmitssion of a break signal.
+ * @port: Ptr to the uart_port.
+ * @break_state: Raise/Lower the break signal.
+ *
+ * The Serial Mux does not support this function.
+ */
+static void mux_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+/**
+ * mux_write - Write chars to the mux fifo.
+ * @port: Ptr to the uart_port.
+ *
+ * This function writes all the data from the uart buffer to
+ * the mux fifo.
+ */
+static void mux_write(struct uart_port *port)
+{
+	int count;
+	struct circ_buf *xmit = &port->info->xmit;
+
+	if(port->x_char) {
+		UART_PUT_CHAR(port, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		mux_stop_tx(port, 0);
+		return;
+	}
+
+	count = (port->fifosize >> 1) - UART_GET_FIFO_CNT(port);
+	do {
+		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if(uart_circ_empty(xmit))
+			break;
+
+	} while(--count > 0);
+
+	if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		mux_stop_tx(port, 0);
+}
+
+/**
+ * mux_read - Read chars from the mux fifo.
+ * @port: Ptr to the uart_port.
+ *
+ * This reads all available data from the mux's fifo and pushes
+ * the data to the tty layer.
+ */
+static void mux_read(struct uart_port *port)
+{
+	int data;
+	__u32 start_count = port->icount.rx;
+	struct tty_struct *tty = port->info->tty;
+
+	while(1) {
+		data = __raw_readl((unsigned long)port->membase
+						+ IO_DATA_REG_OFFSET);
+
+		if (MUX_STATUS(data))
+			continue;
+
+		if (MUX_EOFIFO(data))
+			break;
+
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			continue;
+
+		*tty->flip.char_buf_ptr = data & 0xffu;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		port->icount.rx++;
+
+		if (MUX_BREAK(data)) {
+			port->icount.brk++;
+			if(uart_handle_break(port))
+				continue;
+		}
+
+		if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
+			continue;
+
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+	}
+	
+	if (start_count != port->icount.rx) {
+		tty_flip_buffer_push(tty);
+	}
+}
+
+/**
+ * mux_startup - Initialize the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Grab any resources needed for this port and start the
+ * mux timer.
+ */
+static int mux_startup(struct uart_port *port)
+{
+	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+	return 0;
+}
+
+/**
+ * mux_shutdown - Disable the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Release any resources needed for the port.
+ */
+static void mux_shutdown(struct uart_port *port)
+{
+}
+
+/**
+ * mux_change_speed - Chane port parameters.
+ * @port: Ptr to the uart_port.
+ * @cflag: character flags.
+ * @iflag: interrupt flags.
+ * @quot: 
+ *
+ * The Serial Mux does not support this function.
+ */
+static void
+mux_change_speed(struct uart_port *port, unsigned int cflag,
+			unsigned int iflag, unsigned int quot)
+{
+}
+
+/**
+ * mux_type - Describe the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Return a pointer to a string constant describing the
+ * specified port.
+ */
+static const char *mux_type(struct uart_port *port)
+{
+	return "Mux";
+}
+
+/**
+ * release_port - Release memory and IO regions.
+ * @port: Ptr to the uart_port.
+ * 
+ * Release any memory and IO region resources currently in use by
+ * the port.
+ */
+static void mux_release_port(struct uart_port *port)
+{
+}
+
+/**
+ * mux_request_port - Request memory and IO regions.
+ * @port: Ptr to the uart_port.
+ *
+ * Request any memory and IO region resources required by the port.
+ * If any fail, no resources should be registered when this function
+ * returns, and it should return -EBUSY on failure.
+ */
+static int mux_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/**
+ * mux_config_port - Perform port autoconfiguration.
+ * @port: Ptr to the uart_port.
+ * @type: Bitmask of required configurations.
+ *
+ * Perform any autoconfiguration steps for the port.  This functino is
+ * called if the UPF_BOOT_AUTOCONF flag is specified for the port.
+ * [Note: This is required for now because of a bug in the Serial core.
+ *  rmk has already submitted a patch to linus, should be available for
+ *  2.5.47.]
+ */
+static void mux_config_port(struct uart_port *port, int type)
+{
+	port->type = PORT_MUX;
+}
+
+/**
+ * mux_verify_port - Verify the port information.
+ * @port: Ptr to the uart_port.
+ * @ser: Ptr to the serial information.
+ *
+ * Verify the new serial port information contained within serinfo is
+ * suitable for this port type.
+ */
+static int mux_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if(port->membase == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * mux_drv_poll - Mux poll function.   
+ * @unused: Unused variable
+ *
+ * This function periodically polls the Serial MUX to check for new data.
+ */
+static void mux_poll(unsigned long unused)
+{  
+	struct uart_port *port = &mux_ports[0];
+
+	mux_read(port);
+	mux_write(port);
+	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+}
+
+
+#ifdef CONFIG_SERIAL_MUX_CONSOLE
+static struct console mux_console = {
+	.name =		"ttyB",
+	.flags =	CON_PRINTBUFFER,
+	.index =	0,
+};
+#define MUX_CONSOLE	&mux_console
+#else
+#define MUX_CONSOLE	NULL
+#endif
+
+static struct uart_ops mux_pops = {
+	.tx_empty =		mux_tx_empty,
+	.set_mctrl =		mux_set_mctrl,
+	.get_mctrl =		mux_get_mctrl,
+	.stop_tx =		mux_stop_tx,
+	.start_tx =		mux_start_tx,
+	.stop_rx =		mux_stop_rx,
+	.enable_ms =		mux_enable_ms,
+	.break_ctl =		mux_break_ctl,
+	.startup =		mux_startup,
+	.shutdown =		mux_shutdown,
+	.change_speed =		mux_change_speed,
+	.type =			mux_type,
+	.release_port =		mux_release_port,
+	.request_port =		mux_request_port,
+	.config_port =		mux_config_port,
+	.verify_port =		mux_verify_port,
+};
+
+static struct uart_driver mux_reg = {
+	.owner =		THIS_MODULE,
+	.driver_name =		"ttyB",
+#ifdef CONFIG_DEVFS_FS
+	.dev_name =		"ttyB%d",
+#else
+	.dev_name =		"ttyB%d",
+#endif
+	.major =		MUX_MAJOR,
+	.minor =		0,
+	.nr =			MUX_NR, 
+	.cons =			MUX_CONSOLE,
+};
+
+/**
+ * mux_probe - Determine if the Serial Mux should claim this device.
+ * @dev: The parisc device.
+ *
+ * Deterimine if the Serial Mux should claim this chip (return 0)
+ * or not (return 1).
+ */
+static int __init mux_probe(struct parisc_device *dev)
+{
+	int i, ret;
+	struct uart_port *port = &mux_ports[0];
+
+	init_timer(&mux_timer);
+	mux_timer.function = mux_poll;
+
+	printk(KERN_INFO "Serial mux driver Revision: 0.1\n");
+
+	ret = uart_register_driver(&mux_reg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < MUX_NR; i++) {
+		port = &mux_ports[i];
+
+		port->iobase	= 0;
+		port->mapbase	= dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
+		port->membase	= ioremap(port->mapbase, MUX_LINE_OFFSET);
+		port->iotype	= SERIAL_IO_MEM;
+		port->type	= PORT_MUX;
+		port->irq	= SERIAL_IRQ_NONE;
+		port->uartclk	= 0;
+		port->fifosize	= MUX_FIFO_SIZE;
+		port->ops	= &mux_pops;
+		port->flags	= UPF_BOOT_AUTOCONF;
+		port->line	= 0;
+
+		uart_add_one_port(&mux_reg, port);
+	}
+
+	return 0;
+}
+
+static struct parisc_device_id mux_tbl[] = {
+	{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, mux_tbl);
+
+static struct parisc_driver mux_driver = {
+	.name     = "Serial MUX driver",
+	.id_table = mux_tbl,
+	.probe    = mux_probe,
+};
+
+/**
+ * mux_init - Serial MUX initalization procedure.
+ *
+ * Register the Serial MUX driver.
+ */
+static int __init mux_init(void)
+{
+	return register_parisc_driver(&mux_driver);
+}
+
+/**
+ * mux_exit - Serial MUX cleanup procedure.
+ *
+ * Unregister the Serial MUX driver from the tty layer.
+ */
+static void __exit mux_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MUX_NR; i++) {
+		uart_remove_one_port(&mux_reg, &mux_ports[i]);
+	}
+
+	uart_unregister_driver(&mux_reg);
+}
+
+module_init(mux_init);
+module_exit(mux_exit);
+
+MODULE_AUTHOR("Ryan Bradetich");
+MODULE_DESCRIPTION("Serial MUX driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/Makefile	Sun Nov 17 20:30:15 2002
@@ -8,13 +8,8 @@
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= host/
 obj-$(CONFIG_USB_OHCI_HCD)	+= host/
-obj-$(CONFIG_USB_OHCI)		+= host/
-obj-$(CONFIG_USB_OHCI_SA1111)	+= host/
-obj-$(CONFIG_USB_SL811HS)	+= host/
-obj-$(CONFIG_USB_UHCI_ALT)	+= host/
-obj-$(CONFIG_USB_UHCI_HCD_ALT)	+= host/
 obj-$(CONFIG_USB_UHCI_HCD)	+= host/
-obj-$(CONFIG_USB_UHCI)		+= host/
+obj-$(CONFIG_USB_SL811HS)	+= host/
 
 obj-$(CONFIG_USB_ACM)		+= class/
 obj-$(CONFIG_USB_AUDIO)		+= class/
diff -Nru a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
--- a/drivers/usb/class/Kconfig	Sun Nov 17 20:30:02 2002
+++ b/drivers/usb/class/Kconfig	Sun Nov 17 20:30:02 2002
@@ -20,14 +20,16 @@
 	tristate "USB Bluetooth TTY support"
 	depends on USB
 	---help---
-	  Say Y here if you want to connect a USB Bluetooth device to your
-	  computer's USB port. You will need the Bluetooth stack (available
-	  at <http://developer.axis.com/software/index.shtml>) to fully use
-	  the device.
+	  This driver implements a nonstandard tty interface to a Bluetooth
+	  device that can be used only by specialized Bluetooth HCI software.
 
-	  This driver implements a tty inteface to a Bluetooth device.  If
-	  you want to use a socket based Bluetooth stack (like the BlueZ
-	  stack), do not use this driver.
+	  Say Y here if you want to use OpenBT Bluetooth stack (available
+	  at <http://developer.axis.com/software/index.shtml>), or other TTY
+	  based Bluetooth stacks, and want to connect a USB Bluetooth device
+	  to your computer's USB port.
+
+	  Do *not* enable this driver if you want to use generic Linux
+	  Bluetooth support.
 
 	  If in doubt, say N here.
 
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	Sun Nov 17 20:30:04 2002
+++ b/drivers/usb/class/usblp.c	Sun Nov 17 20:30:04 2002
@@ -1,9 +1,9 @@
 /*
- * usblp.c  Version 0.12
+ * usblp.c  Version 0.13
  *
  * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
- * Copyright (c) 2000 Randy Dunlap	<randy.dunlap@intel.com>
+ * Copyright (c) 2000 Randy Dunlap	<rddunlap@osdl.org>
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
  # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
@@ -25,6 +25,8 @@
  *	v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
  *	v0.11 - add proto_bias option (Pete Zaitcev)
  *	v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
+ *	v0.13 - alloc space for statusbuf (<status> not on stack);
+ *		use usb_buffer_alloc() for read buf & write buf;
  */
 
 /*
@@ -59,7 +61,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.12"
+#define DRIVER_VERSION "v0.13"
 #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
 #define DRIVER_DESC "USB Printer Device Class driver"
 
@@ -120,11 +122,19 @@
 #define USBLP_LAST_PROTOCOL	3
 #define USBLP_MAX_PROTOCOLS	(USBLP_LAST_PROTOCOL+1)
 
+/*
+ * some arbitrary status buffer size;
+ * need a status buffer that is allocated via kmalloc(), not on stack
+ */
+#define STATUS_BUF_SIZE		8
+
 struct usblp {
 	struct usb_device 	*dev;			/* USB device */
 	devfs_handle_t		devfs;			/* devfs device */
 	struct semaphore	sem;			/* locks this struct, especially "dev" */
-	char			*buf;		/* writeurb->transfer_buffer */
+	char			*writebuf;		/* write transfer_buffer */
+	char			*readbuf;		/* read transfer_buffer */
+	char			*statusbuf;		/* status transfer_buffer */
 	struct urb		*readurb, *writeurb;	/* The urbs */
 	wait_queue_head_t	wait;			/* Zzzzz ... */
 	int			readcount;		/* Counter for reads */
@@ -289,13 +299,14 @@
 	unsigned char status, newerr = 0;
 	int error;
 
-	error = usblp_read_status (usblp, &status);
+	error = usblp_read_status (usblp, usblp->statusbuf);
 	if (error < 0) {
 		err("usblp%d: error %d reading printer status",
 			usblp->minor, error);
 		return 0;
 	}
 
+	status = *usblp->statusbuf;
 	if (~status & LP_PERRORP) {
 		newerr = 3;
 		if (status & LP_POUTPA) newerr = 1;
@@ -375,8 +386,12 @@
 	usb_deregister_dev (1, usblp->minor);
 	info("usblp%d: removed", usblp->minor);
 
-	kfree (usblp->writeurb->transfer_buffer);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->writebuf, usblp->writeurb->transfer_dma);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->readbuf, usblp->writeurb->transfer_dma);
 	kfree (usblp->device_id_string);
+	kfree (usblp->statusbuf);
 	usb_free_urb(usblp->writeurb);
 	usb_free_urb(usblp->readurb);
 	kfree (usblp);
@@ -841,11 +856,27 @@
 		goto abort_minor;
 	}
 
-	/* Malloc write/read buffers in one chunk.  We somewhat wastefully
+	usblp->writebuf = usblp->readbuf = NULL;
+	usblp->writeurb->transfer_flags = URB_NO_DMA_MAP;
+	usblp->readurb->transfer_flags = URB_NO_DMA_MAP;
+	/* Malloc write & read buffers.  We somewhat wastefully
 	 * malloc both regardless of bidirectionality, because the
 	 * alternate setting can be changed later via an ioctl. */
-	if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
-		err("out of memory for buf");
+	if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
+				GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
+		err("out of memory for write buf");
+		goto abort_minor;
+	}
+	if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
+				GFP_KERNEL, &usblp->readurb->transfer_dma))) {
+		err("out of memory for read buf");
+		goto abort_minor;
+	}
+
+	/* Allocate buffer for printer status */
+	usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
+	if (!usblp->statusbuf) {
+		err("out of memory for statusbuf");
 		goto abort_minor;
 	}
 
@@ -900,10 +931,16 @@
 	usb_deregister_dev (1, usblp->minor);
 abort:
 	if (usblp) {
+		if (usblp->writebuf)
+			usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+				usblp->writebuf, usblp->writeurb->transfer_dma);
+		if (usblp->readbuf)
+			usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+				usblp->readbuf, usblp->writeurb->transfer_dma);
+		if (usblp->statusbuf) kfree(usblp->statusbuf);
+		if (usblp->device_id_string) kfree(usblp->device_id_string);
 		usb_free_urb(usblp->writeurb);
 		usb_free_urb(usblp->readurb);
-		if (usblp->buf) kfree(usblp->buf);
-		if (usblp->device_id_string) kfree(usblp->device_id_string);
 		kfree(usblp);
 	}
 	return -EIO;
@@ -1020,16 +1057,16 @@
 
 	usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
 		usb_sndbulkpipe(usblp->dev,
-		 usblp->protocol[protocol].epwrite->bEndpointAddress),
-		usblp->buf, 0,
+		  usblp->protocol[protocol].epwrite->bEndpointAddress),
+		usblp->writebuf, 0,
 		usblp_bulk_write, usblp);
 
 	usblp->bidir = (usblp->protocol[protocol].epread != 0);
 	if (usblp->bidir)
 		usb_fill_bulk_urb(usblp->readurb, usblp->dev,
 			usb_rcvbulkpipe(usblp->dev,
-			 usblp->protocol[protocol].epread->bEndpointAddress),
-			usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
+			  usblp->protocol[protocol].epread->bEndpointAddress),
+			usblp->readbuf, USBLP_BUF_SIZE,
 			usblp_bulk_read, usblp);
 
 	usblp->current_protocol = protocol;
diff -Nru a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c
--- a/drivers/usb/core/driverfs.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/usb/core/driverfs.c	Sun Nov 17 20:30:12 2002
@@ -148,23 +148,31 @@
 usb_descriptor_attr (bDeviceClass, "%02x\n")
 usb_descriptor_attr (bDeviceSubClass, "%02x\n")
 usb_descriptor_attr (bDeviceProtocol, "%02x\n")
+usb_descriptor_attr (bNumConfigurations, "%d\n")
 
 
 void usb_create_driverfs_dev_files (struct usb_device *udev)
 {
 	struct device *dev = &udev->dev;
 
+	/* current configuration's attributes */
 	device_create_file (dev, &dev_attr_bNumInterfaces);
 	device_create_file (dev, &dev_attr_bConfigurationValue);
 	device_create_file (dev, &dev_attr_bmAttributes);
 	device_create_file (dev, &dev_attr_bMaxPower);
+
+	/* device attributes */
 	device_create_file (dev, &dev_attr_idVendor);
 	device_create_file (dev, &dev_attr_idProduct);
 	device_create_file (dev, &dev_attr_bcdDevice);
 	device_create_file (dev, &dev_attr_bDeviceClass);
 	device_create_file (dev, &dev_attr_bDeviceSubClass);
 	device_create_file (dev, &dev_attr_bDeviceProtocol);
+	device_create_file (dev, &dev_attr_bNumConfigurations);
+
+	/* speed varies depending on how you connect the device */
 	device_create_file (dev, &dev_attr_speed);
+	// FIXME iff there are other speed configs, show how many
 
 	if (udev->descriptor.iManufacturer)
 		device_create_file (dev, &dev_attr_manufacturer);
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/core/hcd-pci.c	Sun Nov 17 20:30:14 2002
@@ -137,7 +137,8 @@
 	hcd->description = driver->description;
 	hcd->pdev = dev;
 	hcd->self.bus_name = dev->slot_name;
-	hcd->product_desc = dev->name;
+	hcd->product_desc = dev->dev.name;
+	hcd->controller = &dev->dev;
 
 	if ((retval = hcd_buffer_create (hcd)) != 0) {
 clean_3:
@@ -145,7 +146,7 @@
 		goto clean_2;
 	}
 
-	info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->name);
+	info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->dev.name);
 
 #ifndef __sparc__
 	sprintf (buf, "%d", dev->irq);
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/core/hcd.c	Sun Nov 17 20:30:14 2002
@@ -23,6 +23,11 @@
  */
 
 #include <linux/config.h>
+
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#endif
+
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -32,13 +37,6 @@
 #include <linux/pci.h>			/* for hcd->pdev and dma addressing */
 #include <asm/byteorder.h>
 
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
 #include <linux/usb.h>
 #include "hcd.h"
 
@@ -1090,6 +1088,7 @@
 {
 	struct hcd_dev			*dev;
 	struct usb_hcd			*hcd = 0;
+	struct device			*sys = 0;
 	unsigned long			flags;
 	struct completion_splice	splice;
 	int				retval;
@@ -1110,38 +1109,31 @@
 	 */
 	spin_lock_irqsave (&urb->lock, flags);
 	spin_lock (&hcd_data_lock);
-	if (!urb->hcpriv || urb->transfer_flags & URB_TIMEOUT_KILLED) {
-		retval = -EINVAL;
-		goto done;
-	}
 
 	if (!urb->dev || !urb->dev->bus) {
 		retval = -ENODEV;
 		goto done;
 	}
 
-	/* giveback clears dev; non-null means it's linked at this level */
 	dev = urb->dev->hcpriv;
+	sys = &urb->dev->dev;
 	hcd = urb->dev->bus->hcpriv;
 	if (!dev || !hcd) {
 		retval = -ENODEV;
 		goto done;
 	}
 
-	/* Except for interrupt transfers, any status except -EINPROGRESS
-	 * means the HCD already started to unlink this URB from the hardware.
-	 * So there's no more work to do.
-	 *
-	 * For interrupt transfers, this is the only way to trigger unlinking
-	 * from the hardware.  Since we (currently) overload urb->status to
-	 * tell the driver to unlink, error status might get clobbered ...
-	 * unless that transfer hasn't yet restarted.  One such case is when
-	 * the URB gets unlinked from its completion handler.
+	if (!urb->hcpriv) {
+		retval = -EINVAL;
+		goto done;
+	}
+
+	/* Any status except -EINPROGRESS means something already started to
+	 * unlink this URB from the hardware.  So there's no more work to do.
 	 *
-	 * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
+	 * FIXME use better explicit urb state
 	 */
-	if (urb->status != -EINPROGRESS
-			&& usb_pipetype (urb->pipe) != PIPE_INTERRUPT) {
+	if (urb->status != -EINPROGRESS) {
 		retval = -EINVAL;
 		goto done;
 	}
@@ -1150,9 +1142,7 @@
 	 * lower level hcd code is always async, locking on urb->status
 	 * updates; an intercepted completion unblocks us.
 	 */
-	if ((urb->transfer_flags & URB_TIMEOUT_KILLED))
-		urb->status = -ETIMEDOUT;
-	else if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
+	if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
 		if (in_interrupt ()) {
 			dbg ("non-async unlink in_interrupt");
 			retval = -EWOULDBLOCK;
@@ -1177,29 +1167,34 @@
 		retval = 0;
 	} else {
 		retval = hcd->driver->urb_dequeue (hcd, urb);
-// FIXME:  if retval and we tried to splice, whoa!!
-if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
+
+		/* hcds shouldn't really fail these calls, but... */
+		if (retval) {
+			dev_dbg (*sys, "dequeue %p --> %d\n", urb, retval);
+			if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
+				spin_lock_irqsave (&urb->lock, flags);
+				urb->complete = splice.complete;
+				urb->context = splice.context;
+				spin_unlock_irqrestore (&urb->lock, flags);
+			}
+			goto bye;
+		}
 	}
 
     	/* block till giveback, if needed */
-	if (!(urb->transfer_flags & (URB_ASYNC_UNLINK|URB_TIMEOUT_KILLED))
-			&& HCD_IS_RUNNING (hcd->state)
-			&& !retval) {
-		dbg ("%s: wait for giveback urb %p",
-			hcd->self.bus_name, urb);
-		wait_for_completion (&splice.done);
-	} else if ((urb->transfer_flags & URB_ASYNC_UNLINK) && retval == 0) {
+	if (urb->transfer_flags & URB_ASYNC_UNLINK)
 		return -EINPROGRESS;
-	}
-	goto bye;
+
+	dev_dbg (*sys, "wait for giveback urb %p\n", urb);
+	wait_for_completion (&splice.done);
+	return 0;
+
 done:
 	spin_unlock (&hcd_data_lock);
 	spin_unlock_irqrestore (&urb->lock, flags);
 bye:
-	if (retval)
-		dbg ("%s: hcd_unlink_urb fail %d",
-		    hcd ? hcd->self.bus_name : "(no bus?)",
-		    retval);
+	if (retval && sys)
+		dev_dbg (*sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
 	return retval;
 }
 
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Sun Nov 17 20:30:12 2002
+++ b/drivers/usb/core/hcd.h	Sun Nov 17 20:30:12 2002
@@ -74,10 +74,10 @@
 	struct hc_driver	*driver;	/* hw-specific hooks */
 	int			irq;		/* irq allocated */
 	void			*regs;		/* device memory/io */
+	struct device		*controller;	/* handle to hardware */
 
 	/* a few non-PCI controllers exist, mostly for OHCI */
 	struct pci_dev		*pdev;		/* pci is typical */
-	struct device		*parent;	/* parent device driver */
 #ifdef	CONFIG_PCI
 	int			region;		/* pci region for regs */
 	u32			pci_state [16];	/* for PM state save */
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c	Sun Nov 17 20:30:02 2002
+++ b/drivers/usb/core/inode.c	Sun Nov 17 20:30:02 2002
@@ -30,6 +30,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/core/usb.c	Sun Nov 17 20:30:14 2002
@@ -67,7 +67,7 @@
 }
 
 static struct device_driver usb_generic_driver = {
-	.name =	"generic",
+	.name =	"usb",
 	.bus = &usb_bus_type,
 	.probe = generic_probe,
 	.remove = generic_remove,
@@ -514,17 +514,10 @@
  * or other modules, configure the device, and more.  Drivers can provide
  * a MODULE_DEVICE_TABLE to help with module loading subtasks.
  *
- * Some synchronization is important: removes can't start processing
- * before the add-device processing completes, and vice versa.  That keeps
- * a stack of USB-related identifiers stable while they're in use.  If we
- * know that agents won't complete after they return (such as by forking
- * a process that completes later), it's enough to just waitpid() for the
- * agent -- as is currently done.
- *
- * The reason: we know we're called either from khubd (the typical case)
- * or from root hub initialization (init, kapmd, modprobe, etc).  In both
- * cases, we know no other thread can recycle our address, since we must
- * already have been serialized enough to prevent that.
+ * We're called either from khubd (the typical case) or from root hub
+ * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
+ * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
+ * device (and this configuration!) are still present.
  */
 static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 			char *buffer, int buffer_size)
@@ -579,7 +572,7 @@
 	scratch += length;
 #endif
 
-	/* per-device configuration hacks are common */
+	/* per-device configurations are common */
 	envp [i++] = scratch;
 	length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x",
 			    usb_dev->descriptor.idVendor,
@@ -604,10 +597,9 @@
 	if (usb_dev->descriptor.bDeviceClass == 0) {
 		int alt = intf->act_altsetting;
 
-		/* a simple/common case: one config, one interface, one driver
-		 * with current altsetting being a reasonable setting.
-		 * everything needs a smart agent and usbfs; or can rely on
-		 * device-specific binding policies.
+		/* 2.4 only exposed interface zero.  in 2.5, hotplug
+		 * agents are called for all interfaces, and can use
+		 * $DEVPATH/bInterfaceNumber if necessary.
 		 */
 		envp [i++] = scratch;
 		length += snprintf (scratch, buffer_size - length,
@@ -949,6 +941,24 @@
 	int i;
 	int j;
 
+	/*
+	 * Set the driver for the usb device to point to the "generic" driver.
+	 * This prevents the main usb device from being sent to the usb bus
+	 * probe function.  Yes, it's a hack, but a nice one :)
+	 *
+	 * Do it asap, so more driver model stuff (like the device.h message
+	 * utilities) can be used in hcd submit/unlink code paths.
+	 */
+	usb_generic_driver.bus = &usb_bus_type;
+	dev->dev.parent = parent;
+	dev->dev.driver = &usb_generic_driver;
+	dev->dev.bus = &usb_bus_type;
+	if (dev->dev.bus_id[0] == 0)
+		sprintf (&dev->dev.bus_id[0], "%d-%s",
+			 dev->bus->busnum, dev->devpath);
+
+	/* USB device state == default ... it's not usable yet */
+
 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
 	 * it's fixed size except for full speed devices.
 	 */
@@ -1010,6 +1020,8 @@
 		dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
 	}
 
+	/* USB device state == addressed ... still not usable */
+
 	err = usb_get_device_descriptor(dev);
 	if (err < (signed)sizeof(dev->descriptor)) {
 		if (err < 0)
@@ -1042,6 +1054,8 @@
 		return 1;
 	}
 
+	/* USB device state == configured ... tell the world! */
+
 	dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",
 		dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
 	set_device_description (dev);
@@ -1051,23 +1065,10 @@
 		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
-	/*
-	 * Set the driver for the usb device to point to the "generic" driver.
-	 * This prevents the main usb device from being sent to the usb bus
-	 * probe function.  Yes, it's a hack, but a nice one :)
-	 */
-	usb_generic_driver.bus = &usb_bus_type;
-	dev->dev.parent = parent;
-	dev->dev.driver = &usb_generic_driver;
-	dev->dev.bus = &usb_bus_type;
-	if (dev->dev.bus_id[0] == 0)
-		sprintf (&dev->dev.bus_id[0], "%d-%s",
-			 dev->bus->busnum, dev->devpath);
+	/* put into sysfs, with device and config specific files */
 	err = device_register (&dev->dev);
 	if (err)
 		return err;
-
-	/* add the USB device specific driverfs files */
 	usb_create_driverfs_dev_files (dev);
 
 	/* Register all of the interfaces for this device with the driver core.
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/Kconfig	Sun Nov 17 20:30:15 2002
@@ -49,7 +49,7 @@
 	  The module will be called ohci-hcd.o. If you want to compile it
 	  as a module, say M here and read <file:Documentation/modules.txt>.
 
-config USB_UHCI_HCD_ALT
+config USB_UHCI_HCD
 	tristate "UHCI HCD (most Intel and VIA) support"
 	depends on USB
 	---help---
diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
--- a/drivers/usb/host/Makefile	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/Makefile	Sun Nov 17 20:30:15 2002
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
-obj-$(CONFIG_USB_UHCI_HCD_ALT)	+= uhci-hcd.o
+obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
 
 obj-$(CONFIG_USB_SL811HS)	+= hc_sl811.o
 
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ehci-dbg.c	Sun Nov 17 20:30:15 2002
@@ -272,6 +272,7 @@
 static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
 {
 	u32			scratch;
+	u32			hw_curr;
 	struct list_head	*entry;
 	struct ehci_qtd		*td;
 	unsigned		temp;
@@ -279,20 +280,22 @@
 	char			*next = *nextp;
 
 	scratch = cpu_to_le32p (&qh->hw_info1);
-	temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x",
+	hw_curr = cpu_to_le32p (&qh->hw_current);
+	temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x %08x)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
 			(scratch >> 8) & 0x000f,
-			scratch, cpu_to_le32p (&qh->hw_info2));
+			scratch, cpu_to_le32p (&qh->hw_info2),
+			hw_curr, cpu_to_le32p (&qh->hw_token));
 	size -= temp;
 	next += temp;
 
 	list_for_each (entry, &qh->qtd_list) {
-		td = list_entry (entry, struct ehci_qtd,
-				qtd_list);
+		td = list_entry (entry, struct ehci_qtd, qtd_list);
 		scratch = cpu_to_le32p (&td->hw_token);
 		temp = snprintf (next, size,
-				"\n\ttd/%p %s len=%d %08x urb %p",
+				"\n\t%std/%p %s len=%d %08x urb %p",
+				(hw_curr == td->qtd_dma) ? "*" : "",
 				td, ({ char *tmp;
 				 switch ((scratch>>8)&0x03) {
 				 case 0: tmp = "out"; break;
@@ -552,8 +555,8 @@
 	size -= temp;
 	next += temp;
 
-	temp = snprintf (next, size, "complete %ld unlink %ld qpatch %ld\n",
-		ehci->stats.complete, ehci->stats.unlink, ehci->stats.qpatch);
+	temp = snprintf (next, size, "complete %ld unlink %ld\n",
+		ehci->stats.complete, ehci->stats.unlink);
 	size -= temp;
 	next += temp;
 #endif
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/host/ehci-hcd.c	Sun Nov 17 20:30:14 2002
@@ -494,8 +494,8 @@
 #ifdef	EHCI_STATS
 	dbg ("irq normal %ld err %ld reclaim %ld",
 		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
-	dbg ("complete %ld unlink %ld qpatch %ld",
-		ehci->stats.complete, ehci->stats.unlink, ehci->stats.qpatch);
+	dbg ("complete %ld unlink %ld",
+		ehci->stats.complete, ehci->stats.unlink);
 #endif
 
 	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
diff -Nru a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
--- a/drivers/usb/host/ehci-mem.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ehci-mem.c	Sun Nov 17 20:30:15 2002
@@ -58,19 +58,23 @@
 
 /* Allocate the key transfer structures from the previously allocated pool */
 
+static void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
+{
+	memset (qtd, 0, sizeof *qtd);
+	qtd->qtd_dma = dma;
+	qtd->hw_next = EHCI_LIST_END;
+	qtd->hw_alt_next = EHCI_LIST_END;
+	INIT_LIST_HEAD (&qtd->qtd_list);
+}
+
 static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
 {
 	struct ehci_qtd		*qtd;
 	dma_addr_t		dma;
 
 	qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
-	if (qtd != 0) {
-		memset (qtd, 0, sizeof *qtd);
-		qtd->qtd_dma = dma;
-		qtd->hw_next = EHCI_LIST_END;
-		qtd->hw_alt_next = EHCI_LIST_END;
-		INIT_LIST_HEAD (&qtd->qtd_list);
-	}
+	if (qtd != 0)
+		ehci_qtd_init (qtd, dma);
 	return qtd;
 }
 
@@ -87,12 +91,21 @@
 
 	qh = (struct ehci_qh *)
 		pci_pool_alloc (ehci->qh_pool, flags, &dma);
-	if (qh) {
-		memset (qh, 0, sizeof *qh);
-		atomic_set (&qh->refcount, 1);
-		qh->qh_dma = dma;
-		// INIT_LIST_HEAD (&qh->qh_list);
-		INIT_LIST_HEAD (&qh->qtd_list);
+	if (!qh)
+		return qh;
+
+	memset (qh, 0, sizeof *qh);
+	atomic_set (&qh->refcount, 1);
+	qh->qh_dma = dma;
+	// INIT_LIST_HEAD (&qh->qh_list);
+	INIT_LIST_HEAD (&qh->qtd_list);
+
+	/* dummy td enables safe urb queuing */
+	qh->dummy = ehci_qtd_alloc (ehci, flags);
+	if (qh->dummy == 0) {
+		dbg ("no dummy td");
+		pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+		qh = 0;
 	}
 	return qh;
 }
@@ -115,6 +128,8 @@
 		dbg ("unused qh not empty!");
 		BUG ();
 	}
+	if (qh->dummy)
+		ehci_qtd_free (ehci, qh->dummy);
 	pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
 }
 
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ehci-q.c	Sun Nov 17 20:30:15 2002
@@ -85,7 +85,7 @@
 
 /* update halted (but potentially linked) qh */
 
-static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
+static void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
 {
 	qh->hw_current = 0;
 	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
@@ -221,17 +221,6 @@
 		struct urb	*urb = qtd->urb;
 		u32		token = 0;
 
-		/* hc's on-chip qh overlay cache can overwrite our idea of
-		 * next qtd ptrs, if we appended a qtd while the queue was
-		 * advancing.  (because we don't use dummy qtds.)
-		 */
-		if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current
-				&& qtd->hw_next != qh->hw_qtd_next) {
-			qh->hw_alt_next = qtd->hw_alt_next;
-			qh->hw_qtd_next = qtd->hw_next;
-			COUNT (ehci->stats.qpatch);
-		}
-
 		/* clean up any state from previous QTD ...*/
 		if (last) {
 			if (likely (last->urb != urb)) {
@@ -495,8 +484,7 @@
 	}
 
 	/* by default, enable interrupt on urb completion */
-// ... do it always, unless we switch over to dummy qtds
-//	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
+	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
 		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
 	return head;
 
@@ -661,8 +649,15 @@
 
 	/* initialize sw and hw queues with these qtds */
 	if (!list_empty (qtd_list)) {
+		struct ehci_qtd		*qtd;
+
+		/* hc's list view ends with dummy td; we might update it */
+		qtd = list_entry (qtd_list->prev, struct ehci_qtd, qtd_list);
+		qtd->hw_next = QTD_NEXT (qh->dummy->qtd_dma);
+
 		list_splice (qtd_list, &qh->qtd_list);
-		qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list));
+		qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
+		qh_update (qh, qtd);
 	} else {
 		qh->hw_qtd_next = qh->hw_alt_next = EHCI_LIST_END;
 	}
@@ -767,39 +762,48 @@
 
 		/* append to tds already queued to this qh? */
 		if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
-			struct ehci_qtd		*last_qtd;
-			u32			hw_next;
+			struct ehci_qtd		*dummy;
+			dma_addr_t		dma;
+			u32			token;
+
+			/* to avoid racing the HC, use the dummy td instead of
+			 * the first td of our list (becomes new dummy).  both
+			 * tds stay deactivated until we're done, when the
+			 * HC is allowed to fetch the old dummy (4.10.2).
+			 */
+			token = qtd->hw_token;
+			qtd->hw_token = 0;
+			dummy = qh->dummy;
+			// dbg ("swap td %p with dummy %p", qtd, dummy);
+
+			dma = dummy->qtd_dma;
+			*dummy = *qtd;
+			dummy->qtd_dma = dma;
+			list_del (&qtd->qtd_list);
+			list_add (&dummy->qtd_list, qtd_list);
 
-			/* update the last qtd's "next" pointer */
-			// dbg_qh ("non-empty qh", ehci, qh);
-			last_qtd = list_entry (qh->qtd_list.prev,
-					struct ehci_qtd, qtd_list);
-			hw_next = QTD_NEXT (qtd->qtd_dma);
-			last_qtd->hw_next = hw_next;
+			ehci_qtd_init (qtd, qtd->qtd_dma);
+			qh->dummy = qtd;
 
-			/* previous urb allows short rx? maybe optimize. */
-			if (!(last_qtd->urb->transfer_flags & URB_SHORT_NOT_OK)
-					&& (epnum & 0x10)) {
-				// only the last QTD for now
-				last_qtd->hw_alt_next = hw_next;
-			}
+			/* hc must see the new dummy at list end */
+			qtd = list_entry (qh->qtd_list.prev,
+					struct ehci_qtd, qtd_list);
+			qtd->hw_next = QTD_NEXT (dma);
 
-			/* qh_completions() may need to patch the qh overlay if
-			 * the hc was advancing this queue while we appended.
-			 * we know it can: last_qtd->hw_token has IOC set.
-			 *
-			 * or:  use a dummy td (so the overlay gets the next td
-			 * only when we set its active bit); fewer irqs.
-			 */
+			/* let the hc process these next qtds */
 			wmb ();
+			dummy->hw_token = token;
 
 		/* no URB queued */
 		} else {
-			// dbg_qh ("empty qh", ehci, qh);
+			struct ehci_qtd		*last_qtd;
 
-			/* NOTE: we already canceled any queued URBs
-			 * when the endpoint halted.
-			 */
+			/* make sure hc sees current dummy at the end */
+			last_qtd = list_entry (qtd_list->prev,
+					struct ehci_qtd, qtd_list);
+			last_qtd->hw_next = QTD_NEXT (qh->dummy->qtd_dma);
+
+			// dbg_qh ("empty qh", ehci, qh);
 
 			/* usb_clear_halt() means qh data toggle gets reset */
 			if (unlikely (!usb_gettoggle (urb->dev,
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ehci.h	Sun Nov 17 20:30:15 2002
@@ -31,11 +31,6 @@
 	/* termination of urbs from core */
 	unsigned long		complete;
 	unsigned long		unlink;
-
-	/* qhs patched to recover from td queueing race
-	 * (can avoid by using 'dummy td', allowing fewer irqs)
-	 */
-	unsigned long		qpatch;
 };
 
 /* ehci_hcd->lock guards shared data against other CPUs:
@@ -311,6 +306,7 @@
 	dma_addr_t		qh_dma;		/* address of qh */
 	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
 	struct list_head	qtd_list;	/* sw qtd list */
+	struct ehci_qtd		*dummy;
 
 	atomic_t		refcount;
 
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ohci-dbg.c	Sun Nov 17 20:30:15 2002
@@ -24,7 +24,8 @@
 /* debug| print the main components of an URB     
  * small: 0) header + data packets 1) just header
  */
-static void urb_print (struct urb * urb, char * str, int small)
+static void __attribute__((unused))
+urb_print (struct urb * urb, char * str, int small)
 {
 	unsigned int pipe= urb->pipe;
 	
@@ -204,10 +205,6 @@
 
 	// dumps some of the state we know about
 	ohci_dump_status (controller);
-#ifdef OHCI_VERBOSE_DEBUG
-	if (verbose)
-		ohci_dump_periodic (controller, "hcca");
-#endif
 	if (controller->hcca)
 		dbg ("hcca frame #%04x", controller->hcca->frame_no);
 	ohci_dump_roothub (controller, 1);
@@ -510,16 +507,16 @@
 
 static inline void create_debug_files (struct ohci_hcd *bus)
 {
-	device_create_file (bus->hcd.parent, &dev_attr_async);
-	device_create_file (bus->hcd.parent, &dev_attr_periodic);
+	device_create_file (bus->hcd.controller, &dev_attr_async);
+	device_create_file (bus->hcd.controller, &dev_attr_periodic);
 	// registers
 	dbg ("%s: created debug files", bus->hcd.self.bus_name);
 }
 
 static inline void remove_debug_files (struct ohci_hcd *bus)
 {
-	device_remove_file (bus->hcd.parent, &dev_attr_async);
-	device_remove_file (bus->hcd.parent, &dev_attr_periodic);
+	device_remove_file (bus->hcd.controller, &dev_attr_async);
+	device_remove_file (bus->hcd.controller, &dev_attr_periodic);
 }
 
 #else /* empty stubs for creating those files */
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Sun Nov 17 20:30:03 2002
+++ b/drivers/usb/host/ohci-hcd.c	Sun Nov 17 20:30:03 2002
@@ -271,7 +271,7 @@
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	unsigned long		flags;
 	
-#ifdef DEBUG
+#ifdef OHCI_VERBOSE_DEBUG
 	urb_print (urb, "UNLINK", 1);
 #endif		  
 
@@ -514,7 +514,7 @@
 
 	usb_connect (udev);
 	udev->speed = USB_SPEED_FULL;
-	if (usb_register_root_hub (udev, ohci->parent_dev) != 0) {
+	if (usb_register_root_hub (udev, ohci->hcd.controller) != 0) {
 		usb_free_dev (udev);
 		ohci->hcd.self.root_hub = NULL;
 		disable (ohci);
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ohci-pci.c	Sun Nov 17 20:30:15 2002
@@ -80,8 +80,6 @@
 	}
 	ohci->regs = hcd->regs;
 
-	ohci->parent_dev = &ohci->hcd.pdev->dev;
-
 	if (hc_reset (ohci) < 0) {
 		ohci_stop (hcd);
 		return -ENODEV;
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/host/ohci-q.c	Sun Nov 17 20:30:15 2002
@@ -110,10 +110,12 @@
 {
 	unsigned	i;
 
+#ifdef OHCI_VERBOSE_DEBUG
 	dbg ("%s: link %sed %p branch %d [%dus.], interval %d",
 		ohci->hcd.self.bus_name,
 		(ed->hwINFO & ED_ISO) ? "iso " : "",
 		ed, ed->branch, ed->load, ed->interval);
+#endif
 
 	for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
 		struct ed	**prev = &ohci->periodic [i];
@@ -244,10 +246,12 @@
 	}	
 	ohci->hcd.self.bandwidth_allocated -= ed->load / ed->interval;
 
+#ifdef OHCI_VERBOSE_DEBUG
 	dbg ("%s: unlink %sed %p branch %d [%dus.], interval %d",
 		ohci->hcd.self.bus_name,
 		(ed->hwINFO & ED_ISO) ? "iso " : "",
 		ed, ed->branch, ed->load, ed->interval);
+#endif
 }
 
 /* unlink an ed from one of the HC chains. 
@@ -265,6 +269,9 @@
 			if (!ed->hwNextED) {
 				ohci->hc_control &= ~OHCI_CTRL_CLE;
 				writel (ohci->hc_control, &ohci->regs->control);
+				writel (0, &ohci->regs->ed_controlcurrent);
+				// post those pci writes
+				(void) readl (&ohci->regs->control);
 			}
 			writel (le32_to_cpup (&ed->hwNextED),
 				&ohci->regs->ed_controlhead);
@@ -286,6 +293,9 @@
 			if (!ed->hwNextED) {
 				ohci->hc_control &= ~OHCI_CTRL_BLE;
 				writel (ohci->hc_control, &ohci->regs->control);
+				writel (0, &ohci->regs->ed_bulkcurrent);
+				// post those pci writes
+				(void) readl (&ohci->regs->control);
 			}
 			writel (le32_to_cpup (&ed->hwNextED),
 				&ohci->regs->ed_bulkhead);
@@ -315,8 +325,12 @@
 	 * involves not marking it ED_IDLE till INTR_SF; we always do that
 	 * if td_list isn't empty.  Otherwise the race is small; but ...
 	 */
-	if (ed->state == ED_OPER)
+	if (ed->state == ED_OPER) {
 		ed->state = ED_IDLE;
+		ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE);
+		ed->hwHeadP &= ~ED_H;
+		wmb ();
+	}
 }
 
 
@@ -404,7 +418,6 @@
 			}
 		}
 		ed->hwINFO = info;
-
 	}
 
 done:
@@ -767,6 +780,8 @@
 		next->next_dl_td = rev;	
 		rev = next;
 
+		if (ed->hwTailP == cpu_to_le32 (next->td_dma))
+			ed->hwTailP = next->hwNextTD;
 		ed->hwHeadP = next->hwNextTD | toggle;
 	}
 
@@ -881,8 +896,13 @@
 				continue;
 			}
 
-			/* patch pointer hc uses */
-			savebits = *prev & cpu_to_le32 (TD_MASK);
+			/* patch pointers hc uses ... tail, if we're removing
+			 * an otherwise active td, and whatever td pointer
+			 * points to this td
+			 */
+			if (ed->hwTailP == cpu_to_le32 (td->td_dma))
+				ed->hwTailP = td->hwNextTD;
+			savebits = *prev & ~cpu_to_le32 (TD_MASK);
 			*prev = td->hwNextTD | savebits;
 
 			/* HC may have partly processed this TD */
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/host/ohci-sa1111.c	Sun Nov 17 20:30:14 2002
@@ -176,7 +176,7 @@
 	hcd->irq = dev->irq[1];
 	hcd->regs = dev->mapbase;
 	hcd->pdev = SA1111_FAKE_PCIDEV;
-	hcd->parent = &dev->dev;
+	hcd->controller = &dev->dev;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
@@ -291,8 +291,6 @@
 		return ret;
 	}
 	ohci->regs = hcd->regs;
-
-	ohci->parent_dev = hcd->parent;
 
 	if (hc_reset (ohci) < 0) {
 		ohci_stop (hcd);
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	Sun Nov 17 20:30:16 2002
+++ b/drivers/usb/host/ohci.h	Sun Nov 17 20:30:16 2002
@@ -349,11 +349,6 @@
 struct ohci_hcd {
 	spinlock_t		lock;
 
-        /*
-	 * parent device
-	 */
-        struct device		*parent_dev;
-
 	/*
 	 * I/O memory used to communicate with the HC (dma-consistent)
 	 */
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/usb/image/scanner.c	Sun Nov 17 20:30:12 2002
@@ -403,8 +403,6 @@
 
 	int err=0;
 
-	MOD_INC_USE_COUNT;
-
 	down(&scn_mutex);
 
 	scn_minor = USB_SCN_MINOR(inode);
@@ -413,7 +411,6 @@
 
 	if (!p_scn_table[scn_minor]) {
 		up(&scn_mutex);
-		MOD_DEC_USE_COUNT;
 		err("open_scanner(%d): Unable to access minor data", scn_minor);
 		return -ENODEV;
 	}
@@ -455,9 +452,6 @@
 
 	up(&(scn->sem)); /* Wake up any possible contending processes */
 
-	if (err)
-		MOD_DEC_USE_COUNT;
-
 	return err;
 }
 
@@ -488,8 +482,6 @@
 	up(&scn_mutex);
 	up(&(scn->sem));
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -826,6 +818,7 @@
 
 static struct
 file_operations usb_scanner_fops = {
+	.owner =	THIS_MODULE,
 	.read =		read_scanner,
 	.write =	write_scanner,
 	.ioctl =	ioctl_scanner,
@@ -840,7 +833,7 @@
 	struct usb_device *dev = interface_to_usbdev (intf);
 	struct scn_usb_data *scn;
 	struct usb_host_interface *interface;
-	struct usb_host_endpoint *endpoint;
+	struct usb_endpoint_descriptor *endpoint;
 
 	int ep_cnt;
 	int ix;
@@ -911,7 +904,6 @@
 	}
 
 	interface = intf->altsetting;
-	endpoint = &interface->endpoint[0];
 
 /*
  * Start checking for two bulk endpoints OR two bulk endpoints *and* one
@@ -929,22 +921,23 @@
 	ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0;
 
 	while (ep_cnt < interface->desc.bNumEndpoints) {
+		endpoint = &interface->endpoint[ep_cnt].desc;
 
-		if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
+		if (!have_bulk_in && IS_EP_BULK_IN(endpoint)) {
 			ep_cnt++;
 			have_bulk_in = ep_cnt;
 			dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
 			continue;
 		}
 
-		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
+		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint)) {
 			ep_cnt++;
 			have_bulk_out = ep_cnt;
 			dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
 			continue;
 		}
 
-		if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) {
+		if (!have_intr && IS_EP_INTR(endpoint)) {
 			ep_cnt++;
 			have_intr = ep_cnt;
 			dbg("probe_scanner: intr_ep:%d", have_intr);
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- a/drivers/usb/image/scanner.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/usb/image/scanner.h	Sun Nov 17 20:30:13 2002
@@ -211,10 +211,10 @@
 
 MODULE_DEVICE_TABLE (usb, scanner_device_ids);
 
-#define IS_EP_BULK(ep)  ((ep).desc.bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
-#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
-#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
-#define IS_EP_INTR(ep) ((ep).desc.bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
+#define IS_EP_BULK(ep)  ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
+#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
 
 #define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
 
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/input/hid-core.c	Sun Nov 17 20:30:14 2002
@@ -1572,7 +1572,8 @@
 	int i;
 	char *c;
 
-	dbg("HID probe called for ifnum %d", intf->ifnum);
+	dbg("HID probe called for ifnum %d",
+			intf->altsetting->desc.bInterfaceNumber);
 
 	if (!(hid = usb_hid_configure(intf)))
 		return -EIO;
@@ -1590,6 +1591,7 @@
 	dev_set_drvdata(&intf->dev, hid);
 
 	if (!hid->claimed) {
+		printk ("HID device not claimed by input or hiddev\n");
 		hid_disconnect(intf);
 		return -EIO;
 	}
diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
--- a/drivers/usb/input/hid-debug.h	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/input/hid-debug.h	Sun Nov 17 20:30:14 2002
@@ -33,7 +33,7 @@
 	char     *description;
 };
 
-static struct hid_usage_entry hid_usage_table[] = {
+static const struct hid_usage_entry hid_usage_table[] = {
   {  0,      0, "Undefined" },
   {  1,      0, "GenericDesktop" },
     {0, 0x01, "Pointer"},
@@ -218,11 +218,95 @@
     {0, 0xAA, "Shared_Parameter_Blocks"},
     {0, 0xAB, "Create_New_Effect_Report"},
     {0, 0xAC, "RAM_Pool_Available"},
+  { 0x84, 0, "Power Device" },
+    { 0x84, 0x02, "PresentStatus" },
+    { 0x84, 0x03, "ChangeStatus" },
+    { 0x84, 0x04, "UPS" },
+    { 0x84, 0x05, "PowerSupply" },
+    { 0x84, 0x10, "BatterySystem" },
+    { 0x84, 0x11, "BatterySystemID" },
+    { 0x84, 0x12, "Battery" },
+    { 0x84, 0x13, "BatteryID" },
+    { 0x84, 0x14, "Charger" },
+    { 0x84, 0x15, "ChargerID" },
+    { 0x84, 0x16, "PowerConverter" },
+    { 0x84, 0x17, "PowerConverterID" },
+    { 0x84, 0x18, "OutletSystem" },
+    { 0x84, 0x19, "OutletSystemID" },
+    { 0x84, 0x1a, "Input" },
+    { 0x84, 0x1b, "InputID" },
+    { 0x84, 0x1c, "Output" },
+    { 0x84, 0x1d, "OutputID" },
+    { 0x84, 0x1e, "Flow" },
+    { 0x84, 0x1f, "FlowID" },
+    { 0x84, 0x20, "Outlet" },
+    { 0x84, 0x21, "OutletID" },
+    { 0x84, 0x22, "Gang" },
+    { 0x84, 0x24, "PowerSummary" },
+    { 0x84, 0x25, "PowerSummaryID" },
+    { 0x84, 0x30, "Voltage" },
+    { 0x84, 0x31, "Current" },
+    { 0x84, 0x32, "Frequency" },
+    { 0x84, 0x33, "ApparentPower" },
+    { 0x84, 0x35, "PercentLoad" },
+    { 0x84, 0x40, "ConfigVoltage" },
+    { 0x84, 0x41, "ConfigCurrent" },
+    { 0x84, 0x43, "ConfigApparentPower" },
+    { 0x84, 0x53, "LowVoltageTransfer" },
+    { 0x84, 0x54, "HighVoltageTransfer" },
+    { 0x84, 0x56, "DelayBeforeStartup" },
+    { 0x84, 0x57, "DelayBeforeShutdown" },
+    { 0x84, 0x58, "Test" },
+    { 0x84, 0x5a, "AudibleAlarmControl" },
+    { 0x84, 0x60, "Present" },
+    { 0x84, 0x61, "Good" },
+    { 0x84, 0x62, "InternalFailure" },
+    { 0x84, 0x65, "Overload" },
+    { 0x84, 0x66, "OverCharged" },
+    { 0x84, 0x67, "OverTemperature" },
+    { 0x84, 0x68, "ShutdownRequested" },
+    { 0x84, 0x69, "ShutdownImminent" },
+    { 0x84, 0x6b, "SwitchOn/Off" },
+    { 0x84, 0x6c, "Switchable" },
+    { 0x84, 0x6d, "Used" },
+    { 0x84, 0x6e, "Boost" },
+    { 0x84, 0x73, "CommunicationLost" },
+    { 0x84, 0xfd, "iManufacturer" },
+    { 0x84, 0xfe, "iProduct" },
+    { 0x84, 0xff, "iSerialNumber" },
+  { 0x85, 0, "Battery System" },
+    { 0x85, 0x01, "SMBBatteryMode" },
+    { 0x85, 0x02, "SMBBatteryStatus" },
+    { 0x85, 0x03, "SMBAlarmWarning" },
+    { 0x85, 0x04, "SMBChargerMode" },
+    { 0x85, 0x05, "SMBChargerStatus" },
+    { 0x85, 0x06, "SMBChargerSpecInfo" },
+    { 0x85, 0x07, "SMBSelectorState" },
+    { 0x85, 0x08, "SMBSelectorPresets" },
+    { 0x85, 0x09, "SMBSelectorInfo" },
+    { 0x85, 0x29, "RemainingCapacityLimit" },
+    { 0x85, 0x2c, "CapacityMode" },
+    { 0x85, 0x42, "BelowRemainingCapacityLimit" },
+    { 0x85, 0x44, "Charging" },
+    { 0x85, 0x45, "Discharging" },
+    { 0x85, 0x4b, "NeedReplacement" },
+    { 0x85, 0x66, "RemainingCapacity" },
+    { 0x85, 0x68, "RunTimeToEmpty" },
+    { 0x85, 0x6a, "AverageTimeToFull" },
+    { 0x85, 0x83, "DesignCapacity" },
+    { 0x85, 0x85, "ManufacturerDate" },
+    { 0x85, 0x89, "iDeviceChemistry" },
+    { 0x85, 0x8b, "Rechargable" },
+    { 0x85, 0x8f, "iOEMInformation" },
+    { 0x85, 0x8d, "CapacityGranularity1" },
+    { 0x85, 0xd0, "ACPresent" },
+  /* pages 0xff00 to 0xffff are vendor-specific */
+  { 0xffff, 0, "Vendor-specific-FF" },
   { 0, 0, NULL }
 };
 
 static void resolv_usage_page(unsigned page) {
-	struct hid_usage_entry *p;
+	const struct hid_usage_entry *p;
 
 	for (p = hid_usage_table; p->description; p++)
 		if (p->page == page) {
@@ -233,13 +317,13 @@
 }
 
 static void resolv_usage(unsigned usage) {
-	struct hid_usage_entry *p;
+	const struct hid_usage_entry *p;
 
 	resolv_usage_page(usage >> 16);
 	printk(".");
 	for (p = hid_usage_table; p->description; p++)
 		if (p->page == (usage >> 16)) {
-			for(++p; p->description && p->page == 0; p++)
+			for(++p; p->description && p->page != 0; p++)
 				if (p->usage == (usage & 0xffff)) {
 					printk("%s", p->description);
 					return;
diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
--- a/drivers/usb/input/hid-input.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/usb/input/hid-input.c	Sun Nov 17 20:30:13 2002
@@ -348,7 +348,7 @@
 	set_bit(usage->type, input->evbit);
 
 	while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
-		usage->code = find_next_zero_bit(bit, usage->code, max + 1);
+		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
 	}
 
 	if (usage->code > max) return;
diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- a/drivers/usb/input/hid.h	Sun Nov 17 20:30:02 2002
+++ b/drivers/usb/input/hid.h	Sun Nov 17 20:30:02 2002
@@ -306,7 +306,7 @@
 #define HID_REPORT_TYPES 3
 
 #define HID_BUFFER_SIZE		32
-#define HID_CONTROL_FIFO_SIZE	64
+#define HID_CONTROL_FIFO_SIZE	256		/* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE	64
 
 struct hid_control_fifo {
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/usb/input/hiddev.c	Sun Nov 17 20:30:13 2002
@@ -652,6 +652,15 @@
 			return copy_to_user((char *) arg, hid->name, len) ?
 				-EFAULT : len;
 		}
+
+		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
+			int len;
+			if (!hid->phys) return 0;
+			len = strlen(hid->phys) + 1;
+			if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+			return copy_to_user((char *) arg, hid->phys, len) ?
+				-EFAULT : len;
+		}
 	}
 	return -EINVAL;
 }
@@ -765,11 +774,7 @@
 
 int __init hiddev_init(void)
 {
-	devfs_handle_t de;
-
-	de = devfs_get_handle(NULL, "usb", 0, 0, 0, 0);
-	hiddev_devfs_handle = devfs_mk_dir(de, "hid", NULL);
-	devfs_put(de);
+	hiddev_devfs_handle = devfs_mk_dir(NULL, "usb/hid", NULL);
 	usb_register(&hiddev_driver);
 	return 0;
 }
diff -Nru a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
--- a/drivers/usb/input/usbkbd.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/input/usbkbd.c	Sun Nov 17 20:30:15 2002
@@ -180,8 +180,10 @@
 		return 0;
 
 	kbd->irq->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
+	if (usb_submit_urb(kbd->irq, GFP_KERNEL)) {
+		kbd->open--;
 		return -EIO;
+	}
 
 	return 0;
 }
diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
--- a/drivers/usb/input/usbmouse.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/input/usbmouse.c	Sun Nov 17 20:30:15 2002
@@ -104,8 +104,10 @@
 		return 0;
 
 	mouse->irq->dev = mouse->usbdev;
-	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
+	if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
+		mouse->open--;
 		return -EIO;
+	}
 
 	return 0;
 }
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/usb/media/vicam.c	Sun Nov 17 20:30:12 2002
@@ -1199,23 +1199,22 @@
 }
 
 static struct file_operations vicam_fops = {
-	.owner =  THIS_MODULE,
-	.open =   vicam_open,
-	.release =vicam_close,
-	.read =   vicam_read,
-	.mmap =   vicam_mmap,
-	.ioctl =  vicam_ioctl,
-	.llseek = no_llseek,
+	.owner		= THIS_MODULE,
+	.open		= vicam_open,
+	.release	= vicam_close,
+	.read		= vicam_read,
+	.mmap		= vicam_mmap,
+	.ioctl		= vicam_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct video_device vicam_template = {
-	.owner = THIS_MODULE,
-	.name = "ViCam-based USB Camera",
-	.type = VID_TYPE_CAPTURE,
-	.hardware = VID_HARDWARE_VICAM,
-	.fops = &vicam_fops,
-//	.initialize = vicam_video_init,
-	.minor = -1,
+	.owner 		= THIS_MODULE,
+	.name 		= "ViCam-based USB Camera",
+	.type 		= VID_TYPE_CAPTURE,
+	.hardware 	= VID_HARDWARE_VICAM,
+	.fops 		= &vicam_fops,
+	.minor 		= -1,
 };
 
 /* table of devices that work with this driver */
@@ -1227,10 +1226,10 @@
 MODULE_DEVICE_TABLE(usb, vicam_table);
 
 static struct usb_driver vicam_driver = {
-	name:"vicam",
-	probe:vicam_probe,
-	disconnect:vicam_disconnect,
-	id_table:vicam_table
+	.name		= "vicam",
+	.probe		= vicam_probe,
+	.disconnect	= vicam_disconnect,
+	.id_table	= vicam_table
 };
 
 /**
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/misc/usbtest.c	Sun Nov 17 20:30:15 2002
@@ -550,6 +550,74 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void unlink1_callback (struct urb *urb)
+{
+	int	status = urb->status;
+
+	// we "know" -EPIPE (stall) never happens
+	if (!status)
+		status = usb_submit_urb (urb, SLAB_ATOMIC);
+	if (status) {
+		if (status == -ECONNRESET || status == -ENOENT)
+			status = 0;
+		urb->status = status;
+		complete ((struct completion *) urb->context);
+	}
+}
+
+static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
+{
+	struct urb		*urb;
+	struct completion	completion;
+	int			retval = 0;
+
+	init_completion (&completion);
+	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
+	if (async)
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+	urb->context = &completion;
+	urb->complete = unlink1_callback;
+
+	/* keep the endpoint busy.  there are lots of hc/hcd-internal
+	 * states, and testing should get to all of them over time.
+	 *
+	 * FIXME want additional tests for when endpoint is STALLing
+	 * due to errors, or is just NAKing requests.
+	 */
+	if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) {
+		dbg ("submit/unlink fail %d", retval);
+		return retval;
+	}
+
+	/* unlinking that should always work.  variable delay tests more
+	 * hcd states and code paths, even with little other system load.
+	 */
+	wait_ms (jiffies % (2 * INTERRUPT_RATE));
+	retval = usb_unlink_urb (urb);
+	if (!(retval == 0 || retval == -EINPROGRESS)) {
+		dbg ("submit/unlink fail %d", retval);
+		return retval;
+	}
+
+	wait_for_completion (&completion);
+	retval = urb->status;
+	simple_free_urb (urb);
+	return retval;
+}
+
+static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
+{
+	int			retval = 0;
+
+	/* test sync and async paths */
+	retval = unlink1 (dev, pipe, len, 1);
+	if (!retval)
+		retval = unlink1 (dev, pipe, len, 0);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* We only have this one interface to user space, through usbfs.
  * User mode code can scan usbfs to find N different devices (maybe on
  * different busses) to use when testing, and allocate one thread per
@@ -560,7 +628,8 @@
  * video capture, and so on.  Run different tests at different times, in
  * different sequences.  Nothing here should interact with other devices,
  * except indirectly by consuming USB bandwidth and CPU resources for test
- * threads and request completion.
+ * threads and request completion.  But the only way to know that for sure
+ * is to test when HC queues are in use by many devices.
  */
 
 static int
@@ -761,13 +830,35 @@
 			dbg ("ch9 subset failed, iterations left %d", i);
 		break;
 
-	/* test cases for the unlink/cancel codepaths need a thread to
-	 * usb_unlink_urb() or usg_sg_cancel(), and a way to check if
-	 * the urb/sg_request was properly canceled.
-	 *
-	 * for the unlink-queued cases, the usb_sg_*() code uses/tests
-	 * the "streamed" cleanup mode, not the "packet" one
-	 */
+	// case 10: queued control
+
+	/* simple non-queued unlinks (ring with one urb) */
+	case 11:
+		if (dev->in_pipe == 0 || !param->length)
+			break;
+		retval = 0;
+		dbg ("%s TEST 11:  unlink %d reads of %d",
+				dev->id, param->iterations, param->length);
+		for (i = param->iterations; retval == 0 && i--; /* NOP */)
+			retval = unlink_simple (dev, dev->in_pipe, param->length);
+		if (retval)
+			dbg ("unlink reads failed, iterations left %d", i);
+		break;
+	case 12:
+		if (dev->out_pipe == 0 || !param->length)
+			break;
+		retval = 0;
+		dbg ("%s TEST 12:  unlink %d writes of %d",
+				dev->id, param->iterations, param->length);
+		for (i = param->iterations; retval == 0 && i--; /* NOP */)
+			retval = unlink_simple (dev, dev->out_pipe, param->length);
+		if (retval)
+			dbg ("unlink writes failed, iterations left %d", i);
+		break;
+
+	// FIXME unlink from queue (ring with N urbs)
+
+	// FIXME scatterlist cancel (needs helper thread)
 
 	}
 	do_gettimeofday (&param->duration);
diff -Nru a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
--- a/drivers/usb/net/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/net/Kconfig	Sun Nov 17 20:30:15 2002
@@ -124,20 +124,23 @@
 	  module, say M here and read <file:Documentation/modules.txt>.
 
 config USB_USBNET
-	tristate "USB-to-USB Networking cable device support"
+	tristate "USB-to-USB Networking for cables, PDAs and other devices"
 	depends on USB && NET
 	---help---
 	  This driver supports network links over USB with USB "Network"
 	  or "data transfer" cables, often used to network laptops to PCs.
 	  Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
-	  (GeneLink), NetChip and Prolific. Intelligent USB devices could also
-	  use this approach to provide Internet access, using standard USB
-	  cabling. You can find these chips also on some motherboards with
-	  USB PC2PC support.
+	  (GeneLink), NetChip and Prolific.  Some motherboards with USB PC2PC
+	  support include such chips.
+	  
+	  Intelligent USB devices, such as PDAs running Linux (like Yopy
+	  and Zaurus, or iPaqs after upgrading to Linux) can use the same
+	  approach to provide Internet access.
 
 	  These links will have names like "usb0", "usb1", etc.  They act
 	  like two-node Ethernets, so you can use 802.1d Ethernet Bridging
-	  (CONFIG_BRIDGE) to simplify your network routing.
+	  (CONFIG_BRIDGE) to simplify your network routing.  For more
+	  information see <http://www.linux-usb.org/usbnet/>.
 
 	  This code is also available as a kernel module (code which can be
 	  inserted in and removed from the running kernel whenever you want).
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Sun Nov 17 20:30:16 2002
+++ b/drivers/usb/storage/freecom.c	Sun Nov 17 20:30:16 2002
@@ -128,15 +128,8 @@
         result = usb_stor_bulk_msg (us, fxfr, opipe,
                         FCM_PACKET_LENGTH, &partial);
         if (result != USB_STOR_XFER_GOOD) {
-                US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n",
+                US_DEBUGP ("Freecom readdata xport failure: r=%d, p=%d\n",
                                 result, partial);
-
-		/* has the current command been aborted? */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("freecom_readdata(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-
                 return USB_STOR_TRANSPORT_ERROR;
         }
         US_DEBUGP("Done issuing read request: %d %d\n", result, partial);
@@ -171,15 +164,8 @@
         result = usb_stor_bulk_msg (us, fxfr, opipe,
                         FCM_PACKET_LENGTH, &partial);
         if (result != USB_STOR_XFER_GOOD) {
-                US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n",
+                US_DEBUGP ("Freecom writedata xport failure: r=%d, p=%d\n",
                                 result, partial);
-
-		/* has the current command been aborted? */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("freecom_writedata(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-
                 return USB_STOR_TRANSPORT_ERROR;
         }
         US_DEBUGP("Done issuing write request: %d %d\n",
@@ -238,13 +224,6 @@
         if (result != USB_STOR_XFER_GOOD) {
                 US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
                                 result, partial);
-
-		/* we canceled this transfer */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("freecom_transport(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-
                 return USB_STOR_TRANSPORT_ERROR;
         }
 
@@ -253,12 +232,6 @@
         result = usb_stor_bulk_msg (us, fst, ipipe,
                         FCM_PACKET_LENGTH, &partial);
         US_DEBUGP("foo Status result %d %d\n", result, partial);
-
-	/* we canceled this transfer */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("freecom_transport(): transfer aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
-	}
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -293,13 +266,6 @@
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
 					result, partial);
-
-			/* we canceled this transfer */
-			if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-				US_DEBUGP("freecom_transport(): transfer aborted\n");
-				return USB_STOR_TRANSPORT_ABORTED;
-			}
-
 			return USB_STOR_TRANSPORT_ERROR;
 		}
 
@@ -308,12 +274,6 @@
 				FCM_PACKET_LENGTH, &partial);
 
 		US_DEBUGP("bar Status result %d %d\n", result, partial);
-
-		/* we canceled this transfer */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("freecom_transport(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
 		if (result > USB_STOR_XFER_SHORT)
 	                return USB_STOR_TRANSPORT_ERROR;
 
@@ -372,10 +332,6 @@
                                 FCM_PACKET_LENGTH, &partial);
 		US_DEBUG(pdump ((void *) fst, partial));
 
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-                        US_DEBUGP ("freecom_transport: transfer aborted\n");
-                        return USB_STOR_TRANSPORT_ABORTED;
-                }
                 if (partial != 4 || result > USB_STOR_XFER_SHORT)
                         return USB_STOR_TRANSPORT_ERROR;
                 if ((fst->Status & ERR_STAT) != 0) {
@@ -401,10 +357,6 @@
                 result = usb_stor_bulk_msg (us, fst, ipipe,
                                 FCM_PACKET_LENGTH, &partial);
 
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-                        US_DEBUGP ("freecom_transport: transfer aborted\n");
-                        return USB_STOR_TRANSPORT_ABORTED;
-                }
                 if (partial != 4 || result > USB_STOR_XFER_SHORT)
                         return USB_STOR_TRANSPORT_ERROR;
                 if ((fst->Status & ERR_STAT) != 0) {
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/storage/isd200.c	Sun Nov 17 20:30:14 2002
@@ -130,8 +130,6 @@
 #define ISD200_TRANSPORT_GOOD       0   /* Transport good, command good     */
 #define ISD200_TRANSPORT_FAILED     1   /* Transport good, command failed   */
 #define ISD200_TRANSPORT_ERROR      2   /* Transport bad (i.e. device dead) */
-#define ISD200_TRANSPORT_ABORTED    3   /* Transport aborted                */
-#define ISD200_TRANSPORT_SHORT      4   /* Transport short                  */
 
 /* driver action codes */
 #define	ACTION_READ_STATUS	0
@@ -395,138 +393,6 @@
 
 
 /**************************************************************************
- *  ISD200 Bulk Transport
- *
- * Note:  This routine was copied from the usb_stor_Bulk_transport routine
- * located in the transport.c source file.  The scsi command is limited to
- * only 12 bytes while the CDB for the ISD200 must be 16 bytes.
- */
-int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb, 
-                           union ata_cdb *AtaCdb, unsigned char AtaCdbLength )
-{
-        struct bulk_cb_wrap bcb;
-        struct bulk_cs_wrap bcs;
-        int result;
-        unsigned int transfer_length;
-
-	int dir = srb->sc_data_direction;
-	srb->sc_data_direction = SCSI_DATA_WRITE;
-        transfer_length = usb_stor_transfer_length(srb);
-	srb->sc_data_direction = dir;
-    
-        /* set up the command wrapper */
-        bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-        bcb.DataTransferLength = cpu_to_le32(transfer_length);
-        bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
-        bcb.Tag = srb->serial_number;
-        bcb.Lun = srb->cmnd[1] >> 5;
-        if (us->flags & US_FL_SCM_MULT_TARG)
-                bcb.Lun |= srb->target << 4;
-        bcb.Length = AtaCdbLength;
-    
-        /* copy the command payload */
-        memset(bcb.CDB, 0, sizeof(bcb.CDB));
-        memcpy(bcb.CDB, AtaCdb, bcb.Length);
-    
-        /* send it to out endpoint */
-        US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
-                  le32_to_cpu(bcb.Signature), bcb.Tag,
-                  (bcb.Lun >> 4), (bcb.Lun & 0x0F), 
-                  le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-				(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
-        US_DEBUGP("Bulk command transfer result=%d\n", result);
-    
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		return ISD200_TRANSPORT_ABORTED;
-	}
-	if (result != USB_STOR_XFER_GOOD)  
-                return ISD200_TRANSPORT_ERROR;
-    
-        /* if the command transfered well, then we go to the data stage */
-	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
-				us->recv_bulk_pipe : us->send_bulk_pipe;
-		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
-					transfer_length);
-		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-
-		/* if it was aborted, we need to indicate that */
-		if (result == USB_STOR_XFER_ABORTED)
-			return ISD200_TRANSPORT_ABORTED;
-		if (result == USB_STOR_XFER_ERROR)
-			return ISD200_TRANSPORT_ERROR;
-        }
-    
-        /* See flow chart on pg 15 of the Bulk Only Transport spec for
-         * an explanation of how this code works.
-         */
-    
-        /* get CSW for device status */
-        US_DEBUGP("Attempting to get CSW...\n");
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
-
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		return ISD200_TRANSPORT_ABORTED;
-	}
-
-        /* did the attempt to read the CSW fail? */
-	if (result == USB_STOR_XFER_STALLED) {
-           
-                /* get the status again */
-                US_DEBUGP("Attempting to get CSW (2nd try)...\n");
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
-
-                /* if the command was aborted, indicate that */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			return ISD200_TRANSPORT_ABORTED;
-		}
-        }
-    
-        /* if we still have a failure at this point, we're in trouble */
-        US_DEBUGP("Bulk status result = %d\n", result);
-        if (result != USB_STOR_XFER_GOOD)
-                return ISD200_TRANSPORT_ERROR;
-    
-        /* check bulk status */
-        US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
-                  le32_to_cpu(bcs.Signature), bcs.Tag, 
-                  bcs.Residue, bcs.Status);
-        if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || 
-            bcs.Tag != bcb.Tag || 
-            bcs.Status > US_BULK_STAT_PHASE) {
-                US_DEBUGP("Bulk logical error\n");
-                return ISD200_TRANSPORT_ERROR;
-        }
-    
-        /* based on the status code, we report good or bad */
-        switch (bcs.Status) {
-        case US_BULK_STAT_OK:
-                /* command good -- note that we could be short on data */
-		if (srb->resid > 0)
-			return ISD200_TRANSPORT_SHORT;
-                return ISD200_TRANSPORT_GOOD;
-
-        case US_BULK_STAT_FAIL:
-                /* command failed */
-                return ISD200_TRANSPORT_FAILED;
-        
-        case US_BULK_STAT_PHASE:
-                /* phase error */
-                usb_stor_Bulk_reset(us);
-                return ISD200_TRANSPORT_ERROR;
-        }
-    
-        /* we should never get here, but if we do, we're in trouble */
-        return ISD200_TRANSPORT_ERROR;
-}
-
-
-/**************************************************************************
  *  isd200_action
  *
  * Routine for sending commands to the isd200
@@ -612,9 +478,11 @@
 		break;
 	}
 
-	status = isd200_Bulk_transport(us, &srb, &ata, sizeof(ata.generic));
-	if (status != ISD200_TRANSPORT_GOOD &&
-			status != ISD200_TRANSPORT_SHORT) {
+	memcpy(srb.cmnd, &ata, sizeof(ata.generic));
+	status = usb_stor_Bulk_transport(&srb, us);
+	if (status == USB_STOR_TRANSPORT_GOOD)
+		status = ISD200_GOOD;
+	else {
 		US_DEBUGP("   isd200_action(0x%02x) error: %d\n",action,status);
 		status = ISD200_ERROR;
 		/* need to reset device here */
@@ -669,8 +537,8 @@
 
 	/* send the command to the transport layer */
 	srb->resid = 0;
-	transferStatus = isd200_Bulk_transport(us, srb, ataCdb,
-					       sizeof(ataCdb->generic));
+	memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic));
+	transferStatus = usb_stor_Bulk_transport(srb, us);
 
 	/* if the command gets aborted by the higher layers, we need to
 	 * short-circuit all other processing
@@ -683,45 +551,37 @@
 
 	switch (transferStatus) {
 
-	case ISD200_TRANSPORT_GOOD:
+	case USB_STOR_TRANSPORT_GOOD:
 		/* Indicate a good result */
 		srb->result = GOOD << 1;
 		break;
 
-	case ISD200_TRANSPORT_ABORTED:
-		/* if the command gets aborted by the higher layers, we need to
-		 * short-circuit all other processing
-		 */
-		US_DEBUGP("-- transport indicates command was aborted\n");
-		srb->result = DID_ABORT << 16;
-		break;
-
-	case ISD200_TRANSPORT_FAILED:
+	case USB_STOR_TRANSPORT_FAILED:
 		US_DEBUGP("-- transport indicates command failure\n");
 		need_auto_sense = 1;
 		break;
 
-	case ISD200_TRANSPORT_ERROR:
-		US_DEBUGP("-- transport indicates transport failure\n");
+	case USB_STOR_TRANSPORT_ERROR:
+		US_DEBUGP("-- transport indicates transport error\n");
 		srb->result = DID_ERROR << 16;
-		break;
-
-	case ISD200_TRANSPORT_SHORT:
-		srb->result = GOOD << 1;
-		if (!((srb->cmnd[0] == REQUEST_SENSE) ||
-		      (srb->cmnd[0] == INQUIRY) ||
-		      (srb->cmnd[0] == MODE_SENSE) ||
-		      (srb->cmnd[0] == LOG_SENSE) ||
-		      (srb->cmnd[0] == MODE_SENSE_10))) {
-			US_DEBUGP("-- unexpectedly short transfer\n");
-			need_auto_sense = 1;
-		}
-		break;
+		/* Need reset here */
+		return;
     
 	default:
-		US_DEBUGP("-- transport indicates unknown failure\n");   
+		US_DEBUGP("-- transport indicates unknown error\n");   
 		srb->result = DID_ERROR << 16;
-       
+		/* Need reset here */
+		return;
+	}
+
+	if ((srb->resid > 0) &&
+	    !((srb->cmnd[0] == REQUEST_SENSE) ||
+	      (srb->cmnd[0] == INQUIRY) ||
+	      (srb->cmnd[0] == MODE_SENSE) ||
+	      (srb->cmnd[0] == LOG_SENSE) ||
+	      (srb->cmnd[0] == MODE_SENSE_10))) {
+		US_DEBUGP("-- unexpectedly short transfer\n");
+		need_auto_sense = 1;
 	}
 
 	if (need_auto_sense) {
@@ -729,14 +589,23 @@
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 			US_DEBUGP("-- auto-sense aborted\n");
 			srb->result = DID_ABORT << 16;
-		} else if (result == ISD200_GOOD)
+			return;
+		}
+		if (result == ISD200_GOOD) {
 			isd200_build_sense(us, srb);
+			srb->result = CHECK_CONDITION << 1;
+
+			/* If things are really okay, then let's show that */
+			if ((srb->sense_buffer[2] & 0xf) == 0x0)
+				srb->result = GOOD << 1;
+		} else
+			srb->result = DID_ERROR << 16;
 	}
 
 	/* Regardless of auto-sense, if we _know_ we have an error
 	 * condition, show that in the result code
 	 */
-	if (transferStatus == ISD200_TRANSPORT_FAILED)
+	if (transferStatus == USB_STOR_TRANSPORT_FAILED)
 		srb->result = CHECK_CONDITION << 1;
 }
 
diff -Nru a/drivers/usb/storage/raw_bulk.c b/drivers/usb/storage/raw_bulk.c
--- a/drivers/usb/storage/raw_bulk.c	Sun Nov 17 20:30:15 2002
+++ b/drivers/usb/storage/raw_bulk.c	Sun Nov 17 20:30:15 2002
@@ -1,16 +1,9 @@
 /*
  * Common routines for a handful of drivers.
- * Unrelated to CF/SM - just USB stuff.
- *
- * This is mostly a thin layer on top of transport.c.
- * It converts routines that return values like -EPIPE
- * into routines that return USB_STOR_TRANSPORT_ABORTED etc.
- *
- * There is also some debug printing here.
+ * Unrelated to CF/SM - just scatter-gather stuff.
  */
 
-#include "debug.h"
-#include "transport.h"
+#include "usb.h"
 #include "raw_bulk.h"
 
 /*
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Sun Nov 17 20:30:14 2002
+++ b/drivers/usb/storage/scsiglue.c	Sun Nov 17 20:30:14 2002
@@ -103,7 +103,7 @@
  *
  * NOTE: There is no contention here, because we're already deregistered
  * the driver and we're doing each virtual host in turn, not in parallel
- * Synchronization: BLK, no spinlock.
+ * Synchronization: BKL, no spinlock.
  */
 static int release(struct Scsi_Host *psh)
 {
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Sun Nov 17 20:30:13 2002
+++ b/drivers/usb/storage/transport.c	Sun Nov 17 20:30:13 2002
@@ -562,12 +562,6 @@
 			value, index, data, size);
 	US_DEBUGP("usb_stor_control_msg returned %d\n", result);
 
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("-- transfer aborted\n");
-		return USB_STOR_XFER_ABORTED;
-	}
-
 	/* a stall indicates a protocol error */
 	if (result == -EPIPE) {
 		US_DEBUGP("-- stall on control pipe\n");
@@ -624,12 +618,6 @@
 		return USB_STOR_XFER_STALLED;
 	}
 
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("-- transfer aborted\n");
-		return USB_STOR_XFER_ABORTED;
-	}
-
 	/* NAK - that means we've retried a few times already */
 	if (result == -ETIMEDOUT) {
 		US_DEBUGP("-- device NAKed\n");
@@ -669,7 +657,7 @@
 
 	/* initialize the scatter-gather request block */
 	US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %d bytes, "
-			"%d entires\n", length, num_sg);
+			"%d entries\n", length, num_sg);
 	result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
 			sg, num_sg, length, SLAB_NOIO);
 	if (result) {
@@ -691,26 +679,27 @@
 		}
 	}
 
+	/* wait for the completion of the transfer */
 	usb_sg_wait(us->current_sg);
 	clear_bit(US_FLIDX_CANCEL_SG, &us->flags);
 
 	result = us->current_sg->status;
 	partial = us->current_sg->bytes;
-	US_DEBUGP("usb_sg_wait() returned %d xferrerd %d/%d\n",
+	US_DEBUGP("usb_sg_wait() returned %d xferred %d/%d\n",
 			result, partial, length);
 	if (act_len)
 		*act_len = partial;
 
 	/* if we stall, we need to clear it before we go on */
 	if (result == -EPIPE) {
-		US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
+		US_DEBUGP("clearing endpoint halt for pipe 0x%x, "
 				"stalled at %d bytes\n", pipe, partial);
 		if (usb_stor_clear_halt(us, pipe) < 0)
 			return USB_STOR_XFER_ERROR;
 		return USB_STOR_XFER_STALLED;
 	}
 
-	/* NAK - that means we've tried this a few times already */
+	/* NAK - that means we've retried this a few times already */
 	if (result == -ETIMEDOUT) {
 		US_DEBUGP("-- device NAKed\n");
 		return USB_STOR_XFER_ERROR;
@@ -738,10 +727,10 @@
  * Transfer an entire SCSI command's worth of data payload over the bulk
  * pipe.
  *
- * Nore that this uses the usb_stor_bulk_transfer_buf() and
+ * Nore that this uses usb_stor_bulk_transfer_buf() and
  * usb_stor_bulk_transfer_sglist() to achieve its goals --
  * this function simply determines whether we're going to use
- * scatter-gather or not, and acts apropriately.
+ * scatter-gather or not, and acts appropriately.
  */
 int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
 		char *buf, unsigned int length_left, int use_sg, int *residual)
@@ -1116,15 +1105,6 @@
 	if (result != USB_STOR_XFER_GOOD) {
 		/* Reset flag for status notification */
 		clear_bit(US_FLIDX_IP_WANTED, &us->flags);
-	}
-
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("usb_stor_control_msg(): transfer aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
-	}
-
-	if (result != USB_STOR_XFER_GOOD) {
 		/* Uh oh... serious problem here */
 		return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -1137,12 +1117,6 @@
 		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
 					transfer_length);
 		US_DEBUGP("CBI data stage result is 0x%x\n", result);
-
-		/* report any errors */
-		if (result == USB_STOR_XFER_ABORTED) {
-			clear_bit(US_FLIDX_IP_WANTED, &us->flags);
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
 		if (result == USB_STOR_XFER_ERROR) {
 			clear_bit(US_FLIDX_IP_WANTED, &us->flags);
 			return USB_STOR_TRANSPORT_ERROR;
@@ -1157,7 +1131,7 @@
 	/* has the current command been aborted? */
 	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
 		US_DEBUGP("CBI interrupt aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
+		return USB_STOR_TRANSPORT_ERROR;
 	}
 
 	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
@@ -1222,13 +1196,6 @@
 
 	/* check the return code for the command */
 	US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
-
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
-	}
-
 	if (result != USB_STOR_XFER_GOOD) {
 		/* Uh oh... serious problem here */
 		return USB_STOR_TRANSPORT_ERROR;
@@ -1242,14 +1209,8 @@
 		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
 					transfer_length);
 		US_DEBUGP("CB data stage result is 0x%x\n", result);
-
-		/* report any errors */
-		if (result == USB_STOR_XFER_ABORTED) {
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
-		if (result == USB_STOR_XFER_ERROR) {
+		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
-		}
 	}
 
 	/* STATUS STAGE */
@@ -1319,12 +1280,6 @@
 	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
 				(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
 	US_DEBUGP("Bulk command transfer result=%d\n", result);
-
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
-	}
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -1336,10 +1291,6 @@
 		result = usb_stor_bulk_transfer_srb(us, pipe, srb,
 					transfer_length);
 		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-
-		/* if it was aborted, we need to indicate that */
-		if (result == USB_STOR_XFER_ABORTED)
-			return USB_STOR_TRANSPORT_ABORTED;
 		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -1353,12 +1304,6 @@
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
 
-	/* did we abort this command? */
-	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-		US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-		return USB_STOR_TRANSPORT_ABORTED;
-	}
-
 	/* did the attempt to read the CSW fail? */
 	if (result == USB_STOR_XFER_STALLED) {
 
@@ -1366,12 +1311,6 @@
 		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
 		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
-
-		/* did we abort this command? */
-		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-			US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
-			return USB_STOR_TRANSPORT_ABORTED;
-		}
 	}
 
 	/* if we still have a failure at this point, we're in trouble */
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	Sun Nov 17 20:30:13 2002
+++ b/drivers/usb/storage/transport.h	Sun Nov 17 20:30:13 2002
@@ -121,7 +121,6 @@
 #define USB_STOR_XFER_SHORT		1  /* transfered less than expected */
 #define USB_STOR_XFER_STALLED		2  /* endpoint stalled		    */
 #define USB_STOR_XFER_ERROR		3  /* transfer died in the middle   */
-#define USB_STOR_XFER_ABORTED		4  /* transfer canceled             */
 
 /*
  * Transport return codes
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Sun Nov 17 20:30:12 2002
+++ b/drivers/usb/storage/usb.c	Sun Nov 17 20:30:12 2002
@@ -437,41 +437,6 @@
 			us->srb->result = GOOD << 1;
 		}
 
-		/* Most USB devices can't handle START_STOP.  But we
-		 * need something for media-change, so we'll use TUR
-		 * instead.
-		 *
-		 * We specifically allow this command through if either:
-		 * (a) it's a load/eject command (cmnd[4] & 2)
-		 * (b) it's a multi-target unit (i.e. legacy SCSI adaptor)
-		 */
-		else if (us->srb->cmnd[0] == START_STOP &&
-				!(us->srb->cmnd[4] & 2) &&
-				!(us->flags & US_FL_SCM_MULT_TARG)) {
-			unsigned char saved_cdb[16]; /* largest SCSI-III cmd */
-			__u8 old_cmd_len;
-
-			US_DEBUGP("Converting START_STOP to TUR\n");
-
-			/* save old command */
-			memcpy(saved_cdb, us->srb->cmnd, us->srb->cmd_len);
-			old_cmd_len = us->srb->cmd_len;
-
-			/* set up new command -- preserve LUN */
-			us->srb->cmd_len = 6;
-			memset(us->srb->cmnd, 0, us->srb->cmd_len);
-			us->srb->cmnd[0] = TEST_UNIT_READY;
-			us->srb->cmnd[1] = saved_cdb[1] & 0xE0;
-
-			/* do command */
-			US_DEBUG(usb_stor_show_command(us->srb));
-			us->proto_handler(us->srb, us);
-
-			/* restore original command */
-			us->srb->cmd_len = old_cmd_len;
-			memcpy(us->srb->cmnd, saved_cdb, us->srb->cmd_len);
-		}
-
 		/* we've got a command, let's do it! */
 		else {
 			US_DEBUG(usb_stor_show_command(us->srb));
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	Sun Nov 17 20:30:14 2002
+++ b/fs/Kconfig	Sun Nov 17 20:30:14 2002
@@ -1037,15 +1037,12 @@
 	  If you haven't heard about all of this before, it's safe to say N.
 
 config UDF_FS
-	tristate "UDF file system support (read only)"
+	tristate "UDF file system support"
 	---help---
 	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
 	  you intend to mount DVD discs or CDRW's written in packet mode, or
-	  if written to by other UDF utilities, such as DirectCD. This UDF
-	  file system support is read-only. If you want to write to UDF
-	  file systems on some media, you need to say Y to "UDF read-write
-	  support" below in addition. Please read
-	  <file:Documentation/filesystems/udf.txt>.
+	  if written to by other UDF utilities, such as DirectCD.
+	  Please read <file:Documentation/filesystems/udf.txt>.
 
 	  This file system support is also available as a module ( = code
 	  which can be inserted in and removed from the running kernel
@@ -1054,14 +1051,6 @@
 	  <file:Documentation/modules.txt>.
 
 	  If unsure, say N.
-
-config UDF_RW
-	bool "UDF write support (DANGEROUS)"
-	depends on UDF_FS && EXPERIMENTAL
-	help
-	  Say Y if you want to test write support for UDF file systems.
-	  Due to lack of support for writing to CDR/CDRW's, this option
-	  is only supported for hard discs, DVD-RAM, and loopback files.
 
 config UFS_FS
 	tristate "UFS file system support (read only)"
diff -Nru a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
--- a/fs/adfs/dir_f.c	Sun Nov 17 20:30:14 2002
+++ b/fs/adfs/dir_f.c	Sun Nov 17 20:30:14 2002
@@ -17,6 +17,7 @@
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 
 #include "adfs.h"
 #include "dir_f.h"
diff -Nru a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
--- a/fs/adfs/dir_fplus.c	Sun Nov 17 20:30:03 2002
+++ b/fs/adfs/dir_fplus.c	Sun Nov 17 20:30:03 2002
@@ -15,6 +15,7 @@
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 
 #include "adfs.h"
 #include "dir_fplus.h"
diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c
--- a/fs/adfs/inode.c	Sun Nov 17 20:30:12 2002
+++ b/fs/adfs/inode.c	Sun Nov 17 20:30:12 2002
@@ -271,9 +271,10 @@
 	ADFS_I(inode)->stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
 
 	inode->i_mode	 = adfs_atts2mode(sb, inode);
-	inode->i_mtime	 =
-	inode->i_atime	 =
-	inode->i_ctime	 = adfs_adfs2unix_time(inode);
+	inode->i_mtime.tv_sec	 =
+	inode->i_atime.tv_sec	 =
+	inode->i_ctime.tv_sec	 = adfs_adfs2unix_time(inode);
+	inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
 
 	if (S_ISDIR(inode->i_mode)) {
 		inode->i_op	= &adfs_dir_inode_operations;
@@ -327,7 +328,7 @@
 
 	if (ia_valid & ATTR_MTIME) {
 		inode->i_mtime = attr->ia_mtime;
-		adfs_unix2adfs_time(inode, attr->ia_mtime);
+		adfs_unix2adfs_time(inode, attr->ia_mtime.tv_sec);
 	}
 	/*
 	 * FIXME: should we make these == to i_mtime since we don't
diff -Nru a/fs/affs/inode.c b/fs/affs/inode.c
--- a/fs/affs/inode.c	Sun Nov 17 20:30:13 2002
+++ b/fs/affs/inode.c	Sun Nov 17 20:30:13 2002
@@ -165,12 +165,13 @@
 		break;
 	}
 
-	inode->i_mtime = inode->i_atime = inode->i_ctime
+	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
 		       = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) +
 		         be32_to_cpu(tail->change.mins) * 60 +
 			 be32_to_cpu(tail->change.ticks) / 50 +
 			 ((8 * 365 + 2) * 24 * 60 * 60)) +
 			 sys_tz.tz_minuteswest * 60;
+	inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
 	affs_brelse(bh);
 	return;
 
@@ -203,11 +204,11 @@
 	}
 	tail = AFFS_TAIL(sb, bh);
 	if (tail->stype == be32_to_cpu(ST_ROOT)) {
-		secs_to_datestamp(inode->i_mtime,&AFFS_ROOT_TAIL(sb, bh)->root_change);
+		secs_to_datestamp(inode->i_mtime.tv_sec,&AFFS_ROOT_TAIL(sb, bh)->root_change);
 	} else {
 		tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
 		tail->size = cpu_to_be32(inode->i_size);
-		secs_to_datestamp(inode->i_mtime,&tail->change);
+		secs_to_datestamp(inode->i_mtime.tv_sec,&tail->change);
 		if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
 			uid = inode->i_uid;
 			gid = inode->i_gid;
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	Sun Nov 17 20:30:15 2002
+++ b/fs/affs/super.c	Sun Nov 17 20:30:15 2002
@@ -44,7 +44,7 @@
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(1);
-		secs_to_datestamp(CURRENT_TIME,
+		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
 		mark_buffer_dirty(sbi->s_root_bh);
@@ -72,7 +72,7 @@
 		//		if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) {
 		//			clean = 0;
 		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(clean);
-		secs_to_datestamp(CURRENT_TIME,
+		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
 		mark_buffer_dirty(sbi->s_root_bh);
@@ -80,7 +80,6 @@
 	} else
 		sb->s_dirt = 0;
 
-	pr_debug("AFFS: write_super() at %lu, clean=%d\n", CURRENT_TIME, clean);
 	unlock_kernel();
 }
 
diff -Nru a/fs/afs/inode.c b/fs/afs/inode.c
--- a/fs/afs/inode.c	Sun Nov 17 20:30:12 2002
+++ b/fs/afs/inode.c	Sun Nov 17 20:30:12 2002
@@ -70,7 +70,10 @@
 	inode->i_gid		= 0;
 	inode->i_rdev		= NODEV;
 	inode->i_size		= vnode->status.size;
-	inode->i_atime		= inode->i_mtime = inode->i_ctime = vnode->status.mtime_server;
+	inode->i_atime.tv_sec		= inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = vnode->status.mtime_server;
+	inode->i_atime.tv_nsec = 
+	inode->i_mtime.tv_nsec = 
+		inode->i_ctime.tv_nsec = 0;
 	inode->i_blksize	= PAGE_CACHE_SIZE;
 	inode->i_blocks		= 0;
 	inode->i_version	= vnode->fid.unique;
diff -Nru a/fs/afs/vlclient.c b/fs/afs/vlclient.c
--- a/fs/afs/vlclient.c	Sun Nov 17 20:30:02 2002
+++ b/fs/afs/vlclient.c	Sun Nov 17 20:30:02 2002
@@ -276,7 +276,7 @@
 		goto abort;
 
 	/* success */
-	entry->ctime = xtime.tv_sec;
+	entry->ctime = get_seconds();
 	ret = 0;
 
  out_unwait:
@@ -407,7 +407,7 @@
 #endif
 
 	/* success */
-	entry->ctime = xtime.tv_sec;
+	entry->ctime = get_seconds();
 	ret = 0;
 
  out_unwait:
@@ -584,7 +584,7 @@
 #endif
 
 		/* success */
-		entry->ctime = xtime.tv_sec;
+		entry->ctime = CURRENT_TIME;
 		ret = 0;
 		goto done;
 	}
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Sun Nov 17 20:30:03 2002
+++ b/fs/attr.c	Sun Nov 17 20:30:03 2002
@@ -122,7 +122,7 @@
 	struct inode *inode = dentry->d_inode;
 	mode_t mode = inode->i_mode;
 	int error;
-	time_t now = CURRENT_TIME;
+	struct timespec now = CURRENT_TIME;
 	unsigned int ia_valid = attr->ia_valid;
 
 	if (!inode)
diff -Nru a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
--- a/fs/autofs/autofs_i.h	Sun Nov 17 20:30:15 2002
+++ b/fs/autofs/autofs_i.h	Sun Nov 17 20:30:15 2002
@@ -25,6 +25,7 @@
 #include <linux/wait.h>
 #include <linux/dcache.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 #ifdef DEBUG
diff -Nru a/fs/autofs/inode.c b/fs/autofs/inode.c
--- a/fs/autofs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/autofs/inode.c	Sun Nov 17 20:30:15 2002
@@ -233,7 +233,8 @@
 		sl = &sbi->symlink[n];
 		inode->u.generic_ip = sl;
 		inode->i_mode = S_IFLNK | S_IRWXUGO;
-		inode->i_mtime = inode->i_ctime = sl->mtime;
+		inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
+		inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
 		inode->i_size = sl->len;
 		inode->i_nlink = 1;
 	}
diff -Nru a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c	Sun Nov 17 20:30:14 2002
+++ b/fs/autofs/root.c	Sun Nov 17 20:30:14 2002
@@ -314,7 +314,7 @@
 	}
 
 	memcpy(sl->data,symname,slsize);
-	sl->mtime = CURRENT_TIME;
+	sl->mtime = get_seconds();
 
 	ent->ino = AUTOFS_FIRST_SYMLINK + n;
 	ent->hash = dentry->d_name.hash;
diff -Nru a/fs/autofs4/expire.c b/fs/autofs4/expire.c
--- a/fs/autofs4/expire.c	Sun Nov 17 20:30:15 2002
+++ b/fs/autofs4/expire.c	Sun Nov 17 20:30:15 2002
@@ -12,6 +12,7 @@
  * ------------------------------------------------------------------------- */
 
 #include "autofs_i.h"
+#include <linux/mount.h>
 
 /*
  * Determine if a subtree of the namespace is busy.
diff -Nru a/fs/befs/datastream.c b/fs/befs/datastream.c
--- a/fs/befs/datastream.c	Sun Nov 17 20:30:15 2002
+++ b/fs/befs/datastream.c	Sun Nov 17 20:30:15 2002
@@ -14,6 +14,7 @@
 #include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 
 #include "befs.h"
 #include "datastream.h"
diff -Nru a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
--- a/fs/befs/linuxvfs.c	Sun Nov 17 20:30:13 2002
+++ b/fs/befs/linuxvfs.c	Sun Nov 17 20:30:13 2002
@@ -360,8 +360,9 @@
 	 * doesn't have creation time.
 	 */
 
-	inode->i_mtime =
-	    (time_t) (fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16);
+	inode->i_mtime.tv_sec =
+	    fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16;
+	inode->i_mtime.tv_nsec = 0;   /* use the lower bits ? */	
 	inode->i_ctime = inode->i_mtime;
 	inode->i_atime = inode->i_mtime;
 	inode->i_blksize = befs_sb->block_size;
diff -Nru a/fs/bfs/inode.c b/fs/bfs/inode.c
--- a/fs/bfs/inode.c	Sun Nov 17 20:30:13 2002
+++ b/fs/bfs/inode.c	Sun Nov 17 20:30:13 2002
@@ -71,9 +71,12 @@
 	inode->i_size = BFS_FILESIZE(di);
 	inode->i_blocks = BFS_FILEBLOCKS(di);
 	inode->i_blksize = PAGE_SIZE;
-	inode->i_atime = di->i_atime;
-	inode->i_mtime = di->i_mtime;
-	inode->i_ctime = di->i_ctime;
+	inode->i_atime.tv_sec = di->i_atime;
+	inode->i_mtime.tv_sec = di->i_mtime;
+	inode->i_ctime.tv_sec = di->i_ctime;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
 	BFS_I(inode)->i_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
 	BFS_I(inode)->i_sblock = di->i_sblock;
 	BFS_I(inode)->i_eblock = di->i_eblock;
@@ -115,9 +118,9 @@
 	di->i_uid = inode->i_uid;
 	di->i_gid = inode->i_gid;
 	di->i_nlink = inode->i_nlink;
-	di->i_atime = inode->i_atime;
-	di->i_mtime = inode->i_mtime;
-	di->i_ctime = inode->i_ctime;
+	di->i_atime = inode->i_atime.tv_sec;
+	di->i_mtime = inode->i_mtime.tv_sec;
+	di->i_ctime = inode->i_ctime.tv_sec;
 	di->i_sblock = BFS_I(inode)->i_sblock;
 	di->i_eblock = BFS_I(inode)->i_eblock;
 	di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
diff -Nru a/fs/binfmt_misc.c b/fs/binfmt_misc.c
--- a/fs/binfmt_misc.c	Sun Nov 17 20:30:12 2002
+++ b/fs/binfmt_misc.c	Sun Nov 17 20:30:12 2002
@@ -25,6 +25,7 @@
 #include <linux/file.h>
 #include <linux/pagemap.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 
diff -Nru a/fs/binfmt_som.c b/fs/binfmt_som.c
--- a/fs/binfmt_som.c	Sun Nov 17 20:30:12 2002
+++ b/fs/binfmt_som.c	Sun Nov 17 20:30:12 2002
@@ -54,7 +54,11 @@
 #define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1))
 
 static struct linux_binfmt som_format = {
-	NULL, THIS_MODULE, load_som_binary, load_som_library, som_core_dump, SOM_PAGESIZE
+	.module		= THIS_MODULE,
+	.load_binary	= load_som_binary,
+	.load_library	= load_som_library,
+	.core_dump	= som_core_dump,
+	.min_coredump	= SOM_PAGESIZE
 };
 
 /*
@@ -182,8 +186,8 @@
  * libraries.  There is no binary dependent code anywhere else.
  */
 
-static inline int
-do_load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int
+load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
 	int som_exec_fileno;
 	int retval;
@@ -280,34 +284,11 @@
 	return retval;
 }
 
-static int
-load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
-	int retval;
-
-	MOD_INC_USE_COUNT;
-	retval = do_load_som_binary(bprm, regs);
-	MOD_DEC_USE_COUNT;
-	return retval;
-}
-
-static inline int
-do_load_som_library(struct file *f)
+static int load_som_library(struct file *f)
 {
 /* No lib support in SOM yet.  gizza chance.. */
 	return -ENOEXEC;
 }
-
-static int load_som_library(struct file *f)
-{
-	int retval;
-
-	MOD_INC_USE_COUNT;
-	retval = do_load_som_library(f);
-	MOD_DEC_USE_COUNT;
-	return retval;
-}
-
 	/* Install the SOM loader.
 	 * N.B. We *rely* on the table being the right size with the
 	 * right number of free slots...
@@ -326,4 +307,3 @@
 
 module_init(init_som_binfmt);
 module_exit(exit_som_binfmt);
-
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Sun Nov 17 20:30:16 2002
+++ b/fs/block_dev.c	Sun Nov 17 20:30:16 2002
@@ -20,9 +20,11 @@
 #include <linux/blkpg.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
-
+#include <linux/mount.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 
+
 static sector_t max_block(struct block_device *bdev)
 {
 	sector_t retval = ~((sector_t)0);
@@ -518,7 +520,7 @@
 	if (bdev->bd_contains != bdev)
 		BUG();
 	down(&bdev->bd_sem);
-	if (check_disk_change(bdev)) {
+	if (check_disk_change(bdev) && bdev->bd_invalidated) {
 		rescan_partitions(bdev->bd_disk, bdev);
 		res = 1;
 	}
@@ -783,14 +785,14 @@
 	return res;
 }
 
-const char *__bdevname(kdev_t dev)
+const char *__bdevname(dev_t dev)
 {
 	static char buffer[32];
-	const char * name = blkdevs[major(dev)];
+	const char * name = blkdevs[MAJOR(dev)];
 
 	if (!name)
 		name = "unknown-block";
 
-	sprintf(buffer, "%s(%d,%d)", name, major(dev), minor(dev));
+	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
 	return buffer;
 }
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Sun Nov 17 20:30:14 2002
+++ b/fs/buffer.c	Sun Nov 17 20:30:14 2002
@@ -678,7 +678,7 @@
 
 int inode_has_buffers(struct inode *inode)
 {
-	return !list_empty(&inode->i_mapping->private_list);
+	return !list_empty(&inode->i_data.private_list);
 }
 
 /*
@@ -858,7 +858,7 @@
 void invalidate_inode_buffers(struct inode *inode)
 {
 	if (inode_has_buffers(inode)) {
-		struct address_space *mapping = inode->i_mapping;
+		struct address_space *mapping = &inode->i_data;
 		struct list_head *list = &mapping->private_list;
 		struct address_space *buffer_mapping = mapping->assoc_mapping;
 
@@ -867,6 +867,35 @@
 			__remove_assoc_queue(BH_ENTRY(list->next));
 		spin_unlock(&buffer_mapping->private_lock);
 	}
+}
+
+/*
+ * Remove any clean buffers from the inode's buffer list.  This is called
+ * when we're trying to free the inode itself.  Those buffers can pin it.
+ *
+ * Returns true if all buffers were removed.
+ */
+int remove_inode_buffers(struct inode *inode)
+{
+	int ret = 1;
+
+	if (inode_has_buffers(inode)) {
+		struct address_space *mapping = &inode->i_data;
+		struct list_head *list = &mapping->private_list;
+		struct address_space *buffer_mapping = mapping->assoc_mapping;
+
+		spin_lock(&buffer_mapping->private_lock);
+		while (!list_empty(list)) {
+			struct buffer_head *bh = BH_ENTRY(list->next);
+			if (buffer_dirty(bh)) {
+				ret = 0;
+				break;
+			}
+			__remove_assoc_queue(bh);
+		}
+		spin_unlock(&buffer_mapping->private_lock);
+	}
+	return ret;
 }
 
 /*
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	Sun Nov 17 20:30:12 2002
+++ b/fs/char_dev.c	Sun Nov 17 20:30:12 2002
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #define HASH_BITS	6
 #define HASH_SIZE	(1UL << HASH_BITS)
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Sun Nov 17 20:30:14 2002
+++ b/fs/cifs/cifsfs.c	Sun Nov 17 20:30:14 2002
@@ -25,6 +25,7 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/version.h>
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h	Sun Nov 17 20:30:02 2002
+++ b/fs/cifs/cifsproto.h	Sun Nov 17 20:30:02 2002
@@ -55,8 +55,8 @@
 			const struct cifsTconInfo *, int
 			/* length of fixed section (word count) in two byte units  */
 			);
-extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
-extern u64 cifs_UnixTimeToNT(time_t);
+extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
+extern u64 cifs_UnixTimeToNT(struct timespec);
 extern void RevUcode_to_Ucode(char *revUnicode, char *UnicodeName);
 extern void Ucode_to_RevUcode(char *Unicode, char *revUnicodeName);
 extern void RevUcode_to_Ucode_with_Len(char *revUnicode, char *UnicodeName,
diff -Nru a/fs/cifs/md5.c b/fs/cifs/md5.c
--- a/fs/cifs/md5.c	Sun Nov 17 20:30:14 2002
+++ b/fs/cifs/md5.c	Sun Nov 17 20:30:14 2002
@@ -20,7 +20,7 @@
    and to fit the cifs vfs by 
    Steve French sfrench@us.ibm.com */
 
-#include <linux/fs.h>
+#include <linux/string.h>
 #include "md5.h"
 
 static void MD5Transform(__u32 buf[4], __u32 const in[16]);
diff -Nru a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
--- a/fs/cifs/netmisc.c	Sun Nov 17 20:30:15 2002
+++ b/fs/cifs/netmisc.c	Sun Nov 17 20:30:15 2002
@@ -878,23 +878,25 @@
      * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
      * into Unix UTC (based 1970-01-01, in seconds).
      */
-time_t
+struct timespec
 cifs_NTtimeToUnix(u64 ntutc)
 {
+	struct timespec ts; 
 	/* BB what about the timezone? BB */
 
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
 	u64 t;
 
 	t = ntutc - NTFS_TIME_OFFSET;
-	do_div(t, 10000000);
-	return (time_t) t;
+	ts.tv_nsec = do_div(t, 10000000) * 100;
+	ts.tv_sec = t; 
+	return ts;
 }
 
 /* Convert the Unix UTC into NT UTC. */
 u64
-cifs_UnixTimeToNT(time_t t)
+cifs_UnixTimeToNT(struct timespec t)
 {
 	/* Convert to 100ns intervals and then add the NTFS time offset. */
-	return (u64) t *10000000 + NTFS_TIME_OFFSET;
+	return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
 }
diff -Nru a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
--- a/fs/coda/coda_linux.c	Sun Nov 17 20:30:02 2002
+++ b/fs/coda/coda_linux.c	Sun Nov 17 20:30:02 2002
@@ -136,11 +136,11 @@
 	if (attr->va_size != -1)
 		inode->i_blocks = (attr->va_size + 511) >> 9;
 	if (attr->va_atime.tv_sec != -1) 
-	        inode->i_atime = attr->va_atime.tv_sec;
+	        inode->i_atime = attr->va_atime;
 	if (attr->va_mtime.tv_sec != -1)
-	        inode->i_mtime = attr->va_mtime.tv_sec;
+	        inode->i_mtime = attr->va_mtime;
         if (attr->va_ctime.tv_sec != -1)
-	        inode->i_ctime = attr->va_ctime.tv_sec;
+	        inode->i_ctime = attr->va_ctime;
 }
 
 
@@ -162,10 +162,10 @@
         vattr->va_gid = (vgid_t) -1;
         vattr->va_size = (off_t) -1;
 	vattr->va_atime.tv_sec = (time_t) -1;
-        vattr->va_mtime.tv_sec  = (time_t) -1;
-	vattr->va_ctime.tv_sec  = (time_t) -1;
 	vattr->va_atime.tv_nsec =  (time_t) -1;
+        vattr->va_mtime.tv_sec = (time_t) -1;
         vattr->va_mtime.tv_nsec = (time_t) -1;
+	vattr->va_ctime.tv_sec = (time_t) -1;
 	vattr->va_ctime.tv_nsec = (time_t) -1;
         vattr->va_type = C_VNON;
 	vattr->va_fileid = -1;
@@ -206,16 +206,13 @@
                 vattr->va_size = iattr->ia_size;
 	}
         if ( valid & ATTR_ATIME ) {
-                vattr->va_atime.tv_sec = iattr->ia_atime;
-                vattr->va_atime.tv_nsec = 0;
+                vattr->va_atime = iattr->ia_atime;
 	}
         if ( valid & ATTR_MTIME ) {
-                vattr->va_mtime.tv_sec = iattr->ia_mtime;
-                vattr->va_mtime.tv_nsec = 0;
+                vattr->va_mtime = iattr->ia_mtime;
 	}
         if ( valid & ATTR_CTIME ) {
-                vattr->va_ctime.tv_sec = iattr->ia_ctime;
-                vattr->va_ctime.tv_nsec = 0;
+                vattr->va_ctime = iattr->ia_ctime;
 	}
 }
 
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Sun Nov 17 20:30:03 2002
+++ b/fs/dcache.c	Sun Nov 17 20:30:03 2002
@@ -23,7 +23,7 @@
 #include <linux/smp_lock.h>
 #include <linux/cache.h>
 #include <linux/module.h>
-
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 #define DCACHE_PARANOIA 1
@@ -55,15 +55,17 @@
 	.age_limit = 45,
 };
 
-/* no dcache_lock, please */
-static inline void d_free(struct dentry *dentry)
+/*
+ * no dcache_lock, please.  The caller must decrement dentry_stat.nr_dentry
+ * inside dcache_lock.
+ */
+static void d_free(struct dentry *dentry)
 {
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
 	if (dname_external(dentry)) 
 		kfree(dentry->d_name.name);
 	kmem_cache_free(dentry_cache, dentry); 
-	dentry_stat.nr_dentry--;
 }
 
 /*
@@ -149,6 +151,7 @@
 kill_it: {
 		struct dentry *parent;
 		list_del(&dentry->d_child);
+		dentry_stat.nr_dentry--;	/* For d_free, below */
 		/* drops the lock, at that point nobody can reach this dentry */
 		dentry_iput(dentry);
 		parent = dentry->d_parent;
@@ -307,6 +310,7 @@
 
 	list_del_init(&dentry->d_hash);
 	list_del(&dentry->d_child);
+	dentry_stat.nr_dentry--;	/* For d_free, below */
 	dentry_iput(dentry);
 	parent = dentry->d_parent;
 	d_free(dentry);
@@ -569,11 +573,25 @@
 }
 
 /*
- * This is called from kswapd when we think we need some
- * more memory. 
+ * This is called from kswapd when we think we need some more memory.
+ *
+ * We don't want the VM to steal _all_ unused dcache.  Because that leads to
+ * the VM stealing all unused inodes, which shoots down recently-used
+ * pagecache.  So what we do is to tell fibs to the VM about how many reapable
+ * objects there are in this cache.   If the number of unused dentries is
+ * less than half of the total dentry count then return zero.  The net effect
+ * is that the number of unused dentries will be, at a minimum, equal to the
+ * number of used ones.
+ *
+ * If unused_ratio is set to 5, the number of unused dentries will not fall
+ * below 5* the number of used ones.
  */
 static int shrink_dcache_memory(int nr, unsigned int gfp_mask)
 {
+	int nr_used;
+	int nr_unused;
+	const int unused_ratio = 1;
+
 	if (nr) {
 		/*
 		 * Nasty deadlock avoidance.
@@ -589,7 +607,11 @@
 		if (gfp_mask & __GFP_FS)
 			prune_dcache(nr);
 	}
-	return dentry_stat.nr_dentry;
+	nr_unused = dentry_stat.nr_unused;
+	nr_used = dentry_stat.nr_dentry - nr_unused;
+	if (nr_unused < nr_used * unused_ratio)
+		return 0;
+	return nr_unused - nr_used * unused_ratio;
 }
 
 #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
@@ -642,16 +664,20 @@
 	INIT_LIST_HEAD(&dentry->d_lru);
 	INIT_LIST_HEAD(&dentry->d_subdirs);
 	INIT_LIST_HEAD(&dentry->d_alias);
+
 	if (parent) {
 		dentry->d_parent = dget(parent);
 		dentry->d_sb = parent->d_sb;
-		spin_lock(&dcache_lock);
-		list_add(&dentry->d_child, &parent->d_subdirs);
-		spin_unlock(&dcache_lock);
-	} else
+	} else {
 		INIT_LIST_HEAD(&dentry->d_child);
+	}
 
+	spin_lock(&dcache_lock);
+	if (parent)
+		list_add(&dentry->d_child, &parent->d_subdirs);
 	dentry_stat.nr_dentry++;
+	spin_unlock(&dcache_lock);
+
 	return dentry;
 }
 
@@ -1085,9 +1111,9 @@
  *
  * "buflen" should be %PAGE_SIZE or more. Caller holds the dcache_lock.
  */
-char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-		struct dentry *root, struct vfsmount *rootmnt,
-		char *buffer, int buflen)
+static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+			struct dentry *root, struct vfsmount *rootmnt,
+			char *buffer, int buflen)
 {
 	char * end = buffer+buflen;
 	char * retval;
@@ -1138,6 +1164,25 @@
 		memcpy(retval, dentry->d_name.name, namelen);
 	}
 	return retval;
+}
+
+/* write full pathname into buffer and return start of pathname */
+char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+				char *buf, int buflen)
+{
+	char *res;
+	struct vfsmount *rootmnt;
+	struct dentry *root;
+	read_lock(&current->fs->lock);
+	rootmnt = mntget(current->fs->rootmnt);
+	root = dget(current->fs->root);
+	read_unlock(&current->fs->lock);
+	spin_lock(&dcache_lock);
+	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
+	spin_unlock(&dcache_lock);
+	dput(root);
+	mntput(rootmnt);
+	return res;
 }
 
 /*
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Sun Nov 17 20:30:04 2002
+++ b/fs/devfs/base.c	Sun Nov 17 20:30:04 2002
@@ -1902,6 +1902,20 @@
     devfs_put (de);
 }   /*  End Function devfs_find_and_unregister  */
 
+void devfs_remove(const char *fmt, ...)
+{
+	char buf[64];
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n < 64) {
+		devfs_handle_t de = devfs_get_handle(NULL, buf, 0, 0, 0, 0);
+		devfs_unregister(de);
+		devfs_put(de);
+	}
+}
 
 /**
  *	devfs_get_flags - Get the flags for a devfs entry.
@@ -2317,6 +2331,7 @@
 EXPORT_SYMBOL(devfs_mk_dir);
 EXPORT_SYMBOL(devfs_get_handle);
 EXPORT_SYMBOL(devfs_find_and_unregister);
+EXPORT_SYMBOL(devfs_remove);
 EXPORT_SYMBOL(devfs_get_flags);
 EXPORT_SYMBOL(devfs_set_flags);
 EXPORT_SYMBOL(devfs_get_maj_min);
@@ -2494,9 +2509,9 @@
     de->mode = inode->i_mode;
     de->inode.uid = inode->i_uid;
     de->inode.gid = inode->i_gid;
-    de->inode.atime = inode->i_atime;
-    de->inode.mtime = inode->i_mtime;
-    de->inode.ctime = inode->i_ctime;
+    de->inode.atime = inode->i_atime.tv_sec;
+    de->inode.mtime = inode->i_mtime.tv_sec;
+    de->inode.ctime = inode->i_ctime.tv_sec;
     if ( ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) ) &&
 	 !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode,
@@ -2595,9 +2610,12 @@
     inode->i_mode = de->mode;
     inode->i_uid = de->inode.uid;
     inode->i_gid = de->inode.gid;
-    inode->i_atime = de->inode.atime;
-    inode->i_mtime = de->inode.mtime;
-    inode->i_ctime = de->inode.ctime;
+    inode->i_atime.tv_sec = de->inode.atime;
+    inode->i_mtime.tv_sec = de->inode.mtime;
+    inode->i_ctime.tv_sec = de->inode.ctime;
+    inode->i_atime.tv_nsec = 0;
+    inode->i_mtime.tv_nsec = 0;
+    inode->i_ctime.tv_nsec = 0;
     DPRINTK (DEBUG_I_GET, "():   mode: 0%o  uid: %d  gid: %d\n",
 	     (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid);
     return inode;
diff -Nru a/fs/devfs/util.c b/fs/devfs/util.c
--- a/fs/devfs/util.c	Sun Nov 17 20:30:14 2002
+++ b/fs/devfs/util.c	Sun Nov 17 20:30:14 2002
@@ -80,26 +80,30 @@
  *	@de: Any tape device entry in the device directory.
  */
 
-void devfs_register_tape (devfs_handle_t de)
+int devfs_register_tape (devfs_handle_t de)
 {
     int pos;
-    devfs_handle_t parent, slave;
-    char name[16], dest[64];
+    devfs_handle_t slave;
+    char name[32], dest[64];
     static unsigned int tape_counter;
-    static devfs_handle_t tape_dir;
+    int n = tape_counter++;
 
-    if (tape_dir == NULL) tape_dir = devfs_mk_dir (NULL, "tapes", NULL);
-    parent = devfs_get_parent (de);
-    pos = devfs_generate_path (parent, dest + 3, sizeof dest - 3);
-    if (pos < 0) return;
+    pos = devfs_generate_path (de, dest + 3, sizeof dest - 3);
+    if (pos < 0) return -1;
     strncpy (dest + pos, "../", 3);
-    sprintf (name, "tape%u", tape_counter++);
-    devfs_mk_symlink (tape_dir, name, DEVFS_FL_DEFAULT, dest + pos,
-		      &slave, NULL);
-    devfs_auto_unregister (de, slave);
+    sprintf (name, "tapes/tape%u", n);
+    devfs_mk_symlink (NULL, name, DEVFS_FL_DEFAULT, dest + pos, &slave, NULL);
+    return n;
 }   /*  End Function devfs_register_tape  */
 EXPORT_SYMBOL(devfs_register_tape);
 
+void devfs_unregister_tape(int num)
+{
+	if (num >= 0)
+		devfs_remove("tapes/tape%u", num);
+}
+
+EXPORT_SYMBOL(devfs_unregister_tape);
 
 /**
  *	devfs_register_series - Register a sequence of device entries.
diff -Nru a/fs/devpts/inode.c b/fs/devpts/inode.c
--- a/fs/devpts/inode.c	Sun Nov 17 20:30:04 2002
+++ b/fs/devpts/inode.c	Sun Nov 17 20:30:04 2002
@@ -15,6 +15,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #define DEVPTS_SUPER_MAGIC 0x1cd1
 
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Sun Nov 17 20:30:14 2002
+++ b/fs/direct-io.c	Sun Nov 17 20:30:14 2002
@@ -21,6 +21,7 @@
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/rwsem.h>
+#include <linux/uio.h>
 #include <asm/atomic.h>
 
 /*
@@ -410,9 +411,11 @@
 }
 
 /*
- * Attempt tp put the current chunk of 'cur_page' into the current BIO.  If
+ * Attempt to put the current chunk of 'cur_page' into the current BIO.  If
  * that was successful then update final_block_in_bio and take a ref against
  * the just-added page.
+ *
+ * Return zero on success.  Non-zero means the caller needs to start a new BIO.
  */
 static int dio_bio_add_page(struct dio *dio)
 {
@@ -426,6 +429,8 @@
 		dio->final_block_in_bio = dio->cur_page_block +
 			(dio->cur_page_len >> dio->blkbits);
 		ret = 0;
+	} else {
+		ret = 1;
 	}
 	return ret;
 }
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Sun Nov 17 20:30:15 2002
+++ b/fs/dquot.c	Sun Nov 17 20:30:15 2002
@@ -55,6 +55,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/mm.h>
 #include <linux/time.h>
 #include <linux/types.h>
@@ -861,7 +862,7 @@
 
 	if (dquot->dq_dqb.dqb_isoftlimit &&
 	   (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
-	    dquot->dq_dqb.dqb_itime && CURRENT_TIME >= dquot->dq_dqb.dqb_itime &&
+	    dquot->dq_dqb.dqb_itime && get_seconds() >= dquot->dq_dqb.dqb_itime &&
             !ignore_hardlimit(dquot)) {
 		*warntype = ISOFTLONGWARN;
 		return NO_QUOTA;
@@ -871,7 +872,7 @@
 	   (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
 	    dquot->dq_dqb.dqb_itime == 0) {
 		*warntype = ISOFTWARN;
-		dquot->dq_dqb.dqb_itime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
+		dquot->dq_dqb.dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
 	}
 
 	return QUOTA_OK;
@@ -893,7 +894,7 @@
 
 	if (dquot->dq_dqb.dqb_bsoftlimit &&
 	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
-	    dquot->dq_dqb.dqb_btime && CURRENT_TIME >= dquot->dq_dqb.dqb_btime &&
+	    dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
             !ignore_hardlimit(dquot)) {
 		if (!prealloc)
 			*warntype = BSOFTLONGWARN;
@@ -905,7 +906,7 @@
 	    dquot->dq_dqb.dqb_btime == 0) {
 		if (!prealloc) {
 			*warntype = BSOFTWARN;
-			dquot->dq_dqb.dqb_btime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
+			dquot->dq_dqb.dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
 		}
 		else
 			/*
@@ -1404,7 +1405,7 @@
 			dquot->dq_flags &= ~DQ_BLKS;
 		}
 		else if (!(di->dqb_valid & QIF_BTIME))	/* Set grace only if user hasn't provided his own... */
-			dm->dqb_btime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
+			dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
 	}
 	if (check_ilim) {
 		if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) {
@@ -1412,7 +1413,7 @@
 			dquot->dq_flags &= ~DQ_INODES;
 		}
 		else if (!(di->dqb_valid & QIF_ITIME))	/* Set grace only if user hasn't provided his own... */
-			dm->dqb_itime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
+			dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
 	}
 	if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
 		dquot->dq_flags &= ~DQ_FAKE;
diff -Nru a/fs/efs/inode.c b/fs/efs/inode.c
--- a/fs/efs/inode.c	Sun Nov 17 20:30:13 2002
+++ b/fs/efs/inode.c	Sun Nov 17 20:30:13 2002
@@ -92,9 +92,10 @@
 	inode->i_uid   = (uid_t)be16_to_cpu(efs_inode->di_uid);
 	inode->i_gid   = (gid_t)be16_to_cpu(efs_inode->di_gid);
 	inode->i_size  = be32_to_cpu(efs_inode->di_size);
-	inode->i_atime = be32_to_cpu(efs_inode->di_atime);
-	inode->i_mtime = be32_to_cpu(efs_inode->di_mtime);
-	inode->i_ctime = be32_to_cpu(efs_inode->di_ctime);
+	inode->i_atime.tv_sec = be32_to_cpu(efs_inode->di_atime);
+	inode->i_mtime.tv_sec = be32_to_cpu(efs_inode->di_mtime);
+	inode->i_ctime.tv_sec = be32_to_cpu(efs_inode->di_ctime);
+	inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
 
 	/* this is the number of blocks in the file */
 	if (inode->i_size == 0) {
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	Sun Nov 17 20:30:13 2002
+++ b/fs/eventpoll.c	Sun Nov 17 20:30:13 2002
@@ -1,5 +1,5 @@
 /*
- *  drivers/char/eventpoll.c ( Efficent event polling implementation )
+ *  fs/eventpoll.c ( Efficent event polling implementation )
  *  Copyright (C) 2001,...,2002	 Davide Libenzi
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -27,14 +27,16 @@
 #include <linux/list.h>
 #include <linux/hash.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 #include <linux/wait.h>
+#include <linux/eventpoll.h>
+#include <linux/mount.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <asm/atomic.h>
-#include <linux/eventpoll.h>
 
 
 
@@ -65,16 +67,6 @@
 /* Minimum size of the hash in bits ( 2^N ) */
 #define EP_MIN_HASH_BITS 9
 
-/*
- * Event buffer dimension used to cache events before sending them in
- * userspace with a __copy_to_user(). The event buffer is in stack,
- * so keep this size fairly small.
- */
-#define EP_EVENT_BUFF_SIZE 32
-
-/* Maximum number of wait queue we can attach to */
-#define EP_MAX_POLL_QUEUE 2
-
 /* Number of hash entries ( "struct list_head" ) inside a page */
 #define EP_HENTRY_X_PAGE (PAGE_SIZE / sizeof(struct list_head))
 
@@ -91,6 +83,12 @@
 /* Macro to free a "struct epitem" to the slab cache */
 #define DPI_MEM_FREE(p) kmem_cache_free(dpi_cache, p)
 
+/* Macro to allocate a "struct eppoll_entry" from the slab cache */
+#define PWQ_MEM_ALLOC()	(struct eppoll_entry *) kmem_cache_alloc(pwq_cache, SLAB_KERNEL)
+
+/* Macro to free a "struct eppoll_entry" to the slab cache */
+#define PWQ_MEM_FREE(p) kmem_cache_free(pwq_cache, p)
+
 /* Fast test to see if the file is an evenpoll file */
 #define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
 
@@ -107,7 +105,20 @@
 /* Get the "struct epitem" from a wait queue pointer */
 #define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
 
+/* Get the "struct epitem" from an epoll queue wrapper */
+#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->dpi)
 
+/*
+ * This is used to optimize the event transfer to userspace. Since this
+ * is kept on stack, it should be pretty small.
+ */
+#define EP_MAX_BUF_EVENTS 32
+
+/*
+ * Used to optimize ready items collection by reducing the irqlock/irqunlock
+ * switching rate. This is kept in stack too, so do not go wild with this number.
+ */
+#define EP_MAX_COLLECT_ITEMS 64
 
 
 
@@ -117,9 +128,6 @@
  * interface.
  */
 struct eventpoll {
-	/* Used to link to the "struct eventpoll" list ( eplist ) */
-	struct list_head llink;
-
 	/* Protect the this structure access */
 	rwlock_t lock;
 
@@ -141,6 +149,9 @@
 
 /* Wait structure used by the poll hooks */
 struct eppoll_entry {
+	/* List header used to link this structure to the "struct epitem" */
+	struct list_head llink;
+
 	/* The "base" pointer is set to the container "struct epitem" */
 	void *base;
 
@@ -168,8 +179,8 @@
 	/* Number of active wait queue attached to poll operations */
 	int nwait;
 
-	/* Wait queue used to attach poll operations */
-	struct eppoll_entry wait[EP_MAX_POLL_QUEUE];
+	/* List containing poll wait queues */
+	struct list_head pwqlist;
 
 	/* The "container" of this item */
 	struct eventpoll *ep;
@@ -185,6 +196,15 @@
 	 * that the structure will desappear from underneath our processing.
 	 */
 	atomic_t usecnt;
+
+	/* List header used to link this item to the "struct file" items list */
+	struct list_head fllink;
+};
+
+/* Wrapper struct used by poll queueing */
+struct ep_pqueue {
+	poll_table pt;
+	struct epitem *dpi;
 };
 
 
@@ -201,14 +221,18 @@
 static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
 static void ep_use_epitem(struct epitem *dpi);
 static void ep_release_epitem(struct epitem *dpi);
-static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead);
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt);
 static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfile);
 static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int events);
+static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *dpi);
 static int ep_unlink(struct eventpoll *ep, struct epitem *dpi);
 static int ep_remove(struct eventpoll *ep, struct epitem *dpi);
 static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync);
 static int ep_eventpoll_close(struct inode *inode, struct file *file);
 static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
+static int ep_collect_ready_items(struct eventpoll *ep, struct epitem **adpi, int maxdpi);
+static int ep_send_events(struct eventpoll *ep, struct epitem **adpi, int ndpi,
+			  struct pollfd *events);
 static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int maxevents);
 static int ep_poll(struct eventpoll *ep, struct pollfd *events, int maxevents,
 		   int timeout);
@@ -218,16 +242,22 @@
 					      int flags, char *dev_name, void *data);
 
 
-
-/* Use to link togheter all the "struct eventpoll" */
-static struct list_head eplist;
-
-/* Serialize the access to "eplist" */
-static rwlock_t eplock;
+/*
+ * This semaphore is used to ensure that files are not removed
+ * while epoll is using them. Namely the f_op->poll(), since
+ * it has to be called from outside the lock, must be protected.
+ * This is read-held during the event transfer loop to userspace
+ * and it is write-held during the file cleanup path and the epoll
+ * file exit code.
+ */
+struct rw_semaphore epsem;
 
 /* Slab cache used to allocate "struct epitem" */
 static kmem_cache_t *dpi_cache;
 
+/* Slab cache used to allocate "struct eppoll_entry" */
+static kmem_cache_t *pwq_cache;
+
 /* Virtual fs used to allocate inodes for eventpoll files */
 static struct vfsmount *eventpoll_mnt;
 
@@ -267,29 +297,52 @@
 }
 
 
+/* Used to initialize the epoll bits inside the "struct file" */
+void eventpoll_init_file(struct file *file)
+{
+
+	INIT_LIST_HEAD(&file->f_ep_links);
+	spin_lock_init(&file->f_ep_lock);
+}
+
+
 /*
  * This is called from inside fs/file_table.c:__fput() to unlink files
  * from the eventpoll interface. We need to have this facility to cleanup
  * correctly files that are closed without being removed from the eventpoll
  * interface.
  */
-void ep_notify_file_close(struct file *file)
+void eventpoll_release(struct file *file)
 {
-	unsigned long flags;
-	struct list_head *lnk;
-	struct eventpoll *ep;
+	struct list_head *lsthead = &file->f_ep_links;
 	struct epitem *dpi;
 
-	read_lock_irqsave(&eplock, flags);
-	list_for_each(lnk, &eplist) {
-		ep = list_entry(lnk, struct eventpoll, llink);
+	/*
+	 * Fast check to avoid the get/release of the semaphore. Since
+	 * we're doing this outside the semaphore lock, it might return
+	 * false negatives, but we don't care. It'll help in 99.99% of cases
+	 * to avoid the semaphore lock. False positives simply cannot happen
+	 * because the file in on the way to be removed and nobody ( but
+	 * eventpoll ) has still a reference to this file.
+	 */
+	if (list_empty(lsthead))
+		return;
+
+	/*
+	 * We don't want to get "file->f_ep_lock" because it is not
+	 * necessary. It is not necessary because we're in the "struct file"
+	 * cleanup path, and this means that noone is using this file anymore.
+	 * The only hit might come from ep_free() but by holding the semaphore
+	 * will correctly serialize the operation.
+	 */
+	down_write(&epsem);
+	while (!list_empty(lsthead)) {
+		dpi = list_entry(lsthead->next, struct epitem, fllink);
 
-		while ((dpi = ep_find(ep, file))) {
-			ep_remove(ep, dpi);
-			ep_release_epitem(dpi);
-		}
+		EP_LIST_DEL(&dpi->fllink);
+		ep_remove(dpi->ep, dpi);
 	}
-	read_unlock_irqrestore(&eplock, flags);
+	up_write(&epsem);
 }
 
 
@@ -430,14 +483,14 @@
 	if (dpi)
 		ep_release_epitem(dpi);
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u) = %d\n",
-		     current, epfd, op, fd, events, error));
-
 eexit_3:
 	fput(tfile);
 eexit_2:
 	fput(file);
 eexit_1:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u) = %d\n",
+		     current, epfd, op, fd, events, error));
+
 	return error;
 }
 
@@ -487,12 +540,12 @@
 	/* Time to fish for events ... */
 	error = ep_poll(ep, events, maxevents, timeout);
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
-		     current, epfd, events, maxevents, timeout, error));
-
 eexit_2:
 	fput(file);
 eexit_1:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
+		     current, epfd, events, maxevents, timeout, error));
+
 	return error;
 }
 
@@ -608,7 +661,6 @@
 static int ep_file_init(struct file *file, unsigned int hashbits)
 {
 	int error;
-	unsigned long flags;
 	struct eventpoll *ep;
 
 	if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL)))
@@ -624,11 +676,6 @@
 
 	file->private_data = ep;
 
-	/* Add the structure to the linked list that links "struct eventpoll" */
-	write_lock_irqsave(&eplock, flags);
-	list_add(&ep->llink, &eplist);
-	write_unlock_irqrestore(&eplock, flags);
-
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",
 		     current, ep));
 	return 0;
@@ -661,7 +708,6 @@
 	int error;
 	unsigned int i, hsize;
 
-	INIT_LIST_HEAD(&ep->llink);
 	rwlock_init(&ep->lock);
 	init_waitqueue_head(&ep->wq);
 	init_waitqueue_head(&ep->poll_wait);
@@ -686,44 +732,44 @@
 static void ep_free(struct eventpoll *ep)
 {
 	unsigned int i, hsize;
-	unsigned long flags;
-	struct list_head *lsthead;
+	struct list_head *lsthead, *lnk;
+
+	/*
+	 * We need to lock this because we could be hit by
+	 * eventpoll_release() while we're freeing the "struct eventpoll".
+	 */
+	down_write(&epsem);
 
 	/*
-	 * Walks through the whole hash by unregistering file callbacks and
-	 * freeing each "struct epitem".
+	 * Walks through the whole hash by unregistering poll callbacks.
 	 */
 	for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) {
 		lsthead = ep_hash_entry(ep, i);
 
-		/*
-		 * We need to lock this because we could be hit by
-		 * ep_notify_file_close() while we're freeing this.
-		 */
-		write_lock_irqsave(&ep->lock, flags);
-
-		while (!list_empty(lsthead)) {
-			struct epitem *dpi = list_entry(lsthead->next, struct epitem, llink);
+		list_for_each(lnk, lsthead) {
+			struct epitem *dpi = list_entry(lnk, struct epitem, llink);
 
-			/* The function ep_unlink() must be called with held lock */
-			ep_unlink(ep, dpi);
+			ep_unregister_pollwait(ep, dpi);
+		}
+	}
 
-			/* We release the lock before releasing the "struct epitem" */
-			write_unlock_irqrestore(&ep->lock, flags);
+	/*
+	 * Walks through the whole hash by freeing each "struct epitem". At this
+	 * point we are sure no poll callbacks will be lingering around, and also by
+	 * write-holding "epsem" we can be sure that no file cleanup code will hit
+	 * us during this operation. So we can avoid the lock on "ep->lock".
+	 */
+	for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) {
+		lsthead = ep_hash_entry(ep, i);
 
-			ep_release_epitem(dpi);
+		while (!list_empty(lsthead)) {
+			struct epitem *dpi = list_entry(lsthead->next, struct epitem, llink);
 
-			/* And then we reaquire the lock ... */
-			write_lock_irqsave(&ep->lock, flags);
+			ep_remove(ep, dpi);
 		}
-
-		write_unlock_irqrestore(&ep->lock, flags);
 	}
 
-	/* Remove the structure to the linked list that links "struct eventpoll" */
-	write_lock_irqsave(&eplock, flags);
-	EP_LIST_DEL(&ep->llink);
-	write_unlock_irqrestore(&eplock, flags);
+	up_write(&epsem);
 
 	/* Free hash pages */
 	ep_free_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
@@ -791,25 +837,34 @@
  * This is the callback that is used to add our wait queue to the
  * target file wakeup lists.
  */
-static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead)
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt)
 {
-	struct epitem *dpi = priv;
+	struct epitem *dpi = EP_ITEM_FROM_EPQUEUE(pt);
+	struct eppoll_entry *pwq;
 
-	/* No more than EP_MAX_POLL_QUEUE wait queue are supported */
-	if (dpi->nwait < EP_MAX_POLL_QUEUE) {
-		add_wait_queue(whead, &dpi->wait[dpi->nwait].wait);
-		dpi->wait[dpi->nwait].whead = whead;
+	if (dpi->nwait >= 0 && (pwq = PWQ_MEM_ALLOC()))
+	{
+		init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
+		pwq->whead = whead;
+		pwq->base = dpi;
+		add_wait_queue(whead, &pwq->wait);
+		list_add_tail(&pwq->llink, &dpi->pwqlist);
 		dpi->nwait++;
 	}
+	else
+	{
+		/* We have to signal that an error occured */
+		dpi->nwait = -1;
+	}
 }
 
 
 static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfile)
 {
-	int error, i, revents;
+	int error, revents;
 	unsigned long flags;
 	struct epitem *dpi;
-	poll_table pt;
+	struct ep_pqueue epq;
 
 	error = -ENOMEM;
 	if (!(dpi = DPI_MEM_ALLOC()))
@@ -818,19 +873,32 @@
 	/* Item initialization follow here ... */
 	INIT_LIST_HEAD(&dpi->llink);
 	INIT_LIST_HEAD(&dpi->rdllink);
+	INIT_LIST_HEAD(&dpi->fllink);
+	INIT_LIST_HEAD(&dpi->pwqlist);
 	dpi->ep = ep;
 	dpi->file = tfile;
 	dpi->pfd = *pfd;
 	atomic_set(&dpi->usecnt, 1);
 	dpi->nwait = 0;
-	for (i = 0; i < EP_MAX_POLL_QUEUE; i++) {
-		init_waitqueue_func_entry(&dpi->wait[i].wait, ep_poll_callback);
-		dpi->wait[i].whead = NULL;
-		dpi->wait[i].base = dpi;
-	}
 
 	/* Initialize the poll table using the queue callback */
-	poll_initwait_ex(&pt, 1, ep_ptable_queue_proc, dpi);
+	epq.dpi = dpi;
+	init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
+
+	/*
+	 * Attach the item to the poll hooks and get current event bits.
+	 * We can safely use the file* here because its usage count has
+	 * been increased by the caller of this function.
+	 */
+	revents = tfile->f_op->poll(tfile, &epq.pt);
+
+	/*
+	 * We have to check if something went wrong during the poll wait queue
+	 * install process. Namely an allocation for a wait queue failed due
+	 * high memory pressure.
+	 */
+	if (dpi->nwait < 0)
+		goto eexit_2;
 
 	/* We have to drop the new item inside our item list to keep track of it */
 	write_lock_irqsave(&ep->lock, flags);
@@ -838,9 +906,6 @@
 	/* Add the current item to the hash table */
 	list_add(&dpi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile)));
 
-	/* Attach the item to the poll hooks and get current event bits */
-	revents = tfile->f_op->poll(tfile, &pt);
-
 	/* If the file is already "ready" we drop it inside the ready list */
 	if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) {
 		list_add_tail(&dpi->rdllink, &ep->rdllist);
@@ -854,13 +919,29 @@
 
 	write_unlock_irqrestore(&ep->lock, flags);
 
-	poll_freewait(&pt);
+	/* Add the current item to the list of active epoll hook for this file */
+	spin_lock(&tfile->f_ep_lock);
+	list_add_tail(&dpi->fllink, &tfile->f_ep_links);
+	spin_unlock(&tfile->f_ep_lock);
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %d)\n",
 		     current, ep, pfd->fd));
 
 	return 0;
 
+eexit_2:
+	ep_unregister_pollwait(ep, dpi);
+
+	/*
+	 * We need to do this because an event could have been arrived on some
+	 * allocated wait queue.
+	 */
+	write_lock_irqsave(&ep->lock, flags);
+	if (EP_IS_LINKED(&dpi->rdllink))
+		EP_LIST_DEL(&dpi->rdllink);
+	write_unlock_irqrestore(&ep->lock, flags);
+
+	DPI_MEM_FREE(dpi);
 eexit_1:
 	return error;
 }
@@ -874,23 +955,22 @@
 {
 	unsigned int revents;
 	unsigned long flags;
-	poll_table pt;
 
 	/*
-	 * This is a special poll table initialization that will
-	 * make poll_wait() to not perform any wait queue insertion when
-	 * called by file->f_op->poll(). This is a fast way to retrieve
-	 * file events with perform any queue insertion, hence saving CPU cycles.
+	 * Set the new event interest mask before calling f_op->poll(), otherwise
+	 * a potential race might occur. In fact if we do this operation inside
+	 * the lock, an event might happen between the f_op->poll() call and the
+	 * new event set registering.
 	 */
-	poll_initwait_ex(&pt, 0, NULL, NULL);
-
-	write_lock_irqsave(&ep->lock, flags);
+	dpi->pfd.events = events;
 
-	/* Get current event bits */
-	revents = dpi->file->f_op->poll(dpi->file, &pt);
+	/*
+	 * Get current event bits. We can safely use the file* here because
+	 * its usage count has been increased by the caller of this function.
+	 */
+	revents = dpi->file->f_op->poll(dpi->file, NULL);
 
-	/* Set the new event interest mask */
-	dpi->pfd.events = events;
+	write_lock_irqsave(&ep->lock, flags);
 
 	/* If the file is already "ready" we drop it inside the ready list */
 	if ((revents & events) && EP_IS_LINKED(&dpi->llink) &&
@@ -906,26 +986,52 @@
 
 	write_unlock_irqrestore(&ep->lock, flags);
 
-	poll_freewait(&pt);
-
 	return 0;
 }
 
 
 /*
+ * This function unregister poll callbacks from the associated file descriptor.
+ * Since this must be called without holding "ep->lock" the atomic exchange trick
+ * will protect us from multiple unregister.
+ */
+static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *dpi)
+{
+	int nwait;
+	struct list_head *lsthead = &dpi->pwqlist;
+	struct eppoll_entry *pwq;
+
+	/* This is called without locks, so we need the atomic exchange */
+	nwait = xchg(&dpi->nwait, 0);
+
+	if (nwait)
+	{
+		while (!list_empty(lsthead)) {
+			pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
+
+			EP_LIST_DEL(&pwq->llink);
+			remove_wait_queue(pwq->whead, &pwq->wait);
+			PWQ_MEM_FREE(pwq);
+		}
+	}
+}
+
+
+/*
  * Unlink the "struct epitem" from all places it might have been hooked up.
  * This function must be called with write IRQ lock on "ep->lock".
  */
 static int ep_unlink(struct eventpoll *ep, struct epitem *dpi)
 {
-	int i;
+	int error;
 
 	/*
 	 * It can happen that this one is called for an item already unlinked.
 	 * The check protect us from doing a double unlink ( crash ).
 	 */
+	error = -ENOENT;
 	if (!EP_IS_LINKED(&dpi->llink))
-		goto not_linked;
+		goto eexit_1;
 
 	/*
 	 * At this point is safe to do the job, unlink the item from our list.
@@ -934,10 +1040,6 @@
 	 */
 	EP_LIST_DEL(&dpi->llink);
 
-	/* Removes poll wait queue hooks */
-	for (i = 0; i < dpi->nwait; i++)
-		remove_wait_queue(dpi->wait[i].whead, &dpi->wait[i].wait);
-
 	/*
 	 * If the item we are going to remove is inside the ready file descriptors
 	 * we want to remove it from this list to avoid stale events.
@@ -945,12 +1047,13 @@
 	if (EP_IS_LINKED(&dpi->rdllink))
 		EP_LIST_DEL(&dpi->rdllink);
 
-not_linked:
+	error = 0;
+eexit_1:
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %d)\n",
-		     current, ep, dpi->pfd.fd));
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %d) = %d\n",
+		     current, ep, dpi->pfd.fd, error));
 
-	return 0;
+	return error;
 }
 
 
@@ -963,6 +1066,22 @@
 	int error;
 	unsigned long flags;
 
+	/*
+	 * Removes poll wait queue hooks. We _have_ to do this without holding
+	 * the "ep->lock" otherwise a deadlock might occur. This because of the
+	 * sequence of the lock acquisition. Here we do "ep->lock" then the wait
+	 * queue head lock when unregistering the wait queue. The wakeup callback
+	 * will run by holding the wait queue head lock and will call our callback
+	 * that will try to get "ep->lock".
+	 */
+	ep_unregister_pollwait(ep, dpi);
+
+	/* Remove the current item from the list of epoll hooks */
+	spin_lock(&dpi->file->f_ep_lock);
+	if (EP_IS_LINKED(&dpi->fllink))
+		EP_LIST_DEL(&dpi->fllink);
+	spin_unlock(&dpi->file->f_ep_lock);
+
 	/* We need to acquire the write IRQ lock before calling ep_unlink() */
 	write_lock_irqsave(&ep->lock, flags);
 
@@ -974,14 +1093,14 @@
 	if (error)
 		goto eexit_1;
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %d)\n",
-		     current, ep, dpi->pfd.fd));
-
 	/* At this point it is safe to free the eventpoll item */
 	ep_release_epitem(dpi);
 
 	error = 0;
 eexit_1:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %d) = %d\n",
+		     current, ep, dpi->pfd.fd, error));
+
 	return error;
 }
 
@@ -1057,79 +1176,129 @@
 
 
 /*
- * Perform the transfer of events to user space. Optimize the copy by
- * caching EP_EVENT_BUFF_SIZE events at a time and then copying it to user space.
+ * Since we have to release the lock during the __copy_to_user() operation and
+ * during the f_op->poll() call, we try to collect the maximum number of items
+ * by reducing the irqlock/irqunlock switching rate.
  */
-static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int maxevents)
+static int ep_collect_ready_items(struct eventpoll *ep, struct epitem **adpi, int maxdpi)
 {
-	int eventcnt, ebufcnt, revents;
+	int ndpi;
 	unsigned long flags;
 	struct list_head *lsthead = &ep->rdllist;
-	struct pollfd eventbuf[EP_EVENT_BUFF_SIZE];
-	poll_table pt;
-
-	/*
-	 * This is a special poll table initialization that will
-	 * make poll_wait() to not perform any wait queue insertion when
-	 * called by file->f_op->poll(). This is a fast way to retrieve
-	 * file events with perform any queue insertion, hence saving CPU cycles.
-	 */
-	poll_initwait_ex(&pt, 0, NULL, NULL);
 
 	write_lock_irqsave(&ep->lock, flags);
 
-	for (eventcnt = 0, ebufcnt = 0; (eventcnt + ebufcnt) < maxevents && !list_empty(lsthead);) {
+	for (ndpi = 0; ndpi < maxdpi && !list_empty(lsthead);) {
 		struct epitem *dpi = list_entry(lsthead->next, struct epitem, rdllink);
 
 		/* Remove the item from the ready list */
 		EP_LIST_DEL(&dpi->rdllink);
 
 		/*
-		 * If the item is not linked to the main hash table this means that
-		 * it's on the way to be removed and we don't want to send events
-		 * for such file descriptor.
+		 * We need to increase the usage count of the "struct epitem" because
+		 * another thread might call EP_CTL_DEL on this target and make the
+		 * object to vanish underneath our nose.
 		 */
-		if (!EP_IS_LINKED(&dpi->llink))
-			continue;
+		ep_use_epitem(dpi);
 
-		/* Fetch event bits from the signaled file */
-		revents = dpi->file->f_op->poll(dpi->file, &pt);
+		adpi[ndpi++] = dpi;
+	}
+
+	write_unlock_irqrestore(&ep->lock, flags);
+
+	return ndpi;
+}
+
+
+/*
+ * This function is called without holding the "ep->lock" since the call to
+ * __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ
+ * because of the way poll() is traditionally implemented in Linux.
+ */
+static int ep_send_events(struct eventpoll *ep, struct epitem **adpi, int ndpi,
+			  struct pollfd *events)
+{
+	int i, eventcnt, eventbuf, revents;
+	struct epitem *dpi;
+	struct pollfd pfd[EP_MAX_BUF_EVENTS];
+
+	for (i = 0, eventcnt = 0, eventbuf = 0; i < ndpi; i++, adpi++) {
+		dpi = *adpi;
+
+		/* Get the ready file event set */
+		revents = dpi->file->f_op->poll(dpi->file, NULL);
 
 		if (revents & dpi->pfd.events) {
-			eventbuf[ebufcnt] = dpi->pfd;
-			eventbuf[ebufcnt].revents = revents & eventbuf[ebufcnt].events;
-			ebufcnt++;
-
-			/* If our buffer page is full we need to flush it to user space */
-			if (ebufcnt == EP_EVENT_BUFF_SIZE) {
-				/*
-				 * We need to drop the irqlock before using the function
-				 * __copy_to_user() because it might fault.
-				 */
-				write_unlock_irqrestore(&ep->lock, flags);
-				if (__copy_to_user(&events[eventcnt], eventbuf,
-						   ebufcnt * sizeof(struct pollfd))) {
-					poll_freewait(&pt);
+			pfd[eventbuf] = dpi->pfd;
+			pfd[eventbuf].revents = revents & pfd[eventbuf].events;
+			eventbuf++;
+			if (eventbuf == EP_MAX_BUF_EVENTS) {
+				if (__copy_to_user(&events[eventcnt], pfd,
+						   eventbuf * sizeof(struct pollfd))) {
+					for (; i < ndpi; i++, adpi++)
+						ep_release_epitem(*adpi);
 					return -EFAULT;
 				}
-				eventcnt += ebufcnt;
-				ebufcnt = 0;
-				write_lock_irqsave(&ep->lock, flags);
+				eventcnt += eventbuf;
+				eventbuf = 0;
 			}
 		}
+
+		ep_release_epitem(dpi);
 	}
-	write_unlock_irqrestore(&ep->lock, flags);
 
-	/* There might be still something inside our event buffer */
-	if (ebufcnt) {
-		if (__copy_to_user(&events[eventcnt], eventbuf,
-				   ebufcnt * sizeof(struct pollfd)))
-			eventcnt = -EFAULT;
-		else
-			eventcnt += ebufcnt;
+	if (eventbuf) {
+		if (__copy_to_user(&events[eventcnt], pfd,
+				   eventbuf * sizeof(struct pollfd)))
+			return -EFAULT;
+		eventcnt += eventbuf;
+	}
+
+	return eventcnt;
+}
+
+
+/*
+ * Perform the transfer of events to user space.
+ */
+static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int maxevents)
+{
+	int eventcnt, ndpi, sdpi, maxdpi;
+	struct epitem *adpi[EP_MAX_COLLECT_ITEMS];
+
+	/*
+	 * We need to lock this because we could be hit by
+	 * eventpoll_release() while we're transfering
+	 * events to userspace. Read-holding "epsem" will lock
+	 * out eventpoll_release() during the whole
+	 * transfer loop and this will garantie us that the
+	 * file will not vanish underneath our nose when
+	 * we will call f_op->poll() from ep_send_events().
+	 */
+	down_read(&epsem);
+
+	for (eventcnt = 0; eventcnt < maxevents;) {
+		/* Maximum items we can extract this time */
+		maxdpi = min(EP_MAX_COLLECT_ITEMS, maxevents - eventcnt);
+
+		/* Collect/extract ready items */
+		ndpi = ep_collect_ready_items(ep, adpi, maxdpi);
+
+		if (ndpi) {
+			/* Send events to userspace */
+			sdpi = ep_send_events(ep, adpi, ndpi, &events[eventcnt]);
+			if (sdpi < 0) {
+				up_read(&epsem);
+				return sdpi;
+			}
+			eventcnt += sdpi;
+		}
+
+		if (ndpi < maxdpi)
+			break;
 	}
 
-	poll_freewait(&pt);
+	up_read(&epsem);
 
 	return eventcnt;
 }
@@ -1251,41 +1420,49 @@
 {
 	int error;
 
-	/* Initialize the list that will link "struct eventpoll" */
-	INIT_LIST_HEAD(&eplist);
-
-	/* Initialize the rwlock used to access "eplist" */
-	rwlock_init(&eplock);
+	/* Initialize the semaphore used to syncronize the file cleanup code */
+	init_rwsem(&epsem);
 
 	/* Allocates slab cache used to allocate "struct epitem" items */
 	error = -ENOMEM;
-	dpi_cache = kmem_cache_create("eventpoll",
+	dpi_cache = kmem_cache_create("eventpoll dpi",
 				      sizeof(struct epitem),
 				      0,
-				      DPI_SLAB_DEBUG, NULL, NULL);
+				      SLAB_HWCACHE_ALIGN | DPI_SLAB_DEBUG, NULL, NULL);
 	if (!dpi_cache)
 		goto eexit_1;
 
+	/* Allocates slab cache used to allocate "struct eppoll_entry" */
+	error = -ENOMEM;
+	pwq_cache = kmem_cache_create("eventpoll pwq",
+				      sizeof(struct eppoll_entry),
+				      0,
+				      DPI_SLAB_DEBUG, NULL, NULL);
+	if (!pwq_cache)
+		goto eexit_2;
+
 	/*
 	 * Register the virtual file system that will be the source of inodes
 	 * for the eventpoll files
 	 */
 	error = register_filesystem(&eventpoll_fs_type);
 	if (error)
-		goto eexit_2;
+		goto eexit_3;
 
 	/* Mount the above commented virtual file system */
 	eventpoll_mnt = kern_mount(&eventpoll_fs_type);
 	error = PTR_ERR(eventpoll_mnt);
 	if (IS_ERR(eventpoll_mnt))
-		goto eexit_3;
+		goto eexit_4;
 
-	printk(KERN_INFO "[%p] eventpoll: driver installed.\n", current);
+	printk(KERN_INFO "[%p] eventpoll: successfully initialized.\n", current);
 
 	return 0;
 
-eexit_3:
+eexit_4:
 	unregister_filesystem(&eventpoll_fs_type);
+eexit_3:
+	kmem_cache_destroy(pwq_cache);
 eexit_2:
 	kmem_cache_destroy(dpi_cache);
 eexit_1:
@@ -1299,6 +1476,7 @@
 	/* Undo all operations done inside eventpoll_init() */
 	unregister_filesystem(&eventpoll_fs_type);
 	mntput(eventpoll_mnt);
+	kmem_cache_destroy(pwq_cache);
 	kmem_cache_destroy(dpi_cache);
 }
 
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Sun Nov 17 20:30:12 2002
+++ b/fs/exec.c	Sun Nov 17 20:30:12 2002
@@ -43,6 +43,7 @@
 #include <linux/namei.h>
 #include <linux/proc_fs.h>
 #include <linux/ptrace.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	Sun Nov 17 20:30:02 2002
+++ b/fs/ext2/inode.c	Sun Nov 17 20:30:02 2002
@@ -66,7 +66,7 @@
 {
 	if (is_bad_inode(inode))
 		goto no_delete;
-	EXT2_I(inode)->i_dtime	= CURRENT_TIME;
+	EXT2_I(inode)->i_dtime	= get_seconds();
 	mark_inode_dirty(inode);
 	ext2_update_inode(inode, inode_needs_sync(inode));
 
@@ -999,9 +999,10 @@
 	}
 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
 	inode->i_size = le32_to_cpu(raw_inode->i_size);
-	inode->i_atime = le32_to_cpu(raw_inode->i_atime);
-	inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
-	inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
+	inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
+	inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
 	/* We now have enough fields to check if the inode was active or not.
 	 * This is needed because nfsd might try to access dead inodes
@@ -1120,9 +1121,10 @@
 	}
 	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
 	raw_inode->i_size = cpu_to_le32(inode->i_size);
-	raw_inode->i_atime = cpu_to_le32(inode->i_atime);
-	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
-	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
+	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
+	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
+	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
+
 	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
 	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ext2/super.c	Sun Nov 17 20:30:14 2002
@@ -431,7 +431,7 @@
 		printk ("EXT2-fs warning: maximal mount count reached, "
 			"running e2fsck is recommended\n");
 	else if (le32_to_cpu(es->s_checkinterval) &&
-		(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
+		(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds()))
 		printk ("EXT2-fs warning: checktime reached, "
 			"running e2fsck is recommended\n");
 	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
@@ -830,14 +830,14 @@
 static void ext2_commit_super (struct super_block * sb,
 			       struct ext2_super_block * es)
 {
-	es->s_wtime = cpu_to_le32(CURRENT_TIME);
+	es->s_wtime = cpu_to_le32(get_seconds());
 	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
 	sb->s_dirt = 0;
 }
 
 static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
 {
-	es->s_wtime = cpu_to_le32(CURRENT_TIME);
+	es->s_wtime = cpu_to_le32(get_seconds());
 	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
 	ll_rw_block(WRITE, 1, &EXT2_SB(sb)->s_sbh);
 	wait_on_buffer(EXT2_SB(sb)->s_sbh);
@@ -866,7 +866,7 @@
 			ext2_debug ("setting valid to 0\n");
 			es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) &
 						  ~EXT2_VALID_FS);
-			es->s_mtime = cpu_to_le32(CURRENT_TIME);
+			es->s_mtime = cpu_to_le32(get_seconds());
 			ext2_sync_super(sb, es);
 		} else
 			ext2_commit_super (sb, es);
@@ -901,7 +901,7 @@
 		 * the rdonly flag and then mark the partition as valid again.
 		 */
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
-		es->s_mtime = cpu_to_le32(CURRENT_TIME);
+		es->s_mtime = cpu_to_le32(get_seconds());
 	} else {
 		int ret;
 		if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ext2/xattr.c	Sun Nov 17 20:30:14 2002
@@ -77,13 +77,13 @@
 #ifdef EXT2_XATTR_DEBUG
 # define ea_idebug(inode, f...) do { \
 		printk(KERN_DEBUG "inode %s:%ld: ", \
-			kdevname(inode->i_dev), inode->i_ino); \
+			inode->i_sb->s_id, inode->i_ino); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		printk(KERN_DEBUG "block %s:%ld: ", \
-			kdevname(bh->b_dev), bh->b_blocknr); \
+			bdevname(bh->b_bdev), bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ext3/inode.c	Sun Nov 17 20:30:14 2002
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
+#include <linux/uio.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -211,7 +212,7 @@
 	 * (Well, we could do this if we need to, but heck - it works)
 	 */
 	ext3_orphan_del(handle, inode);
-	EXT3_I(inode)->i_dtime	= CURRENT_TIME;
+	EXT3_I(inode)->i_dtime	= get_seconds();
 
 	/* 
 	 * One subtle ordering requirement: if anything has gone wrong
@@ -2218,9 +2219,10 @@
 	}
 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
 	inode->i_size = le32_to_cpu(raw_inode->i_size);
-	inode->i_atime = le32_to_cpu(raw_inode->i_atime);
-	inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
-	inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
+	inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
+	inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
 
 	ei->i_state = 0;
 	ei->i_next_alloc_block = 0;
@@ -2371,9 +2373,9 @@
 	}
 	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
 	raw_inode->i_size = cpu_to_le32(ei->i_disksize);
-	raw_inode->i_atime = cpu_to_le32(inode->i_atime);
-	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
-	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
+	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
+	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
+	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
 	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
 	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Sun Nov 17 20:30:15 2002
+++ b/fs/ext3/super.c	Sun Nov 17 20:30:15 2002
@@ -308,12 +308,12 @@
 /*
  * Open the external journal device
  */
-static struct block_device *ext3_blkdev_get(kdev_t dev)
+static struct block_device *ext3_blkdev_get(dev_t dev)
 {
 	struct block_device *bdev;
 	int err = -ENODEV;
 
-	bdev = bdget(kdev_t_to_nr(dev));
+	bdev = bdget(dev);
 	if (bdev == NULL)
 		goto fail;
 	err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
@@ -769,7 +769,7 @@
 			"running e2fsck is recommended\n");
 	else if (le32_to_cpu(es->s_checkinterval) &&
 		(le32_to_cpu(es->s_lastcheck) +
-			le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
+			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
 		printk (KERN_WARNING
 			"EXT3-fs warning: checktime reached, "
 			"running e2fsck is recommended\n");
@@ -784,7 +784,7 @@
 		es->s_max_mnt_count =
 			(__s16) cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
-	es->s_mtime = cpu_to_le32(CURRENT_TIME);
+	es->s_mtime = cpu_to_le32(get_seconds());
 	ext3_update_dynamic_rev(sb);
 	EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
 
@@ -1422,7 +1422,7 @@
 }
 
 static journal_t *ext3_get_dev_journal(struct super_block *sb,
-				       kdev_t j_dev)
+				       dev_t j_dev)
 {
 	struct buffer_head * bh;
 	journal_t *journal;
@@ -1508,7 +1508,7 @@
 {
 	journal_t *journal;
 	int journal_inum = le32_to_cpu(es->s_journal_inum);
-	kdev_t journal_dev = to_kdev_t(le32_to_cpu(es->s_journal_dev));
+	dev_t journal_dev = le32_to_cpu(es->s_journal_dev);
 	int err = 0;
 	int really_read_only;
 
@@ -1534,7 +1534,7 @@
 		}
 	}
 
-	if (journal_inum && !kdev_none(journal_dev)) {
+	if (journal_inum && journal_dev) {
 		printk(KERN_ERR "EXT3-fs: filesystem has both journal "
 		       "and inode journals!\n");
 		return -EINVAL;
@@ -1617,7 +1617,7 @@
 			       struct ext3_super_block * es,
 			       int sync)
 {
-	es->s_wtime = cpu_to_le32(CURRENT_TIME);
+	es->s_wtime = cpu_to_le32(get_seconds());
 	BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "marking dirty");
 	mark_buffer_dirty(EXT3_SB(sb)->s_sbh);
 	if (sync) {
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ext3/xattr.c	Sun Nov 17 20:30:14 2002
@@ -73,13 +73,13 @@
 #ifdef EXT3_XATTR_DEBUG
 # define ea_idebug(inode, f...) do { \
 		printk(KERN_DEBUG "inode %s:%ld: ", \
-			kdevname(inode->i_dev), inode->i_ino); \
+			inode->i_sb->s_id, inode->i_ino); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		printk(KERN_DEBUG "block %s:%ld: ", \
-			kdevname(bh->b_dev), bh->b_blocknr); \
+			bdevname(bh->b_bdev), bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
diff -Nru a/fs/fat/dir.c b/fs/fat/dir.c
--- a/fs/fat/dir.c	Sun Nov 17 20:30:02 2002
+++ b/fs/fat/dir.c	Sun Nov 17 20:30:02 2002
@@ -752,7 +752,7 @@
 		return PTR_ERR(bh);
 
 	/* zeroed out, so... */
-	fat_date_unix2dos(dir->i_mtime,&time,&date);
+	fat_date_unix2dos(dir->i_mtime.tv_sec,&time,&date);
 	de = (struct msdos_dir_entry*)&bh->b_data[0];
 	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
 	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	Sun Nov 17 20:30:13 2002
+++ b/fs/fat/inode.c	Sun Nov 17 20:30:13 2002
@@ -18,6 +18,7 @@
 #include <linux/msdos_fs.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/mount.h>
 #include <asm/unaligned.h>
 
 /*
@@ -514,7 +515,8 @@
 	MSDOS_I(inode)->mmu_private = inode->i_size;
 
 	MSDOS_I(inode)->i_attrs = 0;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
+	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
+	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
 	MSDOS_I(inode)->i_ctime_ms = 0;
 	inode->i_nlink = fat_subdirs(inode)+2;
 
@@ -1090,7 +1092,7 @@
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
-	inode->i_generation = CURRENT_TIME;
+	inode->i_generation = get_seconds();
 	
 	if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
 		inode->i_generation &= ~1;
@@ -1138,12 +1140,14 @@
 	inode->i_blksize = 1 << sbi->cluster_bits;
 	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
 			   & ~((loff_t)inode->i_blksize - 1)) >> 9;
-	inode->i_mtime = inode->i_atime =
+	inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
 		date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
-	inode->i_ctime =
+	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_sec =
 		MSDOS_SB(sb)->options.isvfat
 		? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))
-		: inode->i_mtime;
+		: inode->i_mtime.tv_sec;
+	inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
 	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
 
 	return 0;
@@ -1190,12 +1194,12 @@
 	    MSDOS_I(inode)->i_attrs;
 	raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
-	fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
+	fat_date_unix2dos(inode->i_mtime.tv_sec,&raw_entry->time,&raw_entry->date);
 	raw_entry->time = CT_LE_W(raw_entry->time);
 	raw_entry->date = CT_LE_W(raw_entry->date);
 	if (MSDOS_SB(sb)->options.isvfat) {
-		fat_date_unix2dos(inode->i_ctime,&raw_entry->ctime,&raw_entry->cdate);
-		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms;
+		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
+		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
 		raw_entry->ctime = CT_LE_W(raw_entry->ctime);
 		raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 	}
diff -Nru a/fs/fifo.c b/fs/fifo.c
--- a/fs/fifo.c	Sun Nov 17 20:30:13 2002
+++ b/fs/fifo.c	Sun Nov 17 20:30:13 2002
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
+#include <linux/pipe_fs_i.h>
 
 static void wait_for_partner(struct inode* inode, unsigned int* cnt)
 {
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Sun Nov 17 20:30:02 2002
+++ b/fs/file_table.c	Sun Nov 17 20:30:02 2002
@@ -14,6 +14,8 @@
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/eventpoll.h>
+#include <linux/mount.h>
+
 
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {0, 0, NR_FILE};
@@ -50,6 +52,7 @@
 			file_list_unlock();
 			return NULL;
 		}
+		eventpoll_init_file(f);
 		atomic_set(&f->f_count,1);
 		f->f_version = 0;
 		f->f_uid = current->fsuid;
@@ -94,6 +97,7 @@
 int init_private_file(struct file *filp, struct dentry *dentry, int mode)
 {
 	memset(filp, 0, sizeof(*filp));
+	eventpoll_init_file(filp);
 	filp->f_mode   = mode;
 	atomic_set(&filp->f_count, 1);
 	filp->f_dentry = dentry;
@@ -121,7 +125,11 @@
 	struct vfsmount * mnt = file->f_vfsmnt;
 	struct inode * inode = dentry->d_inode;
 
-	ep_notify_file_close(file);
+	/*
+	 * The function eventpoll_release() should be the first called
+	 * in the file cleanup chain.
+	 */
+	eventpoll_release(file);
 	locks_remove_flock(file);
 
 	if (file->f_op && file->f_op->release)
diff -Nru a/fs/filesystems.c b/fs/filesystems.c
--- a/fs/filesystems.c	Sun Nov 17 20:30:15 2002
+++ b/fs/filesystems.c	Sun Nov 17 20:30:15 2002
@@ -31,14 +31,22 @@
 /* WARNING: This can be used only if we _already_ own a reference */
 void get_filesystem(struct file_system_type *fs)
 {
-	if (fs->owner)
-		__MOD_INC_USE_COUNT(fs->owner);
+	if (!try_module_get(fs->owner)) {
+#ifdef CONFIG_MODULE_UNLOAD
+		unsigned int cpu = get_cpu();
+		local_inc(&fs->owner->ref[cpu].count);
+		put_cpu();
+#else
+		/* Getting filesystem while it's starting up?  We're
+                   already supposed to have a reference. */
+		BUG();
+#endif
+	}
 }
 
 void put_filesystem(struct file_system_type *fs)
 {
-	if (fs->owner)
-		__MOD_DEC_USE_COUNT(fs->owner);
+	module_put(fs->owner);
 }
 
 static struct file_system_type **find_filesystem(const char *name)
diff -Nru a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
--- a/fs/freevxfs/vxfs_fshead.c	Sun Nov 17 20:30:02 2002
+++ b/fs/freevxfs/vxfs_fshead.c	Sun Nov 17 20:30:02 2002
@@ -36,6 +36,7 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include "vxfs.h"
 #include "vxfs_inode.h"
diff -Nru a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
--- a/fs/freevxfs/vxfs_inode.c	Sun Nov 17 20:30:04 2002
+++ b/fs/freevxfs/vxfs_inode.c	Sun Nov 17 20:30:04 2002
@@ -243,9 +243,12 @@
 	ip->i_nlink = vip->vii_nlink;
 	ip->i_size = vip->vii_size;
 
-	ip->i_atime = vip->vii_atime;
-	ip->i_ctime = vip->vii_ctime;
-	ip->i_mtime = vip->vii_mtime;
+	ip->i_atime.tv_sec = vip->vii_atime;
+	ip->i_ctime.tv_sec = vip->vii_ctime;
+	ip->i_mtime.tv_sec = vip->vii_mtime;
+	ip->i_atime.tv_nsec = 0;
+	ip->i_ctime.tv_nsec = 0;
+	ip->i_mtime.tv_nsec = 0;
 
 	ip->i_blksize = PAGE_SIZE;
 	ip->i_blocks = vip->vii_blocks;
diff -Nru a/fs/hfs/file.c b/fs/hfs/file.c
--- a/fs/hfs/file.c	Sun Nov 17 20:30:12 2002
+++ b/fs/hfs/file.c	Sun Nov 17 20:30:12 2002
@@ -491,7 +491,7 @@
 		if (pos > fork->lsize) {
 			fork->lsize = pos;
 		}
-		entry->modify_date = hfs_u_to_mtime(CURRENT_TIME);
+		entry->modify_date = hfs_u_to_mtime(get_seconds());
 		hfs_cat_mark_dirty(entry);
 	}
 	return written;
diff -Nru a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
--- a/fs/hfs/file_cap.c	Sun Nov 17 20:30:14 2002
+++ b/fs/hfs/file_cap.c	Sun Nov 17 20:30:14 2002
@@ -85,7 +85,7 @@
 	meta->fi_datevalid = HFS_CAP_MDATE | HFS_CAP_CDATE;
 	hfs_put_nl(hfs_m_to_htime(entry->create_date), meta->fi_ctime);
 	hfs_put_nl(hfs_m_to_htime(entry->modify_date), meta->fi_mtime);
-	hfs_put_nl(CURRENT_TIME,                       meta->fi_utime);
+	hfs_put_nl(get_seconds(),                       meta->fi_utime);
 }
 
 static loff_t cap_info_llseek(struct file *file, loff_t offset, int origin)
diff -Nru a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
--- a/fs/hfs/file_hdr.c	Sun Nov 17 20:30:14 2002
+++ b/fs/hfs/file_hdr.c	Sun Nov 17 20:30:14 2002
@@ -333,8 +333,11 @@
 	tmp = hfs_h_to_mtime(dates[1]);
 	if (entry->modify_date != tmp) {
 		entry->modify_date = tmp;
-		inode->i_ctime = inode->i_atime = inode->i_mtime = 
+		inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec = 
 			hfs_h_to_utime(dates[1]);
+		inode->i_ctime.tv_nsec = 0;
+		inode->i_mtime.tv_nsec = 0;
+		inode->i_atime.tv_nsec = 0;
 		hfs_cat_mark_dirty(entry);
 	}
 	tmp = hfs_h_to_mtime(dates[2]);
diff -Nru a/fs/hfs/inode.c b/fs/hfs/inode.c
--- a/fs/hfs/inode.c	Sun Nov 17 20:30:16 2002
+++ b/fs/hfs/inode.c	Sun Nov 17 20:30:16 2002
@@ -190,7 +190,7 @@
 
 	/* Change the catalog entry if needed */
 	if (attr->ia_valid & ATTR_MTIME) {
-		entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
+		entry->modify_date = hfs_u_to_mtime(inode->i_mtime.tv_sec);
 		hfs_cat_mark_dirty(entry);
 	}
 	if (attr->ia_valid & ATTR_MODE) {
@@ -323,8 +323,11 @@
 		struct hfs_sb_info *hsb = HFS_SB(sb);
 
 		inode->i_rdev = NODEV;
-		inode->i_ctime = inode->i_atime = inode->i_mtime =
+		inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec =
 					hfs_m_to_utime(entry->modify_date);
+		inode->i_ctime.tv_nsec = 0;
+		inode->i_mtime.tv_nsec = 0;
+		inode->i_atime.tv_nsec = 0;
 		inode->i_blksize = HFS_SECTOR_SIZE;
 		inode->i_uid = hsb->s_uid;
 		inode->i_gid = hsb->s_gid;
diff -Nru a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
--- a/fs/hfs/sysdep.c	Sun Nov 17 20:30:14 2002
+++ b/fs/hfs/sysdep.c	Sun Nov 17 20:30:14 2002
@@ -99,9 +99,9 @@
 	lock_kernel();
 	if (inode && 
 	    (diff = (hfs_to_utc(0) - HFS_I(inode)->tz_secondswest))) {
-		inode->i_ctime += diff;
-		inode->i_atime += diff;
-		inode->i_mtime += diff;
+		inode->i_ctime.tv_sec += diff;
+		inode->i_atime.tv_sec += diff;
+		inode->i_mtime.tv_sec += diff;
 		HFS_I(inode)->tz_secondswest += diff;
 	}
 	unlock_kernel();
diff -Nru a/fs/hpfs/dir.c b/fs/hpfs/dir.c
--- a/fs/hpfs/dir.c	Sun Nov 17 20:30:12 2002
+++ b/fs/hpfs/dir.c	Sun Nov 17 20:30:12 2002
@@ -263,11 +263,14 @@
 	 * inode.
 	 */
 
-	if (!result->i_ctime) {
-		if (!(result->i_ctime = local_to_gmt(dir->i_sb, de->creation_date)))
-			result->i_ctime = 1;
-		result->i_mtime = local_to_gmt(dir->i_sb, de->write_date);
-		result->i_atime = local_to_gmt(dir->i_sb, de->read_date);
+	if (!result->i_ctime.tv_sec) {
+		if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date)))
+			result->i_ctime.tv_sec = 1;
+		result->i_ctime.tv_nsec = 0;
+		result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date);
+		result->i_mtime.tv_nsec = 0;
+		result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date);
+		result->i_atime.tv_nsec = 0;
 		hpfs_result->i_ea_size = de->ea_size;
 		if (!hpfs_result->i_ea_mode && de->read_only)
 			result->i_mode &= ~0222;
diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c
--- a/fs/hpfs/inode.c	Sun Nov 17 20:30:12 2002
+++ b/fs/hpfs/inode.c	Sun Nov 17 20:30:12 2002
@@ -88,9 +88,9 @@
 	hpfs_inode->i_rddir_off = NULL;
 	hpfs_inode->i_dirty = 0;
 
-	i->i_atime = 0;
-	i->i_mtime = 0;
-	i->i_ctime = 0;
+	i->i_ctime.tv_sec = i->i_ctime.tv_nsec = 0;
+	i->i_mtime.tv_sec = i->i_mtime.tv_nsec = 0;
+	i->i_atime.tv_sec = i->i_atime.tv_nsec = 0;
 
 	if (!hpfs_sb(i->i_sb)->sb_rd_inode)
 		hpfs_error(i->i_sb, "read_inode: sb_rd_inode == 0");
@@ -278,9 +278,9 @@
 	}
 	hpfs_write_inode_ea(i, fnode);
 	if (de) {
-		de->write_date = gmt_to_local(i->i_sb, i->i_mtime);
-		de->read_date = gmt_to_local(i->i_sb, i->i_atime);
-		de->creation_date = gmt_to_local(i->i_sb, i->i_ctime);
+		de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
+		de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
+		de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
 		de->read_only = !(i->i_mode & 0222);
 		de->ea_size = hpfs_inode->i_ea_size;
 		hpfs_mark_4buffers_dirty(&qbh);
@@ -288,9 +288,9 @@
 	}
 	if (S_ISDIR(i->i_mode)) {
 		if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) {
-			de->write_date = gmt_to_local(i->i_sb, i->i_mtime);
-			de->read_date = gmt_to_local(i->i_sb, i->i_atime);
-			de->creation_date = gmt_to_local(i->i_sb, i->i_ctime);
+			de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
+			de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
+			de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
 			de->read_only = !(i->i_mode & 0222);
 			de->ea_size = /*hpfs_inode->i_ea_size*/0;
 			de->file_size = 0;
diff -Nru a/fs/hpfs/namei.c b/fs/hpfs/namei.c
--- a/fs/hpfs/namei.c	Sun Nov 17 20:30:13 2002
+++ b/fs/hpfs/namei.c	Sun Nov 17 20:30:13 2002
@@ -36,7 +36,7 @@
 	/*dee.archive = 0;*/
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
-	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
+	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
 	hpfs_lock_inode(dir);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1) goto bail2;
@@ -61,7 +61,7 @@
 	dnode->root_dnode = 1;
 	dnode->up = fno;
 	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
-	de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
+	de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, get_seconds());
 	if (!(mode & 0222)) de->read_only = 1;
 	de->first = de->directory = 1;
 	/*de->hidden = de->system = 0;*/
@@ -74,7 +74,10 @@
 	hpfs_lock_iget(dir->i_sb, 1);
 	if ((result = iget(dir->i_sb, fno))) {
 		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_nsec = 0; 
+		result->i_mtime.tv_nsec = 0; 
+		result->i_atime.tv_nsec = 0; 
 		hpfs_i(result)->i_ea_size = 0;
 		if (dee.read_only) result->i_mode &= ~0222;
 		if (result->i_uid != current->fsuid ||
@@ -123,7 +126,7 @@
 	dee.archive = 1;
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
-	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
+	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
 	hpfs_lock_inode(dir);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1) goto bail1;
@@ -143,7 +146,10 @@
 	if ((result = iget(dir->i_sb, fno))) {
 		hpfs_decide_conv(result, (char *)name, len);
 		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_nsec = 0;
+		result->i_mtime.tv_nsec = 0;
+		result->i_atime.tv_nsec = 0;
 		hpfs_i(result)->i_ea_size = 0;
 		if (dee.read_only) result->i_mode &= ~0222;
 		if (result->i_blocks == -1) result->i_blocks = 1;
@@ -195,7 +201,7 @@
 	dee.archive = 1;
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
-	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
+	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
 	hpfs_lock_inode(dir);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1) goto bail1;
@@ -213,7 +219,10 @@
 	hpfs_lock_iget(dir->i_sb, 2);
 	if ((result = iget(dir->i_sb, fno))) {
 		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_nsec = 0;
+		result->i_mtime.tv_nsec = 0;
+		result->i_atime.tv_nsec = 0;
 		hpfs_i(result)->i_ea_size = 0;
 		/*if (result->i_blocks == -1) result->i_blocks = 1;
 		if (result->i_size == -1) result->i_size = 0;*/
@@ -264,7 +273,7 @@
 	dee.archive = 1;
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
-	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
+	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
 	hpfs_lock_inode(dir);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1) goto bail1;
@@ -283,7 +292,10 @@
 	hpfs_lock_iget(dir->i_sb, 2);
 	if ((result = iget(dir->i_sb, fno))) {
 		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+		result->i_ctime.tv_nsec = 0;
+		result->i_mtime.tv_nsec = 0;
+		result->i_atime.tv_nsec = 0;
 		hpfs_i(result)->i_ea_size = 0;
 		/*if (result->i_blocks == -1) result->i_blocks = 1;
 		if (result->i_size == -1) result->i_size = 0;*/
diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c
--- a/fs/hpfs/super.c	Sun Nov 17 20:30:14 2002
+++ b/fs/hpfs/super.c	Sun Nov 17 20:30:14 2002
@@ -608,9 +608,12 @@
 		de = map_dirent(s->s_root->d_inode, root_dno, "\001\001", 2, NULL, &qbh);
 	if (!root_dno || !de) hpfs_error(s, "unable to find root dir");
 	else {
-		s->s_root->d_inode->i_atime = local_to_gmt(s, de->read_date);
-		s->s_root->d_inode->i_mtime = local_to_gmt(s, de->write_date);
-		s->s_root->d_inode->i_ctime = local_to_gmt(s, de->creation_date);
+		s->s_root->d_inode->i_atime.tv_sec = local_to_gmt(s, de->read_date);
+		s->s_root->d_inode->i_atime.tv_nsec = 0;
+		s->s_root->d_inode->i_mtime.tv_sec = local_to_gmt(s, de->write_date);
+		s->s_root->d_inode->i_mtime.tv_nsec = 0;
+		s->s_root->d_inode->i_ctime.tv_sec = local_to_gmt(s, de->creation_date);
+		s->s_root->d_inode->i_ctime.tv_nsec = 0;
 		hpfs_i(s->s_root->d_inode)->i_ea_size = de->ea_size;
 		hpfs_i(s->s_root->d_inode)->i_parent_dir = s->s_root->d_inode->i_ino;
 		if (s->s_root->d_inode->i_size == -1) s->s_root->d_inode->i_size = 2048;
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/hugetlbfs/inode.c	Sun Nov 17 20:30:15 2002
@@ -11,6 +11,7 @@
 #include <asm/current.h>
 #include <linux/sched.h>		/* remove ASAP */
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/file.h>
 #include <linux/writeback.h>
 #include <linux/pagemap.h>
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Sun Nov 17 20:30:16 2002
+++ b/fs/inode.c	Sun Nov 17 20:30:16 2002
@@ -371,6 +371,8 @@
 		return 0;
 	if (atomic_read(&inode->i_count))
 		return 0;
+	if (inode->i_data.nrpages)
+		return 0;
 	return 1;
 }
 
@@ -383,6 +385,9 @@
  * the front of the inode_unused list.  So look for it there and if the
  * inode is still freeable, proceed.  The right inode is found 99.9% of the
  * time in testing on a 4-way.
+ *
+ * If the inode has metadata buffers attached to mapping->private_list then
+ * try to remove them.
  */
 static void prune_icache(int nr_to_scan)
 {
@@ -399,14 +404,15 @@
 
 		inode = list_entry(inode_unused.prev, struct inode, i_list);
 
-		if (!can_unuse(inode)) {
+		if (inode->i_state || atomic_read(&inode->i_count)) {
 			list_move(&inode->i_list, &inode_unused);
 			continue;
 		}
-		if (inode->i_data.nrpages) {
+		if (inode_has_buffers(inode) || inode->i_data.nrpages) {
 			__iget(inode);
 			spin_unlock(&inode_lock);
-			invalidate_inode_pages(&inode->i_data);
+			if (remove_inode_buffers(inode))
+				invalidate_inode_pages(&inode->i_data);
 			iput(inode);
 			spin_lock(&inode_lock);
 
@@ -415,8 +421,6 @@
 				continue;	/* wrong inode or list_empty */
 			if (!can_unuse(inode))
 				continue;
-			if (inode->i_data.nrpages)
-				continue;
 		}
 		list_del_init(&inode->i_hash);
 		list_move(&inode->i_list, &freeable);
@@ -1067,7 +1071,10 @@
  
 void update_atime(struct inode *inode)
 {
-	if (inode->i_atime == CURRENT_TIME)
+	struct timespec now = CURRENT_TIME; 
+
+	/* Can later do this more lazily with a per superblock interval */
+	if (timespec_equal(&inode->i_atime, &now))
 		return;
 	if (IS_NOATIME(inode))
 		return;
@@ -1075,9 +1082,32 @@
 		return;
 	if (IS_RDONLY(inode))
 		return;
-	inode->i_atime = CURRENT_TIME;
+	inode->i_atime = now;
+	mark_inode_dirty_sync(inode);
+}
+
+/**
+ *	inode_update_time	-	update mtime and ctime time
+ *	@inode: inode accessed
+ *	@ctime_too: update ctime too
+ *
+ *	Update the mtime time on an inode and mark it for writeback.
+ *	This function automatically handles read only file systems and media.
+ *	When ctime_too is specified update the ctime too.
+ */
+
+void inode_update_time(struct inode *inode, int ctime_too)
+{
+	struct timespec now = CURRENT_TIME; 
+	if (timespec_equal(&inode->i_mtime, &now) &&
+	    !(ctime_too && !timespec_equal(&inode->i_ctime, &now)))
+		return;
+	inode->i_mtime = now;
+	if (ctime_too) 
+		inode->i_ctime = now;
 	mark_inode_dirty_sync(inode);
 }
+EXPORT_SYMBOL(inode_update_time);
 
 int inode_needs_sync(struct inode *inode)
 {
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Sun Nov 17 20:30:14 2002
+++ b/fs/intermezzo/file.c	Sun Nov 17 20:30:14 2002
@@ -496,7 +496,7 @@
 
         /* FIXME: take a lock here */
 
-        if (dentry->d_inode->i_atime > CURRENT_TIME - 5) {
+        if (dentry->d_inode->i_atime.tv_sec > get_seconds() - 5) {
                 /* We lost the race; this file was accessed while we were doing
                  * ioctls and lookups and whatnot. */
                 rc = -EBUSY;
diff -Nru a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c
--- a/fs/intermezzo/journal.c	Sun Nov 17 20:30:02 2002
+++ b/fs/intermezzo/journal.c	Sun Nov 17 20:30:02 2002
@@ -420,7 +420,7 @@
 
         /* record number needs to be filled in after reservation 
            s.recno = cpu_to_le32(rec->recno); */ 
-        s.time = cpu_to_le32(CURRENT_TIME);
+        s.time = cpu_to_le32(get_seconds());
         s.len = p->len;
         return logit(buf, &s, sizeof(s));
 }
@@ -1548,8 +1548,8 @@
         uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
         gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
         fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
-        mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0;
-        ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0;
+        mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime.tv_sec): 0;
+        ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime.tv_sec): 0;
         flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
                 cpu_to_le32(iattr->ia_attr_flags): 0;
 
diff -Nru a/fs/intermezzo/psdev.c b/fs/intermezzo/psdev.c
--- a/fs/intermezzo/psdev.c	Sun Nov 17 20:30:12 2002
+++ b/fs/intermezzo/psdev.c	Sun Nov 17 20:30:12 2002
@@ -311,8 +311,6 @@
 
         file->private_data = NULL;  
 
-        MOD_INC_USE_COUNT;
-
         CDEBUG(D_PSDEV, "Psdev_open: caller: %d, flags: %d\n", current->pid, file->f_flags);
 
         EXIT;
@@ -333,7 +331,6 @@
                 return -EBADF;
         }
 
-        MOD_DEC_USE_COUNT;
         CDEBUG(D_PSDEV, "Lento: pid %d\n", current->pid);
         channel->uc_pid = 0;
 
@@ -369,6 +366,7 @@
 }
 
 static struct file_operations presto_psdev_fops = {
+	.owner	 = THIS_MODULE,
         .read    = presto_psdev_read,
         .write   = presto_psdev_write,
         .poll    = presto_psdev_poll,
diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c
--- a/fs/intermezzo/super.c	Sun Nov 17 20:30:16 2002
+++ b/fs/intermezzo/super.c	Sun Nov 17 20:30:16 2002
@@ -246,14 +246,11 @@
         CDEBUG(D_SUPER, "Presto: type=%s, fset=%s, dev= %d, flags %x\n",
                cache_type, fileset?fileset:"NULL", minor, cache->cache_flags);
 
-        MOD_INC_USE_COUNT;
-
         /* get the filter for the cache */
         fstype = get_fs_type(cache_type);
         cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
         if ( !fstype || !cache->cache_filter) {
                 CERROR("Presto: unrecognized fs type or cache type\n");
-                MOD_DEC_USE_COUNT;
                 EXIT;
                 goto out_err;
         }
@@ -262,7 +259,6 @@
 
         if ( !sb || IS_ERR(sb)) {
                 CERROR("InterMezzo: cache mount failure.\n");
-                MOD_DEC_USE_COUNT;
                 EXIT;
                 goto out_err;
         }
@@ -270,7 +266,6 @@
         /* can we in fact mount the cache */ 
         if (sb->s_bdev && (strcmp(fstype->name, "vintermezzo") == 0)) {
                 CERROR("vintermezzo must not be used with a  block device\n");
-                MOD_DEC_USE_COUNT;
                 EXIT;
                 goto out_err;
         }
diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
--- a/fs/intermezzo/vfs.c	Sun Nov 17 20:30:12 2002
+++ b/fs/intermezzo/vfs.c	Sun Nov 17 20:30:12 2002
@@ -475,7 +475,7 @@
                name, iattr->ia_valid, iattr->ia_mode, iattr->ia_uid,
                iattr->ia_gid, iattr->ia_size);
         CDEBUG(D_PIOCTL, "atime %#lx, mtime %#lx, ctime %#lx, attr_flags %#x\n",
-               iattr->ia_atime, iattr->ia_mtime, iattr->ia_ctime,
+               iattr->ia_atime, iattr->ia_mtime.tv_sec, iattr->ia_ctime.tv_sec,
                iattr->ia_attr_flags);
         CDEBUG(D_PIOCTL, "offset %d, recno %d, flags %#x\n",
                info->slot_offset, info->recno, info->flags);
diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c
--- a/fs/isofs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/isofs/inode.c	Sun Nov 17 20:30:15 2002
@@ -1279,8 +1279,11 @@
 	}
 #endif
 
-	inode->i_mtime = inode->i_atime = inode->i_ctime =
+	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec =
 		iso_date(de->date, high_sierra);
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
 
 	ei->i_first_extent = (isonum_733 (de->extent) +
 			      isonum_711 (de->ext_attr_length));
diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c
--- a/fs/isofs/rock.c	Sun Nov 17 20:30:14 2002
+++ b/fs/isofs/rock.c	Sun Nov 17 20:30:14 2002
@@ -308,14 +308,22 @@
 	/* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
 	   Try to handle this correctly for either case. */
 	cnt = 0; /* Rock ridge never appears on a High Sierra disk */
-	if(rr->u.TF.flags & TF_CREATE) 
-	  inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
-	if(rr->u.TF.flags & TF_MODIFY) 
-	  inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
-	if(rr->u.TF.flags & TF_ACCESS) 
-	  inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
-	if(rr->u.TF.flags & TF_ATTRIBUTES) 
-	  inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
+	if(rr->u.TF.flags & TF_CREATE) { 
+	  inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
+	  inode->i_ctime.tv_nsec = 0;
+	}
+	if(rr->u.TF.flags & TF_MODIFY) {
+	  inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
+	  inode->i_mtime.tv_nsec = 0;
+	}
+	if(rr->u.TF.flags & TF_ACCESS) {
+	  inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
+	  inode->i_atime.tv_nsec = 0;
+	}
+	if(rr->u.TF.flags & TF_ATTRIBUTES) { 
+	  inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
+	  inode->i_ctime.tv_nsec = 0;
+	} 
 	break;
       case SIG('S','L'):
 	{int slen;
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Sun Nov 17 20:30:14 2002
+++ b/fs/jffs/inode-v23.c	Sun Nov 17 20:30:14 2002
@@ -307,15 +307,15 @@
 		inode->i_mtime = inode->i_ctime;
 	}
 	if (update_all || iattr->ia_valid & ATTR_ATIME) {
-		raw_inode.atime = iattr->ia_atime;
+		raw_inode.atime = iattr->ia_atime.tv_sec;
 		inode->i_atime = iattr->ia_atime;
 	}
 	if (update_all || iattr->ia_valid & ATTR_MTIME) {
-		raw_inode.mtime = iattr->ia_mtime;
+		raw_inode.mtime = iattr->ia_mtime.tv_sec;
 		inode->i_mtime = iattr->ia_mtime;
 	}
 	if (update_all || iattr->ia_valid & ATTR_CTIME) {
-		raw_inode.ctime = iattr->ia_ctime;
+		raw_inode.ctime = iattr->ia_ctime.tv_sec;
 		inode->i_ctime = iattr->ia_ctime;
 	}
 
@@ -364,9 +364,12 @@
 	inode->i_gid = raw_inode->gid;
 	inode->i_rdev = NODEV;
 	inode->i_size = raw_inode->dsize;
-	inode->i_atime = raw_inode->atime;
-	inode->i_mtime = raw_inode->mtime;
-	inode->i_ctime = raw_inode->ctime;
+	inode->i_atime.tv_sec = raw_inode->atime;
+	inode->i_mtime.tv_sec = raw_inode->mtime;
+	inode->i_ctime.tv_sec = raw_inode->ctime;
+	inode->i_ctime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
 	inode->i_blksize = PAGE_SIZE;
 	inode->i_blocks = (inode->i_size + 511) >> 9;
 
@@ -486,7 +489,7 @@
 	raw_inode.uid = f->uid;
 	raw_inode.gid = f->gid;
 #endif
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = raw_inode.atime;
 	raw_inode.ctime = f->ctime;
 	raw_inode.offset = 0;
@@ -868,7 +871,7 @@
 	raw_inode.uid = current->fsuid;
 	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
 	/*	raw_inode.gid = current->fsgid; */
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = raw_inode.atime;
 	raw_inode.ctime = raw_inode.atime;
 	raw_inode.offset = 0;
@@ -1031,7 +1034,7 @@
 	raw_inode.mode = del_f->mode;
 	raw_inode.uid = current->fsuid;
 	raw_inode.gid = current->fsgid;
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = del_f->mtime;
 	raw_inode.ctime = raw_inode.atime;
 	raw_inode.offset = 0;
@@ -1107,7 +1110,7 @@
 	raw_inode.uid = current->fsuid;
 	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
 	/*	raw_inode.gid = current->fsgid; */
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = raw_inode.atime;
 	raw_inode.ctime = raw_inode.atime;
 	raw_inode.offset = 0;
@@ -1217,7 +1220,7 @@
 	raw_inode.mode = S_IFLNK | S_IRWXUGO;
 	raw_inode.uid = current->fsuid;
 	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = raw_inode.atime;
 	raw_inode.ctime = raw_inode.atime;
 	raw_inode.offset = 0;
@@ -1319,7 +1322,7 @@
 	raw_inode.mode = mode;
 	raw_inode.uid = current->fsuid;
 	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	raw_inode.atime = CURRENT_TIME;
+	raw_inode.atime = get_seconds();
 	raw_inode.mtime = raw_inode.atime;
 	raw_inode.ctime = raw_inode.atime;
 	raw_inode.offset = 0;
@@ -1452,7 +1455,7 @@
 
 		raw_inode.uid = f->uid;
 		raw_inode.gid = f->gid;
-		raw_inode.atime = CURRENT_TIME;
+		raw_inode.atime = get_seconds();
 		raw_inode.mtime = raw_inode.atime;
 		raw_inode.ctime = f->ctime;
 		raw_inode.offset = pos;
@@ -1702,9 +1705,13 @@
 	inode->i_uid = f->uid;
 	inode->i_gid = f->gid;
 	inode->i_size = f->size;
-	inode->i_atime = f->atime;
-	inode->i_mtime = f->mtime;
-	inode->i_ctime = f->ctime;
+	inode->i_atime.tv_sec = f->atime;
+	inode->i_mtime.tv_sec = f->mtime;
+	inode->i_ctime.tv_sec = f->ctime;
+	inode->i_atime.tv_nsec = 
+	inode->i_mtime.tv_nsec = 
+	inode->i_ctime.tv_nsec = 0;
+
 	inode->i_blksize = PAGE_SIZE;
 	inode->i_blocks = (inode->i_size + 511) >> 9;
 	if (S_ISREG(inode->i_mode)) {
diff -Nru a/fs/jffs/intrep.c b/fs/jffs/intrep.c
--- a/fs/jffs/intrep.c	Sun Nov 17 20:30:14 2002
+++ b/fs/jffs/intrep.c	Sun Nov 17 20:30:14 2002
@@ -530,7 +530,7 @@
 	root->ino = JFFS_MIN_INO;
 	root->mode = S_IFDIR | S_IRWXU | S_IRGRP
 		     | S_IXGRP | S_IROTH | S_IXOTH;
-	root->atime = root->mtime = root->ctime = CURRENT_TIME;
+	root->atime = root->mtime = root->ctime = get_seconds();
 	root->nlink = 1;
 	root->c = c;
 	root->version_head = root->version_tail = node;
diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c	Sun Nov 17 20:30:15 2002
+++ b/fs/jffs2/dir.c	Sun Nov 17 20:30:15 2002
@@ -211,7 +211,8 @@
 		return ret;
 	}
 
-	dir_i->i_mtime = dir_i->i_ctime = ri->ctime;
+	dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = ri->ctime;
+	dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
 
 	jffs2_free_raw_inode(ri);
 	d_instantiate(dentry, inode);
@@ -377,7 +378,7 @@
 	rd->pino = dir_i->i_ino;
 	rd->version = ++dir_f->highest_version;
 	rd->ino = inode->i_ino;
-	rd->mctime = CURRENT_TIME;
+	rd->mctime = get_seconds();
 	rd->nsize = namelen;
 	rd->type = DT_LNK;
 	rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
@@ -395,7 +396,8 @@
 		return PTR_ERR(fd);
 	}
 
-	dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
+	dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime;
+	dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
 
 	jffs2_free_raw_dirent(rd);
 
@@ -514,7 +516,7 @@
 	rd->pino = dir_i->i_ino;
 	rd->version = ++dir_f->highest_version;
 	rd->ino = inode->i_ino;
-	rd->mctime = CURRENT_TIME;
+	rd->mctime = get_seconds();
 	rd->nsize = namelen;
 	rd->type = DT_DIR;
 	rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
@@ -532,7 +534,8 @@
 		return PTR_ERR(fd);
 	}
 
-	dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
+	dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime;
+	dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
 	dir_i->i_nlink++;
 
 	jffs2_free_raw_dirent(rd);
@@ -674,7 +677,7 @@
 	rd->pino = dir_i->i_ino;
 	rd->version = ++dir_f->highest_version;
 	rd->ino = inode->i_ino;
-	rd->mctime = CURRENT_TIME;
+	rd->mctime = get_seconds();
 	rd->nsize = namelen;
 
 	/* XXX: This is ugly. */
@@ -695,7 +698,8 @@
 		return PTR_ERR(fd);
 	}
 
-	dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
+	dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime;
+	dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
 
 	jffs2_free_raw_dirent(rd);
 
diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c
--- a/fs/jffs2/file.c	Sun Nov 17 20:30:16 2002
+++ b/fs/jffs2/file.c	Sun Nov 17 20:30:16 2002
@@ -156,9 +156,9 @@
 		ri->mode &= ~S_ISGID;
 
 	ri->isize = (ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size;
-	ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime;
-	ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime;
-	ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime;
+	ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime.tv_sec:inode->i_atime.tv_sec;
+	ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime.tv_sec:inode->i_mtime.tv_sec;
+	ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime.tv_sec:inode->i_ctime.tv_sec;
 
 	ri->offset = 0;
 	ri->csize = ri->dsize = mdatalen;
@@ -186,9 +186,12 @@
 		return PTR_ERR(new_metadata);
 	}
 	/* It worked. Update the inode */
-	inode->i_atime = ri->atime;
-	inode->i_ctime = ri->ctime;
-	inode->i_mtime = ri->mtime;
+	inode->i_atime.tv_sec = ri->atime;
+	inode->i_ctime.tv_sec = ri->ctime;
+	inode->i_mtime.tv_sec = ri->mtime;
+	inode->i_atime.tv_nsec =
+	inode->i_ctime.tv_nsec =
+	inode->i_mtime.tv_nsec = 0;
 	inode->i_mode = ri->mode;
 	inode->i_uid = ri->uid;
 	inode->i_gid = ri->gid;
@@ -309,7 +312,7 @@
 		ri.uid = inode->i_uid;
 		ri.gid = inode->i_gid;
 		ri.isize = max((uint32_t)inode->i_size, pageofs);
-		ri.atime = ri.ctime = ri.mtime = CURRENT_TIME;
+		ri.atime = ri.ctime = ri.mtime = get_seconds();
 		ri.offset = inode->i_size;
 		ri.dsize = pageofs - inode->i_size;
 		ri.csize = 0;
@@ -380,7 +383,7 @@
 	ri->uid = inode->i_uid;
 	ri->gid = inode->i_gid;
 	ri->isize = (uint32_t)inode->i_size;
-	ri->atime = ri->ctime = ri->mtime = CURRENT_TIME;
+	ri->atime = ri->ctime = ri->mtime = get_seconds();
 
 	kmap(pg);
 	ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start,
@@ -397,7 +400,8 @@
 			inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen;
 			inode->i_blocks = (inode->i_size + 511) >> 9;
 			
-			inode->i_ctime = inode->i_mtime = ri->ctime;
+			inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = ri->ctime;
+			inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
 		}
 	}
 
diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c
--- a/fs/jffs2/fs.c	Sun Nov 17 20:30:13 2002
+++ b/fs/jffs2/fs.c	Sun Nov 17 20:30:13 2002
@@ -90,9 +90,12 @@
 	inode->i_uid = latest_node.uid;
 	inode->i_gid = latest_node.gid;
 	inode->i_size = latest_node.isize;
-	inode->i_atime = latest_node.atime;
-	inode->i_mtime = latest_node.mtime;
-	inode->i_ctime = latest_node.ctime;
+	inode->i_atime.tv_sec = latest_node.atime;
+	inode->i_mtime.tv_sec = latest_node.mtime;
+	inode->i_ctime.tv_sec = latest_node.ctime;
+	inode->i_atime.tv_nsec = 
+	inode->i_mtime.tv_nsec = 
+	inode->i_ctime.tv_nsec = 0;
 
 	inode->i_nlink = f->inocache->nlink;
 
@@ -251,7 +254,7 @@
 	inode->i_gid = ri->gid;
 	inode->i_uid = ri->uid;
 	inode->i_atime = inode->i_ctime = inode->i_mtime = 
-		ri->atime = ri->mtime = ri->ctime = CURRENT_TIME;
+		ri->atime = ri->mtime = ri->ctime = get_seconds();
 	inode->i_blksize = PAGE_SIZE;
 	inode->i_blocks = 0;
 	inode->i_size = 0;
diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
--- a/fs/jffs2/os-linux.h	Sun Nov 17 20:30:03 2002
+++ b/fs/jffs2/os-linux.h	Sun Nov 17 20:30:03 2002
@@ -37,9 +37,9 @@
 #define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
 #define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
 #define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
-#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime)
-#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime)
-#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime)
+#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime.tv_sec)
+#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime.tv_sec)
+#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime.tv_sec)
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1)
 #define JFFS2_F_I_RDEV_MIN(f) (minor(OFNI_EDONI_2SFFJ(f)->i_rdev))
diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c
--- a/fs/jffs2/super.c	Sun Nov 17 20:30:12 2002
+++ b/fs/jffs2/super.c	Sun Nov 17 20:30:12 2002
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/jffs2.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
diff -Nru a/fs/jffs2/write.c b/fs/jffs2/write.c
--- a/fs/jffs2/write.c	Sun Nov 17 20:30:14 2002
+++ b/fs/jffs2/write.c	Sun Nov 17 20:30:14 2002
@@ -479,7 +479,7 @@
 	rd->pino = dir_f->inocache->ino;
 	rd->version = ++dir_f->highest_version;
 	rd->ino = 0;
-	rd->mctime = CURRENT_TIME;
+	rd->mctime = get_seconds();
 	rd->nsize = namelen;
 	rd->type = DT_UNKNOWN;
 	rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
@@ -561,7 +561,7 @@
 	rd->pino = dir_f->inocache->ino;
 	rd->version = ++dir_f->highest_version;
 	rd->ino = ino;
-	rd->mctime = CURRENT_TIME;
+	rd->mctime = get_seconds();
 	rd->nsize = namelen;
 
 	rd->type = type;
diff -Nru a/fs/jfs/acl.c b/fs/jfs/acl.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/jfs/acl.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,301 @@
+/*
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *   Copyright (c) Andreas Gruenbacher, 2001
+ *   Copyright (c) Linus Torvalds, 1991, 1992
+ *
+ *   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
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include "jfs_incore.h"
+#include "jfs_xattr.h"
+#include "jfs_acl.h"
+
+struct posix_acl *jfs_get_acl(struct inode *inode, int type)
+{
+	struct posix_acl *acl;
+	char *ea_name;
+	struct jfs_inode_info *ji = JFS_IP(inode);
+	struct posix_acl **p_acl;
+	int size;
+	char *value = NULL;
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			ea_name = XATTR_NAME_ACL_ACCESS;
+			p_acl = &ji->i_acl;
+			break;
+		case ACL_TYPE_DEFAULT:
+			ea_name = XATTR_NAME_ACL_DEFAULT;
+			p_acl = &ji->i_default_acl;
+			break;
+		default:
+			return ERR_PTR(-EINVAL);
+	}
+
+	if (*p_acl != JFS_ACL_NOT_CACHED)
+		return posix_acl_dup(*p_acl);
+
+	size = __jfs_getxattr(inode, ea_name, NULL, 0);
+
+	if (size > 0) {
+		value = kmalloc(size, GFP_KERNEL);
+		if (!value)
+			return ERR_PTR(-ENOMEM);
+		size = __jfs_getxattr(inode, ea_name, value, size);
+	}
+
+	if (size < 0) {
+		if (size == -ENODATA) {
+			*p_acl = NULL;
+			acl = NULL;
+		} else
+			acl = ERR_PTR(size);
+	} else {
+		acl = posix_acl_from_xattr(value, size);
+		if (!IS_ERR(acl))
+			*p_acl = posix_acl_dup(acl);
+	}
+	if (value)
+		kfree(value);
+	return acl;
+}
+
+int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	char *ea_name;
+	struct jfs_inode_info *ji = JFS_IP(inode);
+	struct posix_acl **p_acl;
+	int rc;
+	int size = 0;
+	char *value = NULL;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			ea_name = XATTR_NAME_ACL_ACCESS;
+			p_acl = &ji->i_acl;
+			break;
+		case ACL_TYPE_DEFAULT:
+			ea_name = XATTR_NAME_ACL_DEFAULT;
+			p_acl = &ji->i_default_acl;
+			if (!S_ISDIR(inode->i_mode))
+				return acl ? -EACCES : 0;
+			break;
+		default:
+			return -EINVAL;
+	}
+	if (acl) {
+		size = xattr_acl_size(acl->a_count);
+		value = kmalloc(size, GFP_KERNEL);
+		if (!value)
+			return -ENOMEM;
+		rc = posix_acl_to_xattr(acl, value, size);
+		if (rc < 0)
+			goto out;
+	}
+	rc = __jfs_setxattr(inode, ea_name, value, size, 0);
+out:
+	if (value)
+		kfree(value);
+
+	if (!rc) {
+		if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
+			posix_acl_release(*p_acl);
+		*p_acl = posix_acl_dup(acl);
+	}
+	return rc;
+}
+
+/*
+ *	__jfs_permission()
+ *
+ * modified vfs_permission to check posix acl
+ */
+static int __jfs_permission(struct inode * inode, int mask, int have_sem)
+{
+	umode_t mode = inode->i_mode;
+	struct jfs_inode_info *ji = JFS_IP(inode);
+
+	if (mask & MAY_WRITE) {
+		/*
+		 * Nobody gets write access to a read-only fs.
+		 */
+		if (IS_RDONLY(inode) &&
+		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+			return -EROFS;
+
+		/*
+		 * Nobody gets write access to an immutable file.
+		 */
+		if (IS_IMMUTABLE(inode))
+			return -EACCES;
+	}
+
+	if (current->fsuid == inode->i_uid) {
+		mode >>= 6;
+		goto check_mode;
+	}
+	/*
+	 * ACL can't contain additional permissions if the ACL_MASK entry
+	 * is zero.
+	 */
+	if (!(mode & S_IRWXG))
+		goto check_groups;
+
+	if (ji->i_acl == JFS_ACL_NOT_CACHED) {
+		struct posix_acl *acl;
+
+		if (!have_sem)
+			down(&inode->i_sem);
+		acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
+		if (!have_sem)
+			up(&inode->i_sem);
+
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		posix_acl_release(acl);
+	}
+
+	if (ji->i_acl) {
+		int rc = posix_acl_permission(inode, ji->i_acl, mask);
+		if (rc == -EACCES)
+			goto check_capabilities;
+		return rc;
+	}
+
+check_groups:
+	if (in_group_p(inode->i_gid))
+		mode >>= 3;
+
+check_mode:
+	/*
+	 * If the DACs are ok we don't need any capability check.
+	 */
+	if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
+		return 0;
+
+check_capabilities:
+	/*
+	 * Read/write DACs are always overridable.
+	 * Executable DACs are overridable if at least one exec bit is set.
+	 */
+	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+		if (capable(CAP_DAC_OVERRIDE))
+			return 0;
+
+	/*
+	 * Searching includes executable on directories, else just read.
+	 */
+	if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
+		if (capable(CAP_DAC_READ_SEARCH))
+			return 0;
+
+	return -EACCES;
+}
+int jfs_permission(struct inode * inode, int mask)
+{
+	return __jfs_permission(inode, mask, 0);
+}
+int jfs_permission_have_sem(struct inode * inode, int mask)
+{
+	return __jfs_permission(inode, mask, 1);
+}
+
+int jfs_init_acl(struct inode *inode, struct inode *dir)
+{
+	struct posix_acl *acl = NULL;
+	struct posix_acl *clone;
+	mode_t mode;
+	int rc = 0;
+
+	if (S_ISLNK(inode->i_mode))
+		return 0;
+
+	acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+
+	if (acl) {
+		if (S_ISDIR(inode->i_mode)) {
+			rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+			if (rc)
+				goto cleanup;
+		}
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		if (!clone) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+		mode = inode->i_mode;
+		rc = posix_acl_create_masq(clone, &mode);
+		if (rc >= 0) {
+			inode->i_mode = mode;
+			if (rc > 0)
+				rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+		}
+		posix_acl_release(clone);
+cleanup:
+		posix_acl_release(acl);
+	} else
+		inode->i_mode &= ~current->fs->umask;
+
+	return rc;
+}
+
+int jfs_acl_chmod(struct inode *inode)
+{
+	struct posix_acl *acl, *clone;
+	int rc;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+
+	clone = posix_acl_clone(acl, GFP_KERNEL);
+	posix_acl_release(acl);
+	if (!clone)
+		return -ENOMEM;
+
+	rc = posix_acl_chmod_masq(clone, inode->i_mode);
+	if (!rc)
+		rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+
+	posix_acl_release(clone);
+	return rc;
+}
+
+int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	struct inode *inode = dentry->d_inode;
+	int rc;
+
+	rc = inode_change_ok(inode, iattr);
+	if (rc)
+		return rc;
+
+	inode_setattr(inode, iattr);
+
+	if (iattr->ia_valid & ATTR_MODE)
+		rc = jfs_acl_chmod(inode);
+
+	return rc;
+}
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	Sun Nov 17 20:30:04 2002
+++ b/fs/jfs/jfs_imap.c	Sun Nov 17 20:30:04 2002
@@ -3037,9 +3037,12 @@
 	ip->i_uid = le32_to_cpu(dip->di_uid);
 	ip->i_gid = le32_to_cpu(dip->di_gid);
 	ip->i_size = le64_to_cpu(dip->di_size);
-	ip->i_atime = le32_to_cpu(dip->di_atime.tv_sec);
-	ip->i_mtime = le32_to_cpu(dip->di_mtime.tv_sec);
-	ip->i_ctime = le32_to_cpu(dip->di_ctime.tv_sec);
+	ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
+	ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
+	ip->i_mtime.tv_sec = le32_to_cpu(dip->di_mtime.tv_sec);
+	ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
+	ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
+	ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
 	ip->i_blksize = ip->i_sb->s_blocksize;
 	ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
 	ip->i_generation = le32_to_cpu(dip->di_gen);
@@ -3096,12 +3099,12 @@
 	 * Trust i_mode for the lower order ones
 	 */
 	dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode);
-	dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime);
-	dip->di_atime.tv_nsec = 0;
-	dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime);
-	dip->di_ctime.tv_nsec = 0;
-	dip->di_mtime.tv_sec = cpu_to_le32(ip->i_mtime);
-	dip->di_mtime.tv_nsec = 0;
+	dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
+	dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
+	dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
+	dip->di_ctime.tv_nsec = cpu_to_le32(ip->i_ctime.tv_nsec);
+	dip->di_mtime.tv_sec = cpu_to_le32(ip->i_mtime.tv_sec);
+	dip->di_mtime.tv_nsec = cpu_to_le32(ip->i_mtime.tv_nsec);
 	dip->di_ixpxd = jfs_ip->ixpxd;	/* in-memory pxd's are little-endian */
 	dip->di_acl = jfs_ip->acl;	/* as are dxd's */
 	dip->di_ea = jfs_ip->ea;
diff -Nru a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
--- a/fs/jfs/jfs_inode.c	Sun Nov 17 20:30:02 2002
+++ b/fs/jfs/jfs_inode.c	Sun Nov 17 20:30:02 2002
@@ -68,7 +68,7 @@
 	inode->i_blksize = sb->s_blocksize;
 	inode->i_blocks = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	jfs_inode->otime = inode->i_ctime;
+	jfs_inode->otime = inode->i_ctime.tv_sec;
 	inode->i_generation = JFS_SBI(sb)->gengen++;
 
 	jfs_inode->cflag = 0;
diff -Nru a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
--- a/fs/lockd/clntproc.c	Sun Nov 17 20:30:02 2002
+++ b/fs/lockd/clntproc.c	Sun Nov 17 20:30:02 2002
@@ -241,19 +241,17 @@
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_res	*resp = &req->a_res;
 	struct file	*filp = argp->lock.fl.fl_file;
-	struct rpc_message msg;
+	struct rpc_message msg = {
+		.rpc_argp	= argp,
+		.rpc_resp	= resp,
+	};
 	int		status;
 
-	dprintk("lockd: call procedure %s on %s\n",
-			nlm_procname(proc), host->h_name);
+	dprintk("lockd: call procedure %d on %s\n",
+			(int)proc, host->h_name);
 
-	msg.rpc_proc = proc;
-	msg.rpc_argp = argp;
-	msg.rpc_resp = resp;
 	if (filp)
 		msg.rpc_cred = nfs_file_cred(filp);
-	else
-		msg.rpc_cred = NULL;
 
 	do {
 		if (host->h_reclaiming && !argp->reclaim) {
@@ -264,6 +262,7 @@
 		/* If we have no RPC client yet, create one. */
 		if ((clnt = nlm_bind_host(host)) == NULL)
 			return -ENOLCK;
+		msg.rpc_proc = &clnt->cl_procinfo[proc];
 
 		/* Perform the RPC call. If an error occurs, try again */
 		if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
@@ -321,23 +320,21 @@
 {
 	struct nlm_host	*host = req->a_host;
 	struct rpc_clnt	*clnt;
-	struct nlm_args	*argp = &req->a_args;
-	struct nlm_res	*resp = &req->a_res;
-	struct rpc_message msg;
+	struct rpc_message msg = {
+		.rpc_argp	= &req->a_args,
+		.rpc_resp	= &req->a_res,
+	};
 	int		status;
 
-	dprintk("lockd: call procedure %s on %s (async)\n",
-			nlm_procname(proc), host->h_name);
+	dprintk("lockd: call procedure %d on %s (async)\n",
+			(int)proc, host->h_name);
 
 	/* If we have no RPC client yet, create one. */
 	if ((clnt = nlm_bind_host(host)) == NULL)
 		return -ENOLCK;
+	msg.rpc_proc = &clnt->cl_procinfo[proc];
 
         /* bootstrap and kick off the async RPC call */
-	msg.rpc_proc = proc;
-	msg.rpc_argp = argp;
-	msg.rpc_resp =resp;
-	msg.rpc_cred = NULL;	
         status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
 
 	return status;
@@ -351,24 +348,23 @@
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_res	*resp = &req->a_res;
 	struct file	*file = argp->lock.fl.fl_file;
-	struct rpc_message msg;
+	struct rpc_message msg = {
+		.rpc_argp	= argp,
+		.rpc_resp	= resp,
+	};
 	int		status;
 
-	dprintk("lockd: call procedure %s on %s (async)\n",
-			nlm_procname(proc), host->h_name);
+	dprintk("lockd: call procedure %d on %s (async)\n",
+			(int)proc, host->h_name);
 
 	/* If we have no RPC client yet, create one. */
 	if ((clnt = nlm_bind_host(host)) == NULL)
 		return -ENOLCK;
+	msg.rpc_proc = &clnt->cl_procinfo[proc];
 
         /* bootstrap and kick off the async RPC call */
-	msg.rpc_proc = proc;
-	msg.rpc_argp = argp;
-	msg.rpc_resp =resp;
 	if (file)
 		msg.rpc_cred = nfs_file_cred(file);
-	else
-		msg.rpc_cred = NULL;
 	/* Increment host refcount */
 	nlm_get_host(host);
         status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
diff -Nru a/fs/lockd/mon.c b/fs/lockd/mon.c
--- a/fs/lockd/mon.c	Sun Nov 17 20:30:15 2002
+++ b/fs/lockd/mon.c	Sun Nov 17 20:30:15 2002
@@ -134,22 +134,13 @@
 /*
  * XDR functions for NSM.
  */
-static int
-xdr_error(struct rpc_rqst *rqstp, u32 *p, void *dummy)
-{
-	return -EACCES;
-}
 
-static int
-xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+static u32 *
+xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
 {
 	char	buffer[20];
 	u32	addr = ntohl(argp->addr);
 
-	dprintk("nsm: xdr_encode_mon(%08x, %d, %d, %d)\n",
-			htonl(argp->addr), htonl(argp->prog),
-			htonl(argp->vers), htonl(argp->proc));
-
 	/*
 	 * Use the dotted-quad IP address of the remote host as
 	 * identifier. Linux statd always looks up the canonical
@@ -160,19 +151,34 @@
 				 	(addr>>8) & 0xff,  (addr) & 0xff);
 	if (!(p = xdr_encode_string(p, buffer))
 	 || !(p = xdr_encode_string(p, system_utsname.nodename)))
-		return -EIO;
+		return ERR_PTR(-EIO);
 	*p++ = htonl(argp->prog);
 	*p++ = htonl(argp->vers);
 	*p++ = htonl(argp->proc);
 
-	/* This is the private part. Needed only for SM_MON call */
-	if (rqstp->rq_task->tk_msg.rpc_proc == SM_MON) {
-		*p++ = argp->addr;
-		*p++ = argp->vers;
-		*p++ = argp->proto;
-		*p++ = 0;
-	}
+	return p;
+}
+
+static int
+xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+{
+	p = xdr_encode_common(rqstp, p, argp);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+	*p++ = argp->addr;
+	*p++ = argp->vers;
+	*p++ = argp->proto;
+	*p++ = 0;
+	rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
+	return 0;
+}
 
+static int
+xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+{
+	p = xdr_encode_common(rqstp, p, argp);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
 	rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
 	return 0;
 }
@@ -206,42 +212,17 @@
 #endif
 
 static struct rpc_procinfo	nsm_procedures[] = {
-        {
-		.p_procname	= "sm_null",
-		.p_encode	= (kxdrproc_t) xdr_error,
-		.p_decode	= (kxdrproc_t) xdr_error,
-	},
-        {
-		.p_procname	= "sm_stat",
-		.p_encode	= (kxdrproc_t) xdr_error,
-		.p_decode	= (kxdrproc_t) xdr_error,
-	},
-        {
-		.p_procname	= "sm_mon",
+[SM_MON] = {
+		.p_proc		= SM_MON,
 		.p_encode	= (kxdrproc_t) xdr_encode_mon,
 		.p_decode	= (kxdrproc_t) xdr_decode_stat_res,
 		.p_bufsiz	= MAX(SM_mon_sz, SM_monres_sz) << 2,
 	},
-        {
-		.p_procname	= "sm_unmon",
-		.p_encode	= (kxdrproc_t) xdr_encode_mon,
+[SM_UNMON] = {
+		.p_proc		= SM_UNMON,
+		.p_encode	= (kxdrproc_t) xdr_encode_unmon,
 		.p_decode	= (kxdrproc_t) xdr_decode_stat,
 		.p_bufsiz	= MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
-	},
-        {
-		.p_procname	= "sm_unmon_all",
-		.p_encode	= (kxdrproc_t) xdr_error,
-		.p_decode	= (kxdrproc_t) xdr_error,
-	},
-        {
-		.p_procname	= "sm_simu_crash",
-		.p_encode	= (kxdrproc_t) xdr_error,
-		.p_decode	= (kxdrproc_t) xdr_error,
-	},
-        {
-		.p_procname	= "sm_notify",
-		.p_encode	= (kxdrproc_t) xdr_error,
-		.p_decode	= (kxdrproc_t) xdr_error,
 	},
 };
 
diff -Nru a/fs/lockd/xdr.c b/fs/lockd/xdr.c
--- a/fs/lockd/xdr.c	Sun Nov 17 20:30:02 2002
+++ b/fs/lockd/xdr.c	Sun Nov 17 20:30:02 2002
@@ -379,18 +379,13 @@
 /*
  * Now, the client side XDR functions
  */
-static int
-nlmclt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr)
-{
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
-
+#ifdef NLMCLNT_SUPPORT_SHARES
 static int
 nlmclt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
 {
 	return 0;
 }
+#endif
 
 static int
 nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
@@ -544,43 +539,34 @@
 #define nlmclt_decode_norep	NULL
 
 #define PROC(proc, argtype, restype)	\
-    { .p_procname  = "nlm_" #proc,					\
-      .p_encode    = (kxdrproc_t) nlmclt_encode_##argtype,		\
-      .p_decode    = (kxdrproc_t) nlmclt_decode_##restype,		\
-      .p_bufsiz    = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2	\
-    }
+[NLMPROC_##proc] = {							\
+	.p_proc      = NLMPROC_##proc,					\
+	.p_encode    = (kxdrproc_t) nlmclt_encode_##argtype,		\
+	.p_decode    = (kxdrproc_t) nlmclt_decode_##restype,		\
+	.p_bufsiz    = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2	\
+	}
 
 static struct rpc_procinfo	nlm_procedures[] = {
-    PROC(null,		void,		void),
-    PROC(test,		testargs,	testres),
-    PROC(lock,		lockargs,	res),
-    PROC(canc,		cancargs,	res),
-    PROC(unlock,	unlockargs,	res),
-    PROC(granted,	testargs,	res),
-    PROC(test_msg,	testargs,	norep),
-    PROC(lock_msg,	lockargs,	norep),
-    PROC(canc_msg,	cancargs,	norep),
-    PROC(unlock_msg,	unlockargs,	norep),
-    PROC(granted_msg,	testargs,	norep),
-    PROC(test_res,	testres,	norep),
-    PROC(lock_res,	res,		norep),
-    PROC(canc_res,	res,		norep),
-    PROC(unlock_res,	res,		norep),
-    PROC(granted_res,	res,		norep),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
+    PROC(TEST,		testargs,	testres),
+    PROC(LOCK,		lockargs,	res),
+    PROC(CANCEL,	cancargs,	res),
+    PROC(UNLOCK,	unlockargs,	res),
+    PROC(GRANTED,	testargs,	res),
+    PROC(TEST_MSG,	testargs,	norep),
+    PROC(LOCK_MSG,	lockargs,	norep),
+    PROC(CANCEL_MSG,	cancargs,	norep),
+    PROC(UNLOCK_MSG,	unlockargs,	norep),
+    PROC(GRANTED_MSG,	testargs,	norep),
+    PROC(TEST_RES,	testres,	norep),
+    PROC(LOCK_RES,	res,		norep),
+    PROC(CANCEL_RES,	res,		norep),
+    PROC(UNLOCK_RES,	res,		norep),
+    PROC(GRANTED_RES,	res,		norep),
 #ifdef NLMCLNT_SUPPORT_SHARES
-    PROC(share,		shareargs,	shareres),
-    PROC(unshare,	shareargs,	shareres),
-    PROC(nm_lock,	lockargs,	res),
-    PROC(free_all,	notify,		void),
-#else
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
+    PROC(SHARE,		shareargs,	shareres),
+    PROC(UNSHARE,	shareargs,	shareres),
+    PROC(NM_LOCK,	lockargs,	res),
+    PROC(FREE_ALL,	notify,		void),
 #endif
 };
 
@@ -617,14 +603,4 @@
 		.version	= nlm_versions,
 		.stats		= &nlm_stats,
 };
-
-#ifdef LOCKD_DEBUG
-char *
-nlm_procname(u32 proc)
-{
-	if (proc < sizeof(nlm_procedures)/sizeof(nlm_procedures[0]))
-		return nlm_procedures[proc].p_procname;
-	return "unknown";
-}
-#endif
 
diff -Nru a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
--- a/fs/lockd/xdr4.c	Sun Nov 17 20:30:02 2002
+++ b/fs/lockd/xdr4.c	Sun Nov 17 20:30:02 2002
@@ -382,18 +382,13 @@
 /*
  * Now, the client side XDR functions
  */
-static int
-nlm4clt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr)
-{
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
-
+#ifdef NLMCLNT_SUPPORT_SHARES
 static int
 nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
 {
 	return 0;
 }
+#endif
 
 static int
 nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
@@ -547,43 +542,34 @@
 #define nlm4clt_decode_norep	NULL
 
 #define PROC(proc, argtype, restype)					\
-    { .p_procname  = "nlm4_" #proc,					\
-      .p_encode    = (kxdrproc_t) nlm4clt_encode_##argtype,		\
-      .p_decode    = (kxdrproc_t) nlm4clt_decode_##restype,		\
-      .p_bufsiz    = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2	\
-    }
+[NLMPROC_##proc] = {							\
+	.p_proc      = NLMPROC_##proc,					\
+	.p_encode    = (kxdrproc_t) nlm4clt_encode_##argtype,		\
+	.p_decode    = (kxdrproc_t) nlm4clt_decode_##restype,		\
+	.p_bufsiz    = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2	\
+	}
 
 static struct rpc_procinfo	nlm4_procedures[] = {
-    PROC(null,		void,		void),
-    PROC(test,		testargs,	testres),
-    PROC(lock,		lockargs,	res),
-    PROC(canc,		cancargs,	res),
-    PROC(unlock,	unlockargs,	res),
-    PROC(granted,	testargs,	res),
-    PROC(test_msg,	testargs,	norep),
-    PROC(lock_msg,	lockargs,	norep),
-    PROC(canc_msg,	cancargs,	norep),
-    PROC(unlock_msg,	unlockargs,	norep),
-    PROC(granted_msg,	testargs,	norep),
-    PROC(test_res,	testres,	norep),
-    PROC(lock_res,	res,		norep),
-    PROC(canc_res,	res,		norep),
-    PROC(unlock_res,	res,		norep),
-    PROC(granted_res,	res,		norep),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
+    PROC(TEST,		testargs,	testres),
+    PROC(LOCK,		lockargs,	res),
+    PROC(CANCEL,	cancargs,	res),
+    PROC(UNLOCK,	unlockargs,	res),
+    PROC(GRANTED,	testargs,	res),
+    PROC(TEST_MSG,	testargs,	norep),
+    PROC(LOCK_MSG,	lockargs,	norep),
+    PROC(CANCEL_MSG,	cancargs,	norep),
+    PROC(UNLOCK_MSG,	unlockargs,	norep),
+    PROC(GRANTED_MSG,	testargs,	norep),
+    PROC(TEST_RES,	testres,	norep),
+    PROC(LOCK_RES,	res,		norep),
+    PROC(CANCEL_RES,	res,		norep),
+    PROC(UNLOCK_RES,	res,		norep),
+    PROC(GRANTED_RES,	res,		norep),
 #ifdef NLMCLNT_SUPPORT_SHARES
-    PROC(share,		shareargs,	shareres),
-    PROC(unshare,	shareargs,	shareres),
-    PROC(nm_lock,	lockargs,	res),
-    PROC(free_all,	notify,		void),
-#else
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
-    PROC(undef,		void,		void),
+    PROC(SHARE,		shareargs,	shareres),
+    PROC(UNSHARE,	shareargs,	shareres),
+    PROC(NM_LOCK,	lockargs,	res),
+    PROC(FREE_ALL,	notify,		void),
 #endif
 };
 
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Sun Nov 17 20:30:15 2002
+++ b/fs/locks.c	Sun Nov 17 20:30:15 2002
@@ -1101,12 +1101,13 @@
  * exclusive leases.  The justification is that if someone has an
  * exclusive lease, then they could be modifiying it.
  */
-time_t lease_get_mtime(struct inode *inode)
+void lease_get_mtime(struct inode *inode, struct timespec *time)
 {
 	struct file_lock *flock = inode->i_flock;
 	if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK))
-		return CURRENT_TIME;
-	return inode->i_mtime;
+		*time = CURRENT_TIME;
+	else
+		*time = inode->i_mtime;
 }
 
 /**
diff -Nru a/fs/mbcache.c b/fs/mbcache.c
--- a/fs/mbcache.c	Sun Nov 17 20:30:15 2002
+++ b/fs/mbcache.c	Sun Nov 17 20:30:15 2002
@@ -12,7 +12,7 @@
  *
  * There can only be one cache entry in a cache per device and block number.
  * Additional indexes need not be unique in this sense. The number of
- * additional indexes (=other criteria) can be hardwired (at compile time)
+ * additional indexes (=other criteria) can be hardwired at compile time
  * or specified at cache create time.
  *
  * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
@@ -22,7 +22,8 @@
  *
  * A valid cache entry is only in the lru list if no handles refer to it.
  * Invalid cache entries will be freed when the last handle to the cache
- * entry is released.
+ * entry is released. Entries that cannot be freed immediately are put
+ * back on the lru list.
  */
 
 #include <linux/kernel.h>
@@ -76,8 +77,8 @@
 
 /*
  * Global data: list of all mbcache's, lru list, and a spinlock for
- * accessing cache data structures on SMP machines. (The lru list is
- * global across all mbcaches.)
+ * accessing cache data structures on SMP machines. The lru list is
+ * global across all mbcaches.
  */
 
 static LIST_HEAD(mb_cache_list);
@@ -101,90 +102,43 @@
 
 static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
 
-static inline void
-__mb_cache_entry_takeout_lru(struct mb_cache_entry *ce)
-{
-	if (!list_empty(&ce->e_lru_list))
-		list_del_init(&ce->e_lru_list);
-}
-
-
-static inline void
-__mb_cache_entry_into_lru(struct mb_cache_entry *ce)
-{
-	list_add(&ce->e_lru_list, &mb_cache_lru_list);
-}
-
 
 static inline int
-__mb_cache_entry_in_lru(struct mb_cache_entry *ce)
-{
-	return (!list_empty(&ce->e_lru_list));
-}
-
-
-/*
- * Insert the cache entry into all hashes.
- */
-static inline void
-__mb_cache_entry_link(struct mb_cache_entry *ce)
+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
 {
-	struct mb_cache *cache = ce->e_cache;
-	unsigned int bucket;
-	int n;
-	
-	bucket = hash_long((unsigned long)ce->e_bdev +
-			   (ce->e_block & 0xffffff), cache->c_bucket_bits);
-	list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-	for (n=0; n<mb_cache_indexes(cache); n++) {
-		bucket = hash_long(ce->e_indexes[n].o_key,
-				   cache->c_bucket_bits);
-		list_add(&ce->e_indexes[n].o_list,
-		         &cache->c_indexes_hash[n][bucket]);
-	}
+	return !list_empty(&ce->e_block_list);
 }
 
 
-/*
- * Remove the cache entry from all hashes.
- */
 static inline void
-__mb_cache_entry_unlink(struct mb_cache_entry *ce)
+__mb_cache_entry_unhash(struct mb_cache_entry *ce)
 {
 	int n;
 
-	list_del_init(&ce->e_block_list);
-	for (n = 0; n < mb_cache_indexes(ce->e_cache); n++)
-		list_del(&ce->e_indexes[n].o_list);
-}
-
-
-static inline int
-__mb_cache_entry_is_linked(struct mb_cache_entry *ce)
-{
-	return (!list_empty(&ce->e_block_list));
-}
-
-
-static inline struct mb_cache_entry *
-__mb_cache_entry_read(struct mb_cache_entry *ce)
-{
-	__mb_cache_entry_takeout_lru(ce);
-	atomic_inc(&ce->e_used);
-	return ce;
+	if (__mb_cache_entry_is_hashed(ce)) {
+		list_del_init(&ce->e_block_list);
+		for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
+			list_del(&ce->e_indexes[n].o_list);
+	}
 }
 
 
 static inline void
-__mb_cache_entry_forget(struct mb_cache_entry *ce)
+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
 {
 	struct mb_cache *cache = ce->e_cache;
 
 	mb_assert(atomic_read(&ce->e_used) == 0);
-	atomic_dec(&cache->c_entry_count);
-	if (cache->c_op.free)
-		cache->c_op.free(ce);
-	kmem_cache_free(cache->c_entry_cache, ce);
+	if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
+		/* free failed -- put back on the lru list
+		   for freeing later. */
+		spin_lock(&mb_cache_spinlock);
+		list_add(&ce->e_lru_list, &mb_cache_lru_list);
+		spin_unlock(&mb_cache_spinlock);
+	} else {
+		kmem_cache_free(cache->c_entry_cache, ce);
+		atomic_dec(&cache->c_entry_count);
+	}
 }
 
 
@@ -192,15 +146,15 @@
 __mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
 {
 	if (atomic_dec_and_test(&ce->e_used)) {
-		if (!__mb_cache_entry_is_linked(ce))
+		if (!__mb_cache_entry_is_hashed(ce))
 			goto forget;
-		__mb_cache_entry_into_lru(ce);
+		list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
 	}
 	spin_unlock(&mb_cache_spinlock);
 	return;
 forget:
 	spin_unlock(&mb_cache_spinlock);
-	__mb_cache_entry_forget(ce);
+	__mb_cache_entry_forget(ce, GFP_KERNEL);
 }
 
 
@@ -219,11 +173,11 @@
 mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
 {
 	LIST_HEAD(free_list);
-	struct list_head *l;
+	struct list_head *l, *ltmp;
 	int count = 0;
 
 	spin_lock(&mb_cache_spinlock);
-	list_for_each_prev(l, &mb_cache_list) {
+	list_for_each(l, &mb_cache_list) {
 		struct mb_cache *cache =
 			list_entry(l, struct mb_cache, c_cache_list);
 		mb_debug("cache %s (%d)", cache->c_name,
@@ -235,26 +189,19 @@
 		spin_unlock(&mb_cache_spinlock);
 		goto out;
 	}
-	while (nr_to_scan && !list_empty(&mb_cache_lru_list)) {
+	while (nr_to_scan-- && !list_empty(&mb_cache_lru_list)) {
 		struct mb_cache_entry *ce =
-			list_entry(mb_cache_lru_list.prev,
+			list_entry(mb_cache_lru_list.next,
 				   struct mb_cache_entry, e_lru_list);
-		list_move(&ce->e_lru_list, &free_list);
-		if (__mb_cache_entry_is_linked(ce))
-			__mb_cache_entry_unlink(ce);
-		nr_to_scan--;
+		list_move_tail(&ce->e_lru_list, &free_list);
+		__mb_cache_entry_unhash(ce);
 	}
 	spin_unlock(&mb_cache_spinlock);
-	l = free_list.prev;
-	while (l != &free_list) {
-		struct mb_cache_entry *ce = list_entry(l,
-			struct mb_cache_entry, e_lru_list);
-		l = l->prev;
-		__mb_cache_entry_forget(ce);
-		count--;
+	list_for_each_safe(l, ltmp, &free_list) {
+		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
+						   e_lru_list), gfp_mask);
 	}
 out:
-	mb_debug("%d remaining entries ", count);
 	return count;
 }
 
@@ -292,10 +239,9 @@
 	if (!cache)
 		goto fail;
 	cache->c_name = name;
+	cache->c_op.free = NULL;
 	if (cache_op)
 		cache->c_op.free = cache_op->free;
-	else
-		cache->c_op.free = NULL;
 	atomic_set(&cache->c_entry_count, 0);
 	cache->c_bucket_bits = bucket_bits;
 #ifdef MB_CACHE_INDEXES_COUNT
@@ -354,27 +300,21 @@
 mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev)
 {
 	LIST_HEAD(free_list);
-	struct list_head *l;
+	struct list_head *l, *ltmp;
 
 	spin_lock(&mb_cache_spinlock);
-	l = mb_cache_lru_list.prev;
-	while (l != &mb_cache_lru_list) {
+	list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
 		struct mb_cache_entry *ce =
 			list_entry(l, struct mb_cache_entry, e_lru_list);
-		l = l->prev;
 		if (ce->e_bdev == bdev) {
-			list_move(&ce->e_lru_list, &free_list);
-			if (__mb_cache_entry_is_linked(ce))
-				__mb_cache_entry_unlink(ce);
+			list_move_tail(&ce->e_lru_list, &free_list);
+			__mb_cache_entry_unhash(ce);
 		}
 	}
 	spin_unlock(&mb_cache_spinlock);
-	l = free_list.prev;
-	while (l != &free_list) {
-		struct mb_cache_entry *ce =
-			list_entry(l, struct mb_cache_entry, e_lru_list);
-		l = l->prev;
-		__mb_cache_entry_forget(ce);
+	list_for_each_safe(l, ltmp, &free_list) {
+		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
+						   e_lru_list), GFP_KERNEL);
 	}
 }
 
@@ -390,30 +330,24 @@
 mb_cache_destroy(struct mb_cache *cache)
 {
 	LIST_HEAD(free_list);
-	struct list_head *l;
+	struct list_head *l, *ltmp;
 	int n;
 
 	spin_lock(&mb_cache_spinlock);
-	l = mb_cache_lru_list.prev;
-	while (l != &mb_cache_lru_list) {
+	list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
 		struct mb_cache_entry *ce =
 			list_entry(l, struct mb_cache_entry, e_lru_list);
-		l = l->prev;
 		if (ce->e_cache == cache) {
-			list_move(&ce->e_lru_list, &free_list);
-			if (__mb_cache_entry_is_linked(ce))
-				__mb_cache_entry_unlink(ce);
+			list_move_tail(&ce->e_lru_list, &free_list);
+			__mb_cache_entry_unhash(ce);
 		}
 	}
 	list_del(&cache->c_cache_list);
 	spin_unlock(&mb_cache_spinlock);
 
-	l = free_list.prev;
-	while (l != &free_list) {
-		struct mb_cache_entry *ce =
-			list_entry(l, struct mb_cache_entry, e_lru_list);
-		l = l->prev;
-		__mb_cache_entry_forget(ce);
+	list_for_each_safe(l, ltmp, &free_list) {
+		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
+						   e_lru_list), GFP_KERNEL);
 	}
 
 	if (atomic_read(&cache->c_entry_count) > 0) {
@@ -427,7 +361,6 @@
 	for (n=0; n < mb_cache_indexes(cache); n++)
 		kfree(cache->c_indexes_hash[n]);
 	kfree(cache->c_block_hash);
-
 	kfree(cache);
 }
 
@@ -481,8 +414,8 @@
 	struct list_head *l;
 	int error = -EBUSY, n;
 
-	bucket =  hash_long((unsigned long)bdev + (block & 0xffffffff), 
-			    cache->c_bucket_bits);
+	bucket = hash_long((unsigned long)bdev + (block & 0xffffffff), 
+			   cache->c_bucket_bits);
 	spin_lock(&mb_cache_spinlock);
 	list_for_each_prev(l, &cache->c_block_hash[bucket]) {
 		struct mb_cache_entry *ce =
@@ -490,12 +423,16 @@
 		if (ce->e_bdev == bdev && ce->e_block == block)
 			goto out;
 	}
-	mb_assert(!__mb_cache_entry_is_linked(ce));
+	__mb_cache_entry_unhash(ce);
 	ce->e_bdev = bdev;
 	ce->e_block = block;
-	for (n=0; n<mb_cache_indexes(cache); n++)
+	list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
+	for (n=0; n<mb_cache_indexes(cache); n++) {
 		ce->e_indexes[n].o_key = keys[n];
-	__mb_cache_entry_link(ce);
+		bucket = hash_long(keys[n], cache->c_bucket_bits);
+		list_add(&ce->e_indexes[n].o_list,
+			 &cache->c_indexes_hash[n][bucket]);
+	}
 out:
 	spin_unlock(&mb_cache_spinlock);
 	return error;
@@ -528,9 +465,8 @@
 mb_cache_entry_takeout(struct mb_cache_entry *ce)
 {
 	spin_lock(&mb_cache_spinlock);
-	mb_assert(!__mb_cache_entry_in_lru(ce));
-	if (__mb_cache_entry_is_linked(ce))
-		__mb_cache_entry_unlink(ce);
+	mb_assert(list_empty(&ce->e_lru_list));
+	__mb_cache_entry_unhash(ce);
 	spin_unlock(&mb_cache_spinlock);
 }
 
@@ -545,9 +481,8 @@
 mb_cache_entry_free(struct mb_cache_entry *ce)
 {
 	spin_lock(&mb_cache_spinlock);
-	mb_assert(!__mb_cache_entry_in_lru(ce));
-	if (__mb_cache_entry_is_linked(ce))
-		__mb_cache_entry_unlink(ce);
+	mb_assert(list_empty(&ce->e_lru_list));
+	__mb_cache_entry_unhash(ce);
 	__mb_cache_entry_release_unlock(ce);
 }
 
@@ -587,7 +522,9 @@
 	list_for_each(l, &cache->c_block_hash[bucket]) {
 		ce = list_entry(l, struct mb_cache_entry, e_block_list);
 		if (ce->e_bdev == bdev && ce->e_block == block) {
-			ce = __mb_cache_entry_read(ce);
+			if (!list_empty(&ce->e_lru_list))
+				list_del_init(&ce->e_lru_list);
+			atomic_inc(&ce->e_used);
 			goto cleanup;
 		}
 	}
@@ -608,11 +545,11 @@
 		struct mb_cache_entry *ce =
 			list_entry(l, struct mb_cache_entry,
 			           e_indexes[index].o_list);
-		if (ce->e_bdev == bdev &&
-		    ce->e_indexes[index].o_key == key) {
-			ce = __mb_cache_entry_read(ce);
-			if (ce)
-				return ce;
+		if (ce->e_bdev == bdev && ce->e_indexes[index].o_key == key) {
+			if (!list_empty(&ce->e_lru_list))
+				list_del_init(&ce->e_lru_list);
+			atomic_inc(&ce->e_used);
+			return ce;
 		}
 		l = l->next;
 	}
diff -Nru a/fs/minix/inode.c b/fs/minix/inode.c
--- a/fs/minix/inode.c	Sun Nov 17 20:30:14 2002
+++ b/fs/minix/inode.c	Sun Nov 17 20:30:14 2002
@@ -384,7 +384,10 @@
 	inode->i_gid = (gid_t)raw_inode->i_gid;
 	inode->i_nlink = raw_inode->i_nlinks;
 	inode->i_size = raw_inode->i_size;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
+	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = raw_inode->i_time;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = inode->i_blksize = 0;
 	for (i = 0; i < 9; i++)
 		minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
@@ -412,9 +415,12 @@
 	inode->i_gid = (gid_t)raw_inode->i_gid;
 	inode->i_nlink = raw_inode->i_nlinks;
 	inode->i_size = raw_inode->i_size;
-	inode->i_mtime = raw_inode->i_mtime;
-	inode->i_atime = raw_inode->i_atime;
-	inode->i_ctime = raw_inode->i_ctime;
+	inode->i_mtime.tv_sec = raw_inode->i_mtime;
+	inode->i_atime.tv_sec = raw_inode->i_atime;
+	inode->i_ctime.tv_sec = raw_inode->i_ctime;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = inode->i_blksize = 0;
 	for (i = 0; i < 10; i++)
 		minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
@@ -451,7 +457,7 @@
 	raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
 	raw_inode->i_nlinks = inode->i_nlink;
 	raw_inode->i_size = inode->i_size;
-	raw_inode->i_time = inode->i_mtime;
+	raw_inode->i_time = inode->i_mtime.tv_sec;
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
 	else for (i = 0; i < 9; i++)
@@ -478,9 +484,9 @@
 	raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
 	raw_inode->i_nlinks = inode->i_nlink;
 	raw_inode->i_size = inode->i_size;
-	raw_inode->i_mtime = inode->i_mtime;
-	raw_inode->i_atime = inode->i_atime;
-	raw_inode->i_ctime = inode->i_ctime;
+	raw_inode->i_mtime = inode->i_mtime.tv_sec;
+	raw_inode->i_atime = inode->i_atime.tv_sec;
+	raw_inode->i_ctime = inode->i_ctime.tv_sec;
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
 	else for (i = 0; i < 10; i++)
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c	Sun Nov 17 20:30:12 2002
+++ b/fs/mpage.c	Sun Nov 17 20:30:12 2002
@@ -210,10 +210,11 @@
 	}
 
 	if (first_hole != blocks_per_page) {
-		memset(kmap(page) + (first_hole << blkbits), 0,
+		char *kaddr = kmap_atomic(page, KM_USER0);
+		memset(kaddr + (first_hole << blkbits), 0,
 				PAGE_CACHE_SIZE - (first_hole << blkbits));
 		flush_dcache_page(page);
-		kunmap(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		if (first_hole == 0) {
 			SetPageUptodate(page);
 			unlock_page(page);
@@ -427,12 +428,14 @@
 	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 	if (page->index >= end_index) {
 		unsigned offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+		char *kaddr;
 
 		if (page->index > end_index || !offset)
 			goto confused;
-		memset(kmap(page) + offset, 0, PAGE_CACHE_SIZE - offset);
+		kaddr = kmap_atomic(page, KM_USER0);
+		memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
 		flush_dcache_page(page);
-		kunmap(page);
+		kunmap_atomic(kaddr, KM_USER0);
 	}
 
 page_is_mapped:
@@ -587,12 +590,19 @@
 		page_cache_get(page);
 		write_unlock(&mapping->page_lock);
 
+		/*
+		 * At this point we hold neither mapping->page_lock nor
+		 * lock on the page itself: the page may be truncated or
+		 * invalidated (changing page->mapping to NULL), or even
+		 * swizzled back from swapper_space to tmpfs file mapping.
+		 */
+
 		lock_page(page);
 
 		if (sync)
 			wait_on_page_writeback(page);
 
-		if (page->mapping && !PageWriteback(page) &&
+		if (page->mapping == mapping && !PageWriteback(page) &&
 					test_clear_page_dirty(page)) {
 			if (writepage) {
 				ret = (*writepage)(page);
diff -Nru a/fs/msdos/namei.c b/fs/msdos/namei.c
--- a/fs/msdos/namei.c	Sun Nov 17 20:30:14 2002
+++ b/fs/msdos/namei.c	Sun Nov 17 20:30:14 2002
@@ -251,7 +251,7 @@
 		(*de)->attr |= ATTR_HIDDEN;
 	(*de)->start = 0;
 	(*de)->starthi = 0;
-	fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
+	fat_date_unix2dos(dir->i_mtime.tv_sec,&(*de)->time,&(*de)->date);
 	(*de)->size = 0;
 	mark_buffer_dirty(*bh);
 	return 0;
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Sun Nov 17 20:30:12 2002
+++ b/fs/namei.c	Sun Nov 17 20:30:12 2002
@@ -24,7 +24,7 @@
 #include <linux/smp_lock.h>
 #include <linux/personality.h>
 #include <linux/security.h>
-
+#include <linux/mount.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Sun Nov 17 20:30:14 2002
+++ b/fs/namespace.c	Sun Nov 17 20:30:14 2002
@@ -19,7 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 #include <linux/namei.h>
-
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
@@ -110,7 +110,7 @@
 	mnt->mnt_parent = mntget(nd->mnt);
 	mnt->mnt_mountpoint = dget(nd->dentry);
 	list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
-	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+	list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts);
 	nd->dentry->d_mounted++;
 }
 
@@ -879,6 +879,54 @@
 out1:
 	free_page(type_page);
 	return retval;
+}
+
+/*
+ * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
+ * It can block. Requires the big lock held.
+ */
+void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt,
+		 struct dentry *dentry)
+{
+	struct dentry *old_root;
+	struct vfsmount *old_rootmnt;
+	write_lock(&fs->lock);
+	spin_lock(&dcache_lock);
+	old_root = fs->root;
+	old_rootmnt = fs->rootmnt;
+	fs->rootmnt = mntget(mnt);
+	fs->root = dget(dentry);
+	spin_unlock(&dcache_lock);
+	write_unlock(&fs->lock);
+	if (old_root) {
+		dput(old_root);
+		mntput(old_rootmnt);
+	}
+}
+
+/*
+ * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
+ * It can block. Requires the big lock held.
+ */
+void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
+		struct dentry *dentry)
+{
+	struct dentry *old_pwd;
+	struct vfsmount *old_pwdmnt;
+
+	write_lock(&fs->lock);
+	spin_lock(&dcache_lock);
+	old_pwd = fs->pwd;
+	old_pwdmnt = fs->pwdmnt;
+	fs->pwdmnt = mntget(mnt);
+	fs->pwd = dget(dentry);
+	spin_unlock(&dcache_lock);
+	write_unlock(&fs->lock);
+
+	if (old_pwd) {
+		dput(old_pwd);
+		mntput(old_pwdmnt);
+	}
 }
 
 static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ncpfs/inode.c	Sun Nov 17 20:30:14 2002
@@ -134,12 +134,15 @@
 
 	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
-	inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
+	inode->i_mtime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
 					   le16_to_cpu(nwi->modifyDate));
-	inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
+	inode->i_ctime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
 					   le16_to_cpu(nwi->creationDate));
-	inode->i_atime = ncp_date_dos2unix(0,
+	inode->i_atime.tv_sec = ncp_date_dos2unix(0,
 					   le16_to_cpu(nwi->lastAccessDate));
+	inode->i_atime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
 }
 
 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
@@ -896,14 +899,14 @@
 	}
 	if ((attr->ia_valid & ATTR_CTIME) != 0) {
 		info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
-		ncp_date_unix2dos(attr->ia_ctime,
+		ncp_date_unix2dos(attr->ia_ctime.tv_sec,
 			     &(info.creationTime), &(info.creationDate));
 		info.creationTime = le16_to_cpu(info.creationTime);
 		info.creationDate = le16_to_cpu(info.creationDate);
 	}
 	if ((attr->ia_valid & ATTR_MTIME) != 0) {
 		info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
-		ncp_date_unix2dos(attr->ia_mtime,
+		ncp_date_unix2dos(attr->ia_mtime.tv_sec,
 				  &(info.modifyTime), &(info.modifyDate));
 		info.modifyTime = le16_to_cpu(info.modifyTime);
 		info.modifyDate = le16_to_cpu(info.modifyDate);
@@ -911,7 +914,7 @@
 	if ((attr->ia_valid & ATTR_ATIME) != 0) {
 		__u16 dummy;
 		info_mask |= (DM_LAST_ACCESS_DATE);
-		ncp_date_unix2dos(attr->ia_ctime,
+		ncp_date_unix2dos(attr->ia_ctime.tv_sec,
 				  &(dummy), &(info.lastAccessDate));
 		info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
 	}
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/nfs/inode.c	Sun Nov 17 20:30:15 2002
@@ -32,6 +32,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
+#include <linux/mount.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -692,10 +693,12 @@
 
 		NFS_READTIME(inode) = fattr->timestamp;
 		NFS_CACHE_CTIME(inode) = fattr->ctime;
-		inode->i_ctime = nfs_time_to_secs(fattr->ctime);
-		inode->i_atime = new_atime;
+		inode->i_ctime.tv_sec = nfs_time_to_secs(fattr->ctime);
+		inode->i_ctime.tv_nsec = nfs_time_to_nsecs(fattr->ctime);
+		inode->i_atime.tv_sec = new_atime;
 		NFS_CACHE_MTIME(inode) = new_mtime;
-		inode->i_mtime = nfs_time_to_secs(new_mtime);
+		inode->i_mtime.tv_sec = nfs_time_to_secs(new_mtime);
+		inode->i_mtime.tv_nsec = nfs_time_to_nsecs(new_mtime);
 		NFS_MTIME_UPDATE(inode) = fattr->timestamp;
 		NFS_CACHE_ISIZE(inode) = new_size;
 		if (fattr->valid & NFS_ATTR_FATTR_V4)
@@ -990,7 +993,7 @@
 {
 	__u64		new_size, new_mtime;
 	loff_t		new_isize;
-	time_t		new_atime;
+	struct timespec	new_atime;
 	int		invalid = 0;
 
 	dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n",
@@ -1018,7 +1021,8 @@
 	new_size = fattr->size;
  	new_isize = nfs_size_to_loff_t(fattr->size);
 
-	new_atime = nfs_time_to_secs(fattr->atime);
+	new_atime.tv_sec = nfs_time_to_secs(fattr->atime);
+	new_atime.tv_nsec = nfs_time_to_nsecs(fattr->atime);
 	/* Avoid races */
 	if (nfs_fattr_obsolete(inode, fattr))
 		goto out_nochange;
@@ -1083,7 +1087,8 @@
 		new_isize = inode->i_size;
 
 	NFS_CACHE_CTIME(inode) = fattr->ctime;
-	inode->i_ctime = nfs_time_to_secs(fattr->ctime);
+	inode->i_ctime.tv_sec = nfs_time_to_secs(fattr->ctime);
+	inode->i_ctime.tv_nsec = nfs_time_to_nsecs(fattr->ctime);
 
 	inode->i_atime = new_atime;
 
@@ -1091,7 +1096,8 @@
 		if (invalid)
 			NFS_MTIME_UPDATE(inode) = fattr->timestamp;
 		NFS_CACHE_MTIME(inode) = new_mtime;
-		inode->i_mtime = nfs_time_to_secs(new_mtime);
+		inode->i_mtime.tv_sec = nfs_time_to_secs(new_mtime);
+		inode->i_mtime.tv_nsec = nfs_time_to_nsecs(new_mtime);
 	}
 
 	NFS_CACHE_ISIZE(inode) = new_size;
@@ -1140,7 +1146,7 @@
 
 	return 0;
  out_nochange:
-	if (new_atime - inode->i_atime > 0)
+	if (!timespec_equal(&new_atime, &inode->i_atime))
 		inode->i_atime = new_atime;
 	return 0;
  out_changed:
diff -Nru a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
--- a/fs/nfs/mount_clnt.c	Sun Nov 17 20:30:02 2002
+++ b/fs/nfs/mount_clnt.c	Sun Nov 17 20:30:02 2002
@@ -140,24 +140,18 @@
 #define MNT_dirpath_sz		(1 + 256)
 #define MNT_fhstatus_sz		(1 + 8)
 
-static struct rpc_procinfo	mnt_procedures[2] = {
-	{ .p_procname		= "mnt_null",
-	  .p_encode		= (kxdrproc_t) xdr_error,	
-	  .p_decode		= (kxdrproc_t) xdr_error,
-	},
-	{ .p_procname		= "mnt_mount",
+static struct rpc_procinfo	mnt_procedures[] = {
+[MNTPROC_MNT] = {
+	  .p_proc		= MNTPROC_MNT,
 	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,	
 	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus,
 	  .p_bufsiz		= MNT_dirpath_sz << 2,
 	},
 };
 
-static struct rpc_procinfo mnt3_procedures[2] = {
-	{ .p_procname		= "mnt3_null",
-	  .p_encode		= (kxdrproc_t) xdr_error,
-	  .p_decode		= (kxdrproc_t) xdr_error,
-	},
-	{ .p_procname		= "mnt3_mount",
+static struct rpc_procinfo mnt3_procedures[] = {
+[MOUNTPROC3_MNT] = {
+	  .p_proc		= MOUNTPROC3_MNT,
 	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,
 	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus3,
 	  .p_bufsiz		= MNT_dirpath_sz << 2,
diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
--- a/fs/nfs/nfs2xdr.c	Sun Nov 17 20:30:12 2002
+++ b/fs/nfs/nfs2xdr.c	Sun Nov 17 20:30:12 2002
@@ -44,7 +44,6 @@
 #define NFS_info_sz		5
 #define NFS_entry_sz		NFS_filename_sz+3
 
-#define NFS_enc_void_sz		0
 #define NFS_diropargs_sz	NFS_fhandle_sz+NFS_filename_sz
 #define NFS_sattrargs_sz	NFS_fhandle_sz+NFS_sattr_sz
 #define NFS_readlinkargs_sz	NFS_fhandle_sz
@@ -56,7 +55,6 @@
 #define NFS_symlinkargs_sz	NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
 #define NFS_readdirargs_sz	NFS_fhandle_sz+2
 
-#define NFS_dec_void_sz		0
 #define NFS_attrstat_sz		1+NFS_fattr_sz
 #define NFS_diropres_sz		1+NFS_fhandle_sz+NFS_fattr_sz
 #define NFS_readlinkres_sz	1
@@ -133,7 +131,7 @@
 	SATTR(p, attr, ATTR_SIZE, ia_size);
 
 	if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
-		*p++ = htonl(attr->ia_atime);
+		*p++ = htonl(attr->ia_atime.tv_sec);
 		*p++ = 0;
 	} else {
 		*p++ = ~(u32) 0;
@@ -141,7 +139,7 @@
 	}
 
 	if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
-		*p++ = htonl(attr->ia_mtime);
+		*p++ = htonl(attr->ia_mtime.tv_sec);
 		*p++ = 0;
 	} else {
 		*p++ = ~(u32) 0;	
@@ -155,16 +153,6 @@
  * NFS encode functions
  */
 /*
- * Encode void argument
- */
-static int
-nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
-
-/*
  * Encode file handle argument
  * GETATTR, READLINK, STATFS
  */
@@ -463,15 +451,6 @@
  * NFS XDR decode functions
  */
 /*
- * Decode void reply
- */
-static int
-nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	return 0;
-}
-
-/*
  * Decode simple status reply
  */
 static int
@@ -663,31 +642,29 @@
 #endif
 
 #define PROC(proc, argtype, restype, timer)				\
-    { .p_procname =  "nfs_" #proc,					\
-      .p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
-      .p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
-      .p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2,	\
-      .p_timer    =  timer						\
-    }
-static struct rpc_procinfo	nfs_procedures[18] = {
-    PROC(null,		enc_void,	dec_void, 0),
-    PROC(getattr,	fhandle,	attrstat, 1),
-    PROC(setattr,	sattrargs,	attrstat, 0),
-    PROC(root,		enc_void,	dec_void, 0),
-    PROC(lookup,	diropargs,	diropres, 2),
-    PROC(readlink,	readlinkargs,	readlinkres, 3),
-    PROC(read,		readargs,	readres, 3),
-    PROC(writecache,	enc_void,	dec_void, 0),
-    PROC(write,		writeargs,	writeres, 4),
-    PROC(create,	createargs,	diropres, 0),
-    PROC(remove,	diropargs,	stat, 0),
-    PROC(rename,	renameargs,	stat, 0),
-    PROC(link,		linkargs,	stat, 0),
-    PROC(symlink,	symlinkargs,	stat, 0),
-    PROC(mkdir,		createargs,	diropres, 0),
-    PROC(rmdir,		diropargs,	stat, 0),
-    PROC(readdir,	readdirargs,	readdirres, 3),
-    PROC(statfs,	fhandle,	statfsres, 0),
+[NFSPROC_##proc] = {							\
+	.p_proc	    =  NFSPROC_##proc,					\
+	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
+	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
+	.p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2,	\
+	.p_timer    =  timer						\
+	}
+struct rpc_procinfo	nfs_procedures[] = {
+    PROC(GETATTR,	fhandle,	attrstat, 1),
+    PROC(SETATTR,	sattrargs,	attrstat, 0),
+    PROC(LOOKUP,	diropargs,	diropres, 2),
+    PROC(READLINK,	readlinkargs,	readlinkres, 3),
+    PROC(READ,		readargs,	readres, 3),
+    PROC(WRITE,		writeargs,	writeres, 4),
+    PROC(CREATE,	createargs,	diropres, 0),
+    PROC(REMOVE,	diropargs,	stat, 0),
+    PROC(RENAME,	renameargs,	stat, 0),
+    PROC(LINK,		linkargs,	stat, 0),
+    PROC(SYMLINK,	symlinkargs,	stat, 0),
+    PROC(MKDIR,		createargs,	diropres, 0),
+    PROC(RMDIR,		diropargs,	stat, 0),
+    PROC(READDIR,	readdirargs,	readdirres, 3),
+    PROC(STATFS,	fhandle,	statfsres, 0),
 };
 
 struct rpc_version		nfs_version2 = {
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	Sun Nov 17 20:30:14 2002
+++ b/fs/nfs/nfs3proc.c	Sun Nov 17 20:30:14 2002
@@ -19,6 +19,8 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
+extern struct rpc_procinfo nfs3_procedures[];
+
 /* A wrapper to handle the EJUKEBOX error message */
 static int
 nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
@@ -42,7 +44,7 @@
 nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
 	struct rpc_message msg = {
-		.rpc_proc	= proc,
+		.rpc_proc	= &nfs3_procedures[proc],
 		.rpc_argp	= argp,
 		.rpc_resp	= resp,
 	};
@@ -156,7 +158,7 @@
 		.fattr		= &fattr,
 	};
 	struct rpc_message msg = {
-		.rpc_proc	= NFS3PROC_ACCESS,
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -227,7 +229,7 @@
 		.count		= count,
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFS3PROC_READ,
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -262,7 +264,7 @@
 		.verf		= verf,
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFS3PROC_WRITE,
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -369,7 +371,7 @@
 		.len		= name->len
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFS3PROC_REMOVE,
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_REMOVE],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &dir_attr,
 	};
@@ -397,7 +399,7 @@
 	arg->name = name->name;
 	arg->len = name->len;
 	res->valid = 0;
-	msg->rpc_proc = NFS3PROC_REMOVE;
+	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
 	msg->rpc_argp = arg;
 	msg->rpc_resp = res;
 	return 0;
@@ -580,7 +582,7 @@
 		.plus		= plus
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFS3PROC_READDIR,
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_READDIR],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -590,7 +592,7 @@
 	lock_kernel();
 
 	if (plus)
-		msg.rpc_proc = NFS3PROC_READDIRPLUS;
+		msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
 
 	dprintk("NFS call  readdir%s %d\n",
 			plus? "plus" : "", (unsigned int) cookie);
@@ -697,7 +699,12 @@
 	struct inode		*inode = data->inode;
 	struct nfs_page		*req;
 	int			flags;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
+		.rpc_argp	= &data->u.v3.args,
+		.rpc_resp	= &data->u.v3.res,
+		.rpc_cred	= data->cred,
+	};
 	
 	req = nfs_list_entry(data->pages.next);
 	data->u.v3.args.fh     = NFS_FH(inode);
@@ -718,10 +725,6 @@
 	/* Release requests */
 	task->tk_release = nfs_readdata_release;
 
-	msg.rpc_proc = NFS3PROC_READ;
-	msg.rpc_argp = &data->u.v3.args;
-	msg.rpc_resp = &data->u.v3.res;
-	msg.rpc_cred = data->cred;
 	rpc_call_setup(&data->task, &msg, 0);
 }
 
@@ -744,7 +747,12 @@
 	struct nfs_page		*req;
 	int			stable;
 	int			flags;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
+		.rpc_argp	= &data->u.v3.args,
+		.rpc_resp	= &data->u.v3.res,
+		.rpc_cred	= data->cred,
+	};
 
 	if (how & FLUSH_STABLE) {
 		if (!NFS_I(inode)->ncommit)
@@ -774,10 +782,6 @@
 	/* Release requests */
 	task->tk_release = nfs_writedata_release;
 
-	msg.rpc_proc = NFS3PROC_WRITE;
-	msg.rpc_argp = &data->u.v3.args;
-	msg.rpc_resp = &data->u.v3.res;
-	msg.rpc_cred = data->cred;
 	rpc_call_setup(&data->task, &msg, 0);
 }
 
@@ -795,7 +799,12 @@
 	struct rpc_task		*task = &data->task;
 	struct inode		*inode = data->inode;
 	int			flags;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],
+		.rpc_argp	= &data->u.v3.args,
+		.rpc_resp	= &data->u.v3.res,
+		.rpc_cred	= data->cred,
+	};
 
 	data->u.v3.args.fh     = NFS_FH(data->inode);
 	data->u.v3.args.offset = start;
@@ -813,10 +822,6 @@
 	/* Release requests */
 	task->tk_release = nfs_commit_release;
 	
-	msg.rpc_proc = NFS3PROC_COMMIT;
-	msg.rpc_argp = &data->u.v3.args;
-	msg.rpc_resp = &data->u.v3.res;
-	msg.rpc_cred = data->cred;
 	rpc_call_setup(&data->task, &msg, 0);
 }
 
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Sun Nov 17 20:30:16 2002
+++ b/fs/nfs/nfs3xdr.c	Sun Nov 17 20:30:16 2002
@@ -48,7 +48,6 @@
 #define NFS3_pathconf_sz		
 #define NFS3_entry_sz		NFS3_filename_sz+3
 
-#define NFS3_enc_void_sz	0
 #define NFS3_sattrargs_sz	NFS3_fh_sz+NFS3_sattr_sz+3
 #define NFS3_diropargs_sz	NFS3_fh_sz+NFS3_filename_sz
 #define NFS3_accessargs_sz	NFS3_fh_sz+1
@@ -64,7 +63,6 @@
 #define NFS3_readdirargs_sz	NFS3_fh_sz+2
 #define NFS3_commitargs_sz	NFS3_fh_sz+3
 
-#define NFS3_dec_void_sz	0
 #define NFS3_attrstat_sz	1+NFS3_fattr_sz
 #define NFS3_wccstat_sz		1+NFS3_wcc_data_sz
 #define NFS3_lookupres_sz	1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)
@@ -214,7 +212,7 @@
 	}
 	if (attr->ia_valid & ATTR_ATIME_SET) {
 		*p++ = xdr_two;
-		p = xdr_encode_time(p, attr->ia_atime);
+		p = xdr_encode_time(p, attr->ia_atime.tv_sec);
 	} else if (attr->ia_valid & ATTR_ATIME) {
 		*p++ = xdr_one;
 	} else {
@@ -222,7 +220,7 @@
 	}
 	if (attr->ia_valid & ATTR_MTIME_SET) {
 		*p++ = xdr_two;
-		p = xdr_encode_time(p, attr->ia_mtime);
+		p = xdr_encode_time(p, attr->ia_mtime.tv_sec);
 	} else if (attr->ia_valid & ATTR_MTIME) {
 		*p++ = xdr_one;
 	} else {
@@ -268,15 +266,6 @@
 /*
  * NFS encode functions
  */
-/*
- * Encode void argument
- */
-static int
-nfs3_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
 
 /*
  * Encode file handle argument
@@ -652,14 +641,6 @@
 /*
  * NFS XDR decode functions
  */
-/*
- * Decode void reply
- */
-static int
-nfs3_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	return 0;
-}
 
 /*
  * Decode attrstat reply.
@@ -1004,36 +985,36 @@
 #endif
 
 #define PROC(proc, argtype, restype, timer)				\
-    { .p_procname  = "nfs3_" #proc,					\
-      .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
-      .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
-      .p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,	\
-      .p_timer     = timer						\
-    }
-
-static struct rpc_procinfo	nfs3_procedures[22] = {
-  PROC(null,		enc_void,	dec_void, 0),
-  PROC(getattr,		fhandle,	attrstat, 1),
-  PROC(setattr, 	sattrargs,	wccstat, 0),
-  PROC(lookup,		diropargs,	lookupres, 2),
-  PROC(access,		accessargs,	accessres, 1),
-  PROC(readlink,	readlinkargs,	readlinkres, 3),
-  PROC(read,		readargs,	readres, 3),
-  PROC(write,		writeargs,	writeres, 4),
-  PROC(create,		createargs,	createres, 0),
-  PROC(mkdir,		mkdirargs,	createres, 0),
-  PROC(symlink,		symlinkargs,	createres, 0),
-  PROC(mknod,		mknodargs,	createres, 0),
-  PROC(remove,		diropargs,	wccstat, 0),
-  PROC(rmdir,		diropargs,	wccstat, 0),
-  PROC(rename,		renameargs,	renameres, 0),
-  PROC(link,		linkargs,	linkres, 0),
-  PROC(readdir,		readdirargs,	readdirres, 3),
-  PROC(readdirplus,	readdirargs,	readdirres, 3),
-  PROC(fsstat,		fhandle,	fsstatres, 0),
-  PROC(fsinfo,  	fhandle,	fsinfores, 0),
-  PROC(pathconf,	fhandle,	pathconfres, 0),
-  PROC(commit,		commitargs,	commitres, 5),
+[NFS3PROC_##proc] = {							\
+	.p_proc      = NFS3PROC_##proc,					\
+	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
+	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
+	.p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,	\
+	.p_timer     = timer						\
+	}
+
+struct rpc_procinfo	nfs3_procedures[] = {
+  PROC(GETATTR,		fhandle,	attrstat, 1),
+  PROC(SETATTR, 	sattrargs,	wccstat, 0),
+  PROC(LOOKUP,		diropargs,	lookupres, 2),
+  PROC(ACCESS,		accessargs,	accessres, 1),
+  PROC(READLINK,	readlinkargs,	readlinkres, 3),
+  PROC(READ,		readargs,	readres, 3),
+  PROC(WRITE,		writeargs,	writeres, 4),
+  PROC(CREATE,		createargs,	createres, 0),
+  PROC(MKDIR,		mkdirargs,	createres, 0),
+  PROC(SYMLINK,		symlinkargs,	createres, 0),
+  PROC(MKNOD,		mknodargs,	createres, 0),
+  PROC(REMOVE,		diropargs,	wccstat, 0),
+  PROC(RMDIR,		diropargs,	wccstat, 0),
+  PROC(RENAME,		renameargs,	renameres, 0),
+  PROC(LINK,		linkargs,	linkres, 0),
+  PROC(READDIR,		readdirargs,	readdirres, 3),
+  PROC(READDIRPLUS,	readdirargs,	readdirres, 3),
+  PROC(FSSTAT,		fhandle,	fsstatres, 0),
+  PROC(FSINFO,  	fhandle,	fsinfores, 0),
+  PROC(PATHCONF,	fhandle,	pathconfres, 0),
+  PROC(COMMIT,		commitargs,	commitres, 5),
 };
 
 struct rpc_version		nfs_version3 = {
diff -Nru a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
--- a/fs/nfs/nfs4proc.c	Sun Nov 17 20:30:15 2002
+++ b/fs/nfs/nfs4proc.c	Sun Nov 17 20:30:15 2002
@@ -52,6 +52,7 @@
 #define OPNUM(cp)		cp->ops[cp->req_nops].opnum
 
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
+extern struct rpc_procinfo nfs4_procedures[];
 
 static nfs4_stateid zero_stateid =
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -642,7 +643,7 @@
 {
 	int status;
 	struct rpc_message msg = {
-		.rpc_proc = NFSPROC4_COMPOUND,
+		.rpc_proc = &nfs4_procedures[NFSPROC4_COMPOUND],
 		.rpc_argp = cp,
 		.rpc_resp = cp,
 		.rpc_cred = cred,
@@ -1106,7 +1107,7 @@
 	nfs4_setup_remove(cp, name, &up->cinfo);
 	nfs4_setup_getattr(cp, &up->attrs, bmres);
 	
-	msg->rpc_proc = NFSPROC4_COMPOUND;
+	msg->rpc_proc = &nfs4_procedures[NFSPROC4_COMPOUND];
 	msg->rpc_argp = cp;
 	msg->rpc_resp = cp;
 	return 0;
@@ -1367,7 +1368,7 @@
 	struct rpc_task	*task = &data->task;
 	struct nfs4_compound *cp = &data->u.v4.compound;
 	struct rpc_message msg = {
-		.rpc_proc = NFSPROC4_COMPOUND,
+		.rpc_proc = &nfs4_procedures[NFSPROC4_COMPOUND],
 		.rpc_argp = cp,
 		.rpc_resp = cp,
 		.rpc_cred = data->cred,
@@ -1411,7 +1412,7 @@
 	struct rpc_task	*task = &data->task;
 	struct nfs4_compound *cp = &data->u.v4.compound;
 	struct rpc_message msg = {
-		.rpc_proc = NFSPROC4_COMPOUND,
+		.rpc_proc = &nfs4_procedures[NFSPROC4_COMPOUND],
 		.rpc_argp = cp,
 		.rpc_resp = cp,
 		.rpc_cred = data->cred,
@@ -1462,7 +1463,7 @@
 	struct rpc_task	*task = &data->task;
 	struct nfs4_compound *cp = &data->u.v4.compound;
 	struct rpc_message msg = {
-		.rpc_proc = NFSPROC4_COMPOUND,
+		.rpc_proc = &nfs4_procedures[NFSPROC4_COMPOUND],
 		.rpc_argp = cp,
 		.rpc_resp = cp,
 		.rpc_cred = data->cred,
@@ -1516,7 +1517,9 @@
 	struct renew_desc *rp;
 	struct rpc_task *task;
 	struct nfs4_compound *cp;
-	struct rpc_message msg;
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_COMPOUND],
+	};
 
 	rp = (struct renew_desc *) kmalloc(sizeof(*rp), GFP_KERNEL);
 	if (!rp)
@@ -1527,10 +1530,8 @@
 	nfs4_setup_compound(cp, rp->ops, server, "renew");
 	nfs4_setup_renew(cp);
 	
-	msg.rpc_proc = NFSPROC4_COMPOUND;
 	msg.rpc_argp = cp;
 	msg.rpc_resp = cp;
-	msg.rpc_cred = NULL;
 	rpc_init_task(task, server->client, renew_done, RPC_TASK_ASYNC);
 	rpc_call_setup(task, &msg, 0);
 	task->tk_calldata = rp;
diff -Nru a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
--- a/fs/nfs/nfs4xdr.c	Sun Nov 17 20:30:16 2002
+++ b/fs/nfs/nfs4xdr.c	Sun Nov 17 20:30:16 2002
@@ -66,8 +66,6 @@
 
 extern int			nfs_stat_to_errno(int);
 
-#define NFS4_enc_void_sz	0
-#define NFS4_dec_void_sz	0
 #define NFS4_enc_compound_sz	1024  /* XXX: large enough? */
 #define NFS4_dec_compound_sz	1024  /* XXX: large enough? */
 
@@ -223,8 +221,8 @@
 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
 		WRITE32(NFS4_SET_TO_CLIENT_TIME);
 		WRITE32(0);
-		WRITE32(iap->ia_mtime);
-		WRITE32(0);
+		WRITE32(iap->ia_mtime.tv_sec);
+		WRITE32(iap->ia_mtime.tv_nsec);
 	}
 	else if (iap->ia_valid & ATTR_ATIME) {
 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
@@ -234,8 +232,8 @@
 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
 		WRITE32(NFS4_SET_TO_CLIENT_TIME);
 		WRITE32(0);
-		WRITE32(iap->ia_mtime);
-		WRITE32(0);
+		WRITE32(iap->ia_mtime.tv_sec);
+		WRITE32(iap->ia_mtime.tv_nsec);
 	}
 	else if (iap->ia_valid & ATTR_MTIME) {
 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
@@ -722,6 +720,7 @@
 	ENCODE_TAIL;
 }
 
+/* FIXME: this sucks */
 static int
 encode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
 {
@@ -826,16 +825,6 @@
 
 
 /*
- * Encode void argument
- */
-static int
-nfs4_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
-
-/*
  * Encode COMPOUND argument
  */
 static int
@@ -1546,6 +1535,7 @@
 	DECODE_TAIL;
 }
 
+/* FIXME: this sucks */
 static int
 decode_compound(struct nfs4_compound *cp, struct rpc_rqst *req)
 {
@@ -1680,15 +1670,6 @@
  */
 
 /*
- * Decode void reply
- */
-static int
-nfs4_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	return 0;
-}
-
-/*
  * Decode COMPOUND response
  */
 static int
@@ -1753,16 +1734,15 @@
 #endif
 
 #define PROC(proc, argtype, restype)				\
-    { "nfs4_" #proc,						\
-      (kxdrproc_t) nfs4_xdr_##argtype,				\
-      (kxdrproc_t) nfs4_xdr_##restype,				\
-      MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,	\
-      0							\
+[NFSPROC4_##proc] = {						\
+	.p_proc   = NFSPROC4_##proc,				\
+	.p_encode = (kxdrproc_t) nfs4_xdr_##argtype,		\
+	.p_decode = (kxdrproc_t) nfs4_xdr_##restype,		\
+	.p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,	\
     }
 
-static struct rpc_procinfo	nfs4_procedures[] = {
-  PROC(null,		enc_void,	dec_void),
-  PROC(compound,	enc_compound,	dec_compound)
+struct rpc_procinfo	nfs4_procedures[] = {
+  PROC(COMPOUND,	enc_compound,	dec_compound)
 };
 
 struct rpc_version		nfs_version4 = {
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	Sun Nov 17 20:30:15 2002
+++ b/fs/nfs/proc.c	Sun Nov 17 20:30:15 2002
@@ -46,6 +46,8 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
+extern struct rpc_procinfo nfs_procedures[];
+
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -153,7 +155,7 @@
 		.count		= count
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFSPROC_READ,
+		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -190,7 +192,7 @@
 		.count		= count
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFSPROC_WRITE,
+		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 		.rpc_cred	= cred
@@ -282,7 +284,7 @@
 		.len		= name->len
 	};
 	struct rpc_message	msg = { 
-		.rpc_proc	= NFSPROC_REMOVE,
+		.rpc_proc	= &nfs_procedures[NFSPROC_REMOVE],
 		.rpc_argp	= &arg,
 		.rpc_resp	= NULL,
 		.rpc_cred	= NULL
@@ -307,7 +309,7 @@
 	arg->fh = NFS_FH(dir->d_inode);
 	arg->name = name->name;
 	arg->len = name->len;
-	msg->rpc_proc = NFSPROC_REMOVE;
+	msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
 	msg->rpc_argp = arg;
 	return 0;
 }
@@ -441,7 +443,7 @@
 		.pages		= &page
 	};
 	struct rpc_message	msg = {
-		.rpc_proc	= NFSPROC_READDIR,
+		.rpc_proc	= &nfs_procedures[NFSPROC_READDIR],
 		.rpc_argp	= &arg,
 		.rpc_resp	= NULL,
 		.rpc_cred	= cred
@@ -532,7 +534,12 @@
 	struct inode		*inode = data->inode;
 	struct nfs_page		*req;
 	int			flags;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
+		.rpc_argp	= &data->u.v3.args,
+		.rpc_resp	= &data->u.v3.res,
+		.rpc_cred	= data->cred,
+	};
 	
 	req = nfs_list_entry(data->pages.next);
 	data->u.v3.args.fh     = NFS_FH(inode);
@@ -553,10 +560,6 @@
 	/* Release requests */
 	task->tk_release = nfs_readdata_release;
 
-	msg.rpc_proc = NFSPROC_READ;
-	msg.rpc_argp = &data->u.v3.args;
-	msg.rpc_resp = &data->u.v3.res;
-	msg.rpc_cred = data->cred;
 	rpc_call_setup(&data->task, &msg, 0);
 }
 
@@ -575,7 +578,12 @@
 	struct inode		*inode = data->inode;
 	struct nfs_page		*req;
 	int			flags;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
+		.rpc_argp	= &data->u.v3.args,
+		.rpc_resp	= &data->u.v3.res,
+		.rpc_cred	= data->cred,
+	};
 
 	/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
 	
@@ -599,10 +607,6 @@
 	/* Release requests */
 	task->tk_release = nfs_writedata_release;
 
-	msg.rpc_proc = NFSPROC_WRITE;
-	msg.rpc_argp = &data->u.v3.args;
-	msg.rpc_resp = &data->u.v3.res;
-	msg.rpc_cred = data->cred;
 	rpc_call_setup(&data->task, &msg, 0);
 }
 
diff -Nru a/fs/nfs/unlink.c b/fs/nfs/unlink.c
--- a/fs/nfs/unlink.c	Sun Nov 17 20:30:15 2002
+++ b/fs/nfs/unlink.c	Sun Nov 17 20:30:15 2002
@@ -93,14 +93,14 @@
 {
 	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;
 	struct dentry		*dir = data->dir;
-	struct rpc_message	msg;
+	struct rpc_message	msg = {
+		.rpc_cred	= data->cred,
+	};
 	int			status = -ENOENT;
 
 	if (!data->name.len)
 		goto out_err;
 
-	memset(&msg, 0, sizeof(msg));
-	msg.rpc_cred = data->cred;
 	status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name);
 	if (status < 0)
 		goto out_err;
diff -Nru a/fs/nfsctl.c b/fs/nfsctl.c
--- a/fs/nfsctl.c	Sun Nov 17 20:30:16 2002
+++ b/fs/nfsctl.c	Sun Nov 17 20:30:16 2002
@@ -12,6 +12,7 @@
 #include <linux/nfsd/syscall.h>
 #include <linux/linkage.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 /*
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Sun Nov 17 20:30:14 2002
+++ b/fs/nfsd/export.c	Sun Nov 17 20:30:14 2002
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/rwsem.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -545,10 +546,10 @@
 
 	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
 	if (ek && !IS_ERR(ek)) {
-		ek->h.expiry_time = CURRENT_TIME-1;
+		ek->h.expiry_time = get_seconds()-1;
 		expkey_put(&ek->h, &svc_expkey_cache);
 	}
-	svc_expkey_cache.nextcheck = CURRENT_TIME;
+	svc_expkey_cache.nextcheck = get_seconds();
 }
 
 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
@@ -579,10 +580,10 @@
 
 	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
 	if (ek && !IS_ERR(ek)) {
-		ek->h.expiry_time = CURRENT_TIME-1;
+		ek->h.expiry_time = get_seconds()-1;
 		expkey_put(&ek->h, &svc_expkey_cache);
 	}
-	svc_expkey_cache.nextcheck = CURRENT_TIME;
+	svc_expkey_cache.nextcheck = get_seconds();
 }
 	
 extern struct dentry *
@@ -732,8 +733,8 @@
 static void
 exp_do_unexport(svc_export *unexp)
 {
-	unexp->h.expiry_time = CURRENT_TIME-1;
-	svc_export_cache.nextcheck = CURRENT_TIME;
+	unexp->h.expiry_time = get_seconds()-1;
+	svc_export_cache.nextcheck = get_seconds();
 	exp_unhash(unexp);
 	exp_fsid_unhash(unexp);
 }
@@ -1053,7 +1054,7 @@
 	 */
 	if (dom) {
 		err = auth_unix_forget_old(dom);
-		dom->h.expiry_time = CURRENT_TIME;
+		dom->h.expiry_time = get_seconds();
 		auth_domain_put(dom);
 	}
 
diff -Nru a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
--- a/fs/nfsd/lockd.c	Sun Nov 17 20:30:15 2002
+++ b/fs/nfsd/lockd.c	Sun Nov 17 20:30:15 2002
@@ -9,6 +9,8 @@
  */
 
 #include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	Sun Nov 17 20:30:02 2002
+++ b/fs/nfsd/nfs3xdr.c	Sun Nov 17 20:30:02 2002
@@ -41,17 +41,18 @@
  * XDR functions for basic NFS types
  */
 static inline u32 *
-encode_time3(u32 *p, time_t secs)
+encode_time3(u32 *p, struct timespec *time)
 {
-	*p++ = htonl((u32) secs); *p++ = 0;
+	*p++ = htonl((u32) time->tv_sec); *p++ = htons(time->tv_nsec);
 	return p;
 }
 
 static inline u32 *
-decode_time3(u32 *p, time_t *secp)
+decode_time3(u32 *p, struct timespec *time)
 {
-	*secp = ntohl(*p++);
-	return p + 1;
+	time->tv_sec = ntohl(*p++);
+	time->tv_nsec = ntohl(*p++);
+	return p;
 }
 
 static inline u32 *
@@ -147,13 +148,15 @@
 		iap->ia_valid |= ATTR_ATIME;
 	} else if (tmp == 2) {		/* set to client time */
 		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
-		iap->ia_atime = ntohl(*p++), p++;
+		iap->ia_atime.tv_sec = ntohl(*p++);
+		iap->ia_atime.tv_nsec = ntohl(*p++);
 	}
 	if ((tmp = ntohl(*p++)) == 1) {	/* set to server time */
 		iap->ia_valid |= ATTR_MTIME;
 	} else if (tmp == 2) {		/* set to client time */
 		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
-		iap->ia_mtime = ntohl(*p++), p++;
+		iap->ia_mtime.tv_sec = ntohl(*p++);
+		iap->ia_mtime.tv_nsec = ntohl(*p++);
 	}
 	return p;
 }
@@ -164,6 +167,7 @@
 	struct vfsmount *mnt = fhp->fh_export->ex_mnt;
 	struct dentry	*dentry = fhp->fh_dentry;
 	struct kstat stat;
+	struct timespec time;
 
 	vfs_getattr(mnt, dentry, &stat);
 
@@ -187,9 +191,10 @@
 	else
 		p = xdr_encode_hyper(p, (u64) stat.dev);
 	p = xdr_encode_hyper(p, (u64) stat.ino);
-	p = encode_time3(p, stat.atime);
-	p = encode_time3(p, lease_get_mtime(dentry->d_inode));
-	p = encode_time3(p, stat.ctime);
+	p = encode_time3(p, &stat.atime);
+	lease_get_mtime(dentry->d_inode, &time); 
+	p = encode_time3(p, &time);
+	p = encode_time3(p, &stat.ctime);
 
 	return p;
 }
@@ -197,6 +202,7 @@
 static inline u32 *
 encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
 {
+	struct timespec  time;
 	struct inode	*inode = fhp->fh_dentry->d_inode;
 
 	/* Attributes to follow */
@@ -222,9 +228,13 @@
 	else
 		p = xdr_encode_hyper(p, (u64) inode->i_dev);
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
-	p = encode_time3(p, fhp->fh_post_atime);
-	p = encode_time3(p, fhp->fh_post_mtime);
-	p = encode_time3(p, fhp->fh_post_ctime);
+	time.tv_sec = fhp->fh_post_atime; 
+	time.tv_nsec = 0;
+	p = encode_time3(p, &time);
+	time.tv_sec = fhp->fh_post_mtime;
+	p = encode_time3(p, &time);
+	time.tv_sec = fhp->fh_post_ctime; 
+	p = encode_time3(p, &time);
 
 	return p;
 }
@@ -256,10 +266,14 @@
 
 	if (dentry && dentry->d_inode && fhp->fh_post_saved) {
 		if (fhp->fh_pre_saved) {
+			struct timespec time;
 			*p++ = xdr_one;
 			p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
-			p = encode_time3(p, fhp->fh_pre_mtime);
-			p = encode_time3(p, fhp->fh_pre_ctime);
+			time.tv_nsec = 0;
+			time.tv_sec =  fhp->fh_pre_mtime;
+			p = encode_time3(p, &time);
+			time.tv_sec = fhp->fh_pre_ctime;
+			p = encode_time3(p, &time);
 		} else {
 			*p++ = xdr_zero;
 		}
@@ -290,8 +304,11 @@
 	 || !(p = decode_sattr3(p, &args->attrs)))
 		return 0;
 
-	if ((args->check_guard = ntohl(*p++)) != 0)
-		p = decode_time3(p, &args->guardtime);
+	if ((args->check_guard = ntohl(*p++)) != 0) { 
+		struct timespec time; 
+		p = decode_time3(p, &time);
+		args->guardtime = time.tv_sec;
+	}
 
 	return xdr_argsize_check(rqstp, p);
 }
diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
--- a/fs/nfsd/nfs4xdr.c	Sun Nov 17 20:30:12 2002
+++ b/fs/nfsd/nfs4xdr.c	Sun Nov 17 20:30:12 2002
@@ -330,9 +330,9 @@
 			READ32(dummy32);
 			if (dummy32)
 				return nfserr_inval;
-			READ32(iattr->ia_atime);
-			READ32(dummy32);
-			if (dummy32 >= (u32)1000000000)
+			READ32(iattr->ia_atime.tv_sec);
+			READ32(iattr->ia_atime.tv_nsec);
+			if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
 				return nfserr_inval;
 			iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
 			break;
@@ -351,9 +351,9 @@
 		READ32(dummy32);
 		if (dummy32)
 			return nfserr_inval;
-		READ32(iattr->ia_ctime);
-		READ32(dummy32);
-		if (dummy32 >= (u32)1000000000)
+		READ32(iattr->ia_ctime.tv_sec);
+		READ32(iattr->ia_ctime.tv_nsec);
+		if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
 			return nfserr_inval;
 		iattr->ia_valid |= ATTR_CTIME;
 	}
@@ -370,9 +370,9 @@
 			READ32(dummy32);
 			if (dummy32)
 				return nfserr_inval;
-			READ32(iattr->ia_mtime);
-			READ32(dummy32);
-			if (dummy32 >= (u32)1000000000)
+			READ32(iattr->ia_mtime.tv_sec);
+			READ32(iattr->ia_mtime.tv_nsec);
+			if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
 				return nfserr_inval;
 			iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
 			break;
@@ -1071,7 +1071,7 @@
 		if ((buflen -= 8) < 0)
 			goto out_resource;
 		WRITE32(stat.size);
-		WRITE32(stat.mtime);
+		WRITE32(stat.mtime.tv_sec); /* AK: nsec dropped? */
 	}
 	if (bmval0 & FATTR4_WORD0_SIZE) {
 		if ((buflen -= 8) < 0)
@@ -1263,8 +1263,8 @@
 		if ((buflen -= 12) < 0)
 			goto out_resource;
 		WRITE32(0);
-		WRITE32(stat.atime);
-		WRITE32(0);
+		WRITE32(stat.atime.tv_sec);
+		WRITE32(stat.atime.tv_nsec);
 	}
 	if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
 		if ((buflen -= 12) < 0)
@@ -1277,15 +1277,15 @@
 		if ((buflen -= 12) < 0)
 			goto out_resource;
 		WRITE32(0);
-		WRITE32(stat.ctime);
-		WRITE32(0);
+		WRITE32(stat.ctime.tv_sec);
+		WRITE32(stat.ctime.tv_nsec);
 	}
 	if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
 		if ((buflen -= 12) < 0)
 			goto out_resource;
 		WRITE32(0);
-		WRITE32(stat.mtime);
-		WRITE32(0);
+		WRITE32(stat.mtime.tv_sec);
+		WRITE32(stat.mtime.tv_nsec);
 	}
 
 	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	Sun Nov 17 20:30:12 2002
+++ b/fs/nfsd/nfsfh.c	Sun Nov 17 20:30:12 2002
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/dcache.h>
+#include <linux/mount.h>
 #include <asm/pgtable.h>
 
 #include <linux/sunrpc/svc.h>
diff -Nru a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
--- a/fs/nfsd/nfsxdr.c	Sun Nov 17 20:30:02 2002
+++ b/fs/nfsd/nfsxdr.c	Sun Nov 17 20:30:02 2002
@@ -122,12 +122,14 @@
 	tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
 	if (tmp != (u32)-1 && tmp1 != (u32)-1) {
 		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
-		iap->ia_atime = tmp;
+		iap->ia_atime.tv_sec = tmp;
+		iap->ia_atime.tv_nsec = tmp1; 
 	}
 	tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
 	if (tmp != (u32)-1 && tmp1 != (u32)-1) {
 		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
-		iap->ia_mtime = tmp;
+		iap->ia_mtime.tv_sec = tmp;
+		iap->ia_mtime.tv_nsec = tmp1; 
 	}
 	return p;
 }
@@ -139,6 +141,7 @@
 	struct dentry	*dentry = fhp->fh_dentry;
 	struct kstat stat;
 	int type;
+	struct timespec time;
 
 	vfs_getattr(mnt, dentry, &stat);
 	type = (stat.mode & S_IFMT);
@@ -167,12 +170,13 @@
 	else
 		*p++ = htonl((u32) stat.dev);
 	*p++ = htonl((u32) stat.ino);
-	*p++ = htonl((u32) stat.atime);
-	*p++ = 0;
-	*p++ = htonl((u32) lease_get_mtime(dentry->d_inode));
-	*p++ = 0;
-	*p++ = htonl((u32) stat.ctime);
-	*p++ = 0;
+	*p++ = htonl((u32) stat.atime.tv_sec);
+	*p++ = htons(stat.atime.tv_nsec);
+	lease_get_mtime(dentry->d_inode, &time); 
+	*p++ = htonl((u32) time.tv_sec);
+	*p++ = htons(time.tv_nsec); 
+	*p++ = htonl((u32) stat.ctime.tv_sec);
+	*p++ = htons(stat.ctime.tv_nsec);
 
 	return p;
 }
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Sun Nov 17 20:30:13 2002
+++ b/fs/nfsd/vfs.c	Sun Nov 17 20:30:13 2002
@@ -21,6 +21,7 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/major.h>
 #include <linux/ext2_fs.h>
 #include <linux/proc_fs.h>
@@ -229,13 +230,13 @@
 #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
 #define	MAX_TOUCH_TIME_ERROR (30*60)
 	if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
-	    && iap->ia_mtime == iap->ia_atime
+	    && iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec
 	    ) {
 	    /* Looks probable.  Now just make sure time is in the right ballpark.
 	     * Solaris, at least, doesn't seem to care what the time request is.
 	     * We require it be within 30 minutes of now.
 	     */
-	    time_t delta = iap->ia_atime - CURRENT_TIME;
+	    time_t delta = iap->ia_atime.tv_sec - get_seconds();
 	    if (delta<0) delta = -delta;
 	    if (delta < MAX_TOUCH_TIME_ERROR &&
 		inode_change_ok(inode, iap) != 0) {
@@ -292,7 +293,7 @@
 	iap->ia_valid |= ATTR_CTIME;
 
 	err = nfserr_notsync;
-	if (!check_guard || guardtime == inode->i_ctime) {
+	if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
 		fh_lock(fhp);
 		err = notify_change(dentry, iap);
 		err = nfserrno(err);
@@ -1029,8 +1030,8 @@
 			}
 			break;
 		case NFS3_CREATE_EXCLUSIVE:
-			if (   dchild->d_inode->i_mtime == v_mtime
-			    && dchild->d_inode->i_atime == v_atime
+			if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
+			    && dchild->d_inode->i_atime.tv_sec == v_atime
 			    && dchild->d_inode->i_mode  == v_mode
 			    && dchild->d_inode->i_size  == 0 )
 				break;
@@ -1062,8 +1063,11 @@
 		iap->ia_valid = ATTR_MTIME|ATTR_ATIME
 			| ATTR_MTIME_SET|ATTR_ATIME_SET
 			| ATTR_MODE;
-		iap->ia_mtime = v_mtime;
-		iap->ia_atime = v_atime;
+		/* XXX someone who knows this better please fix it for nsec */ 
+		iap->ia_mtime.tv_sec = v_mtime;
+		iap->ia_atime.tv_sec = v_atime;
+		iap->ia_mtime.tv_nsec = 0;
+		iap->ia_atime.tv_nsec = 0;
 		iap->ia_mode  = v_mode;
 	}
 
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/ntfs/inode.c	Sun Nov 17 20:30:15 2002
@@ -23,6 +23,7 @@
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
 #include <linux/quotaops.h>
+#include <linux/mount.h>
 
 #include "ntfs.h"
 #include "dir.h"
@@ -589,18 +590,21 @@
 	 * mtime is the last change of the data within the file. Not changed
 	 * when only metadata is changed, e.g. a rename doesn't affect mtime.
 	 */
-	vi->i_mtime = ntfs2utc(si->last_data_change_time);
+	vi->i_mtime.tv_sec = ntfs2utc(si->last_data_change_time);
+	vi->i_mtime.tv_nsec = 0;
 	/*
 	 * ctime is the last change of the metadata of the file. This obviously
 	 * always changes, when mtime is changed. ctime can be changed on its
 	 * own, mtime is then not changed, e.g. when a file is renamed.
 	 */
-	vi->i_ctime = ntfs2utc(si->last_mft_change_time);
+	vi->i_ctime.tv_sec = ntfs2utc(si->last_mft_change_time);
+	vi->i_ctime.tv_nsec = 0;
 	/*
 	 * Last access to the data within the file. Not changed during a rename
 	 * for example but changed whenever the file is written to.
 	 */
-	vi->i_atime = ntfs2utc(si->last_access_time);
+	vi->i_atime.tv_sec = ntfs2utc(si->last_access_time);
+	vi->i_atime.tv_nsec = 0;
 
 	/* Find the attribute list attribute if present. */
 	reinit_attr_search_ctx(ctx);
diff -Nru a/fs/ntfs/time.c b/fs/ntfs/time.c
--- a/fs/ntfs/time.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ntfs/time.c	Sun Nov 17 20:30:14 2002
@@ -54,7 +54,8 @@
  */
 inline s64 get_current_ntfs_time(void)
 {
-	return utc2ntfs(CURRENT_TIME);
+	/* ignores leap second */
+	return utc2ntfs(get_seconds()) + xtime.tv_nsec/1000;
 }
 
 /**
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Sun Nov 17 20:30:02 2002
+++ b/fs/open.c	Sun Nov 17 20:30:02 2002
@@ -17,6 +17,7 @@
 #include <linux/namei.h>
 #include <linux/backing-dev.h>
 #include <linux/security.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 
@@ -250,9 +251,11 @@
 	/* Don't worry, the checks are done in inode_change_ok() */
 	newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 	if (times) {
-		error = get_user(newattrs.ia_atime, &times->actime);
+		error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
+		newattrs.ia_atime.tv_nsec = 0;
 		if (!error) 
-			error = get_user(newattrs.ia_mtime, &times->modtime);
+			error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
+		newattrs.ia_mtime.tv_nsec = 0;
 		if (error)
 			goto dput_and_out;
 
@@ -301,8 +304,10 @@
 		error = -EFAULT;
 		if (copy_from_user(&times, utimes, sizeof(times)))
 			goto dput_and_out;
-		newattrs.ia_atime = times[0].tv_sec;
-		newattrs.ia_mtime = times[1].tv_sec;
+		newattrs.ia_atime.tv_sec = times[0].tv_sec;
+		newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000;
+		newattrs.ia_mtime.tv_sec = times[1].tv_sec;
+		newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000;
 		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 	} else {
 		if (current->fsuid != inode->i_uid &&
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Sun Nov 17 20:30:15 2002
+++ b/fs/partitions/check.c	Sun Nov 17 20:30:15 2002
@@ -163,7 +163,7 @@
 
 	if (p[part-1].de)
 		return;
-	dir = devfs_get_parent(dev->disk_de);
+	dir = dev->de;
 	if (!dir)
 		return;
 	if (dev->flags & GENHD_FL_REMOVABLE)
@@ -178,7 +178,6 @@
 
 #ifdef CONFIG_DEVFS_FS
 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
-static devfs_handle_t cdroms;
 static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
 #endif
 
@@ -189,9 +188,6 @@
 	devfs_handle_t dir, slave;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char dirname[64], symlink[16];
-	static devfs_handle_t devfs_handle;
-	int part, max_p = dev->minors;
-	struct hd_struct *p = dev->part;
 
 	if (dev->flags & GENHD_FL_REMOVABLE)
 		devfs_flags |= DEVFS_FL_REMOVABLE;
@@ -208,36 +204,25 @@
 		sprintf(dirname, "../%s/disc%d", dev->disk_name,
 			dev->first_minor >> dev->minor_shift);
 		dir = devfs_mk_dir(NULL, dirname + 3, NULL);
+		dev->de = dir;
 	}
-	if (!devfs_handle)
-		devfs_handle = devfs_mk_dir(NULL, "discs", NULL);
 	dev->number = devfs_alloc_unique_number (&disc_numspace);
-	sprintf(symlink, "disc%d", dev->number);
-	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
+	sprintf(symlink, "discs/disc%d", dev->number);
+	devfs_mk_symlink(NULL, symlink, DEVFS_FL_DEFAULT,
 			  dirname + pos, &slave, NULL);
 	dev->disk_de = devfs_register(dir, "disc", devfs_flags,
 			    dev->major, dev->first_minor,
 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
-	devfs_auto_unregister(dev->disk_de, slave);
-	if (!(dev->flags & GENHD_FL_DEVFS))
-		devfs_auto_unregister (slave, dir);
 #endif
 }
 
 static void devfs_create_cdrom(struct gendisk *dev)
 {
 #ifdef CONFIG_DEVFS_FS
-	int pos = 0;
-	devfs_handle_t dir, slave;
-	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
-	char dirname[64], symlink[16];
 	char vname[23];
 
-	if (!cdroms)
-		cdroms = devfs_mk_dir (NULL, "cdroms", NULL);
-
 	dev->number = devfs_alloc_unique_number(&cdrom_numspace);
-	sprintf(vname, "cdrom%d", dev->number);
+	sprintf(vname, "cdroms/cdrom%d", dev->number);
 	if (dev->de) {
 		int pos;
 		devfs_handle_t slave;
@@ -251,10 +236,8 @@
 		pos = devfs_generate_path(dev->disk_de, rname+3, sizeof(rname)-3);
 		if (pos >= 0) {
 			strncpy(rname + pos, "../", 3);
-			devfs_mk_symlink(cdroms, vname,
-					 DEVFS_FL_DEFAULT,
+			devfs_mk_symlink(NULL, vname, DEVFS_FL_DEFAULT,
 					 rname + pos, &slave, NULL);
-			devfs_auto_unregister(dev->de, slave);
 		}
 	} else {
 		dev->disk_de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
@@ -270,10 +253,18 @@
 #ifdef CONFIG_DEVFS_FS
 	devfs_unregister(dev->disk_de);
 	dev->disk_de = NULL;
-	if (dev->flags & GENHD_FL_CD)
+	if (dev->flags & GENHD_FL_CD) {
+		if (dev->de)
+			devfs_remove("cdroms/cdrom%d", dev->number);
 		devfs_dealloc_unique_number(&cdrom_numspace, dev->number);
-	else
+	} else {
+		devfs_remove("discs/disc%d", dev->number);
+		if (!(dev->flags & GENHD_FL_DEVFS)) {
+			devfs_unregister(dev->de);
+			dev->de = NULL;
+		}
 		devfs_dealloc_unique_number(&disc_numspace, dev->number);
+	}
 #endif
 }
 
@@ -458,8 +449,6 @@
 	struct parsed_partitions *state;
 	int p, res;
 
-	if (!bdev->bd_invalidated)
-		return 0;
 	if (bdev->bd_part_count)
 		return -EBUSY;
 	res = invalidate_device(dev, 1);
diff -Nru a/fs/pipe.c b/fs/pipe.c
--- a/fs/pipe.c	Sun Nov 17 20:30:14 2002
+++ b/fs/pipe.c	Sun Nov 17 20:30:14 2002
@@ -11,7 +11,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-
+#include <linux/mount.h>
+#include <linux/pipe_fs_i.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Sun Nov 17 20:30:14 2002
+++ b/fs/proc/base.c	Sun Nov 17 20:30:14 2002
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/kallsyms.h>
+#include <linux/mount.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	Sun Nov 17 20:30:16 2002
+++ b/fs/proc/generic.c	Sun Nov 17 20:30:16 2002
@@ -8,15 +8,14 @@
  * Copyright (C) 1997 Theodore Ts'o
  */
 
-#include <asm/uaccess.h>
-
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
-#define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/smp_lock.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 static ssize_t proc_file_read(struct file * file, char * buf,
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Sun Nov 17 20:30:03 2002
+++ b/fs/proc/proc_misc.c	Sun Nov 17 20:30:03 2002
@@ -296,17 +296,6 @@
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
-extern struct seq_operations ksyms_op;
-static int ksyms_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &ksyms_op);
-}
-static struct file_operations proc_ksyms_operations = {
-	.open		= ksyms_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
 #endif
 
 extern struct seq_operations slabinfo_op;
@@ -604,7 +593,6 @@
 	create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_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);
 	if (proc_root_kcore) {
diff -Nru a/fs/qnx4/inode.c b/fs/qnx4/inode.c
--- a/fs/qnx4/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/qnx4/inode.c	Sun Nov 17 20:30:15 2002
@@ -111,9 +111,9 @@
 	raw_inode->di_gid   = cpu_to_le16(fs_high2lowgid(inode->i_gid));
 	raw_inode->di_nlink = cpu_to_le16(inode->i_nlink);
 	raw_inode->di_size  = cpu_to_le32(inode->i_size);
-	raw_inode->di_mtime = cpu_to_le32(inode->i_mtime);
-	raw_inode->di_atime = cpu_to_le32(inode->i_atime);
-	raw_inode->di_ctime = cpu_to_le32(inode->i_ctime);
+	raw_inode->di_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
+	raw_inode->di_atime = cpu_to_le32(inode->i_atime.tv_sec);
+	raw_inode->di_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
 	raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks);
 	mark_buffer_dirty(bh);
 	brelse(bh);
@@ -480,9 +480,12 @@
 	inode->i_gid     = (gid_t)le16_to_cpu(raw_inode->di_gid);
 	inode->i_nlink   = le16_to_cpu(raw_inode->di_nlink);
 	inode->i_size    = le32_to_cpu(raw_inode->di_size);
-	inode->i_mtime   = le32_to_cpu(raw_inode->di_mtime);
-	inode->i_atime   = le32_to_cpu(raw_inode->di_atime);
-	inode->i_ctime   = le32_to_cpu(raw_inode->di_ctime);
+	inode->i_mtime.tv_sec   = le32_to_cpu(raw_inode->di_mtime);
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_sec   = le32_to_cpu(raw_inode->di_atime);
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_sec   = le32_to_cpu(raw_inode->di_ctime);
+	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
 	inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
 
diff -Nru a/fs/quota_v2.c b/fs/quota_v2.c
--- a/fs/quota_v2.c	Sun Nov 17 20:30:15 2002
+++ b/fs/quota_v2.c	Sun Nov 17 20:30:15 2002
@@ -4,6 +4,7 @@
 
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/dqblk_v2.h>
 #include <linux/quotaio_v2.h>
 #include <linux/kernel.h>
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Sun Nov 17 20:30:12 2002
+++ b/fs/reiserfs/inode.c	Sun Nov 17 20:30:12 2002
@@ -885,9 +885,12 @@
 	inode->i_uid   = sd_v1_uid(sd);
 	inode->i_gid   = sd_v1_gid(sd);
 	inode->i_size  = sd_v1_size(sd);
-	inode->i_atime = sd_v1_atime(sd);
-	inode->i_mtime = sd_v1_mtime(sd);
-	inode->i_ctime = sd_v1_ctime(sd);
+	inode->i_atime.tv_sec = sd_v1_atime(sd);
+	inode->i_mtime.tv_sec = sd_v1_mtime(sd);
+	inode->i_ctime.tv_sec = sd_v1_ctime(sd);
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
 
 	inode->i_blocks = sd_v1_blocks(sd);
 	inode->i_generation = le32_to_cpu (INODE_PKEY (inode)->k_dir_id);
@@ -914,9 +917,12 @@
 	inode->i_uid    = sd_v2_uid(sd);
 	inode->i_size   = sd_v2_size(sd);
 	inode->i_gid    = sd_v2_gid(sd);
-	inode->i_mtime  = sd_v2_mtime(sd);
-	inode->i_atime  = sd_v2_atime(sd);
-	inode->i_ctime  = sd_v2_ctime(sd);
+	inode->i_mtime.tv_sec  = sd_v2_mtime(sd);
+	inode->i_atime.tv_sec = sd_v2_atime(sd);
+	inode->i_ctime.tv_sec  = sd_v2_ctime(sd);
+	inode->i_ctime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
 	inode->i_blocks = sd_v2_blocks(sd);
         rdev            = sd_v2_rdev(sd);
 	if( S_ISCHR( inode -> i_mode ) || S_ISBLK( inode -> i_mode ) )
@@ -960,9 +966,9 @@
     set_sd_v2_uid(sd_v2, inode->i_uid );
     set_sd_v2_size(sd_v2, inode->i_size );
     set_sd_v2_gid(sd_v2, inode->i_gid );
-    set_sd_v2_mtime(sd_v2, inode->i_mtime );
-    set_sd_v2_atime(sd_v2, inode->i_atime );
-    set_sd_v2_ctime(sd_v2, inode->i_ctime );
+    set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec );
+    set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec );
+    set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec );
     set_sd_v2_blocks(sd_v2, inode->i_blocks );
     if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
         set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) );
@@ -984,9 +990,9 @@
     set_sd_v1_gid(sd_v1, inode->i_gid );
     set_sd_v1_nlink(sd_v1, inode->i_nlink );
     set_sd_v1_size(sd_v1, inode->i_size );
-    set_sd_v1_atime(sd_v1, inode->i_atime );
-    set_sd_v1_ctime(sd_v1, inode->i_ctime );
-    set_sd_v1_mtime(sd_v1, inode->i_mtime );
+    set_sd_v1_atime(sd_v1, inode->i_atime.tv_sec );
+    set_sd_v1_ctime(sd_v1, inode->i_ctime.tv_sec );
+    set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec );
 
     if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
         set_sd_v1_rdev(sd_v1, kdev_t_to_nr(inode->i_rdev) );
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Sun Nov 17 20:30:14 2002
+++ b/fs/reiserfs/journal.c	Sun Nov 17 20:30:14 2002
@@ -1246,7 +1246,7 @@
     i = (start + 1) % JOURNAL_LIST_COUNT ;
     while(i != start) {
         jl = SB_JOURNAL_LIST(s) + i  ;
-        age = CURRENT_TIME - jl->j_timestamp ;
+        age = get_seconds() - jl->j_timestamp ;
         if (jl->j_len > 0 && // age >= (JOURNAL_MAX_COMMIT_AGE * 2) && 
             atomic_read(&(jl->j_nonzerolen)) > 0 &&
             atomic_read(&(jl->j_commit_left)) == 0) {
@@ -1655,7 +1655,7 @@
   cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) ;
   printk("reiserfs: checking transaction log (%s) for (%s)\n",
 	 bdevname(SB_JOURNAL(p_s_sb)->j_dev_bd), reiserfs_bdevname(p_s_sb));
-  start = CURRENT_TIME ;
+  start = get_seconds() ;
 
   /* step 1, read in the journal header block.  Check the transaction it says 
   ** is the first unflushed, and if that transaction is not valid, 
@@ -1783,7 +1783,7 @@
   SB_JOURNAL(p_s_sb)->j_first_unflushed_offset = SB_JOURNAL(p_s_sb)->j_start ; 
   if (replay_count > 0) {
     printk("reiserfs: replayed %d transactions in %lu seconds\n", replay_count, 
-	    CURRENT_TIME - start) ;
+	    get_seconds() - start) ;
   }
   if (!bdev_read_only(p_s_sb->s_bdev) && 
        _update_journal_header_block(p_s_sb, SB_JOURNAL(p_s_sb)->j_start, 
@@ -2141,7 +2141,7 @@
 ** transaction
 */
 int journal_transaction_should_end(struct reiserfs_transaction_handle *th, int new_alloc) {
-  time_t now = CURRENT_TIME ;
+  time_t now = get_seconds() ;
   if (reiserfs_dont_log(th->t_super)) 
     return 0 ;
   if ( SB_JOURNAL(th->t_super)->j_must_wait > 0 ||
@@ -2187,7 +2187,7 @@
 ** expect to use in nblocks.
 */
 static int do_journal_begin_r(struct reiserfs_transaction_handle *th, struct super_block * p_s_sb,unsigned long nblocks,int join) {
-  time_t now = CURRENT_TIME ;
+  time_t now = get_seconds() ;
   int old_trans_id  ;
 
   reiserfs_check_lock_depth("journal_begin") ;
@@ -2557,7 +2557,7 @@
   struct reiserfs_transaction_handle th ; 
 
   start =  SB_JOURNAL_LIST_INDEX(p_s_sb) ;
-  now = CURRENT_TIME ;
+  now = get_seconds() ;
 
   /* safety check so we don't flush while we are replaying the log during mount */
   if (SB_JOURNAL_LIST_INDEX(p_s_sb) < 0) {
@@ -2673,7 +2673,7 @@
   }
 
   /* deal with old transactions where we are the last writers */
-  now = CURRENT_TIME ;
+  now = get_seconds() ;
   if ((now - SB_JOURNAL(p_s_sb)->j_trans_start_time) > SB_JOURNAL_MAX_TRANS_AGE(p_s_sb)) {
     commit_now = 1 ;
     SB_JOURNAL(p_s_sb)->j_next_async_flush = 1 ;
@@ -3126,7 +3126,7 @@
     /* this check should always be run, to send old lists to disk */
     if (SB_JOURNAL_LIST(p_s_sb)[jindex].j_len > 0 && 
               SB_JOURNAL_LIST(p_s_sb)[jindex].j_timestamp < 
-	      (CURRENT_TIME - (SB_JOURNAL_MAX_TRANS_AGE(p_s_sb) * 4))) {
+	      (get_seconds() - (SB_JOURNAL_MAX_TRANS_AGE(p_s_sb) * 4))) {
 	flush_journal_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + jindex, 1 ) ; 
     }
   }
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Sun Nov 17 20:30:14 2002
+++ b/fs/reiserfs/namei.c	Sun Nov 17 20:30:14 2002
@@ -968,7 +968,6 @@
     int windex ;
     struct reiserfs_transaction_handle th ;
     int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
-    time_t ctime;
 
     reiserfs_write_lock(dir->i_sb);
     if (inode->i_nlink >= REISERFS_LINK_MAX) {
@@ -995,8 +994,7 @@
     }
 
     inode->i_nlink++;
-    ctime = CURRENT_TIME;
-    inode->i_ctime = ctime;
+    inode->i_ctime = CURRENT_TIME;
     reiserfs_update_sd (&th, inode);
 
     atomic_inc(&inode->i_count) ;
@@ -1069,8 +1067,6 @@
     struct reiserfs_transaction_handle th ;
     int jbegin_count ; 
     umode_t old_inode_mode;
-    time_t ctime;
-
 
     /* two balancings: old name removal, new name insertion or "save" link,
        stat data updates: old directory and new directory and maybe block
@@ -1238,7 +1234,7 @@
 
     mark_de_hidden (old_de.de_deh + old_de.de_entry_num);
     journal_mark_dirty (&th, old_dir->i_sb, old_de.de_bh);
-    old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+    old_dir->i_ctime = old_dir->i_mtime = 
     new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
 
     if (new_dentry_inode) {
@@ -1248,8 +1244,7 @@
 	} else {
 	    new_dentry_inode->i_nlink--;
 	}
-	ctime = CURRENT_TIME;
-	new_dentry_inode->i_ctime = ctime;
+	new_dentry_inode->i_ctime = new_dir->i_ctime;
     }
 
     if (S_ISDIR(old_inode_mode)) {
diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c
--- a/fs/romfs/inode.c	Sun Nov 17 20:30:14 2002
+++ b/fs/romfs/inode.c	Sun Nov 17 20:30:14 2002
@@ -500,7 +500,8 @@
 
 	i->i_nlink = 1;		/* Hard to decide.. */
 	i->i_size = ntohl(ri.size);
-	i->i_mtime = i->i_atime = i->i_ctime = 0;
+	i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
+	i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
 	i->i_uid = i->i_gid = 0;
 
         /* Precalculate the data offset */
diff -Nru a/fs/select.c b/fs/select.c
--- a/fs/select.c	Sun Nov 17 20:30:02 2002
+++ b/fs/select.c	Sun Nov 17 20:30:02 2002
@@ -53,10 +53,18 @@
  * as all select/poll functions have to call it to add an entry to the
  * poll table.
  */
+void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p);
 
-void poll_freewait(poll_table* pt)
+void poll_initwait(struct poll_wqueues *pwq)
 {
-	struct poll_table_page * p = pt->table;
+	init_poll_funcptr(&pwq->pt, __pollwait);
+	pwq->error = 0;
+	pwq->table = NULL;
+}
+
+void poll_freewait(struct poll_wqueues *pwq)
+{
+	struct poll_table_page * p = pwq->table;
 	while (p) {
 		struct poll_table_entry * entry;
 		struct poll_table_page *old;
@@ -73,18 +81,11 @@
 	}
 }
 
-void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
+void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p)
 {
+	struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
 	struct poll_table_page *table = p->table;
 
-	if (!p->queue)
-		return;
-
-	if (p->qproc) {
-		p->qproc(p->priv, wait_address);
-		return;
-	}
-
 	if (!table || POLL_TABLE_FULL(table)) {
 		struct poll_table_page *new_table;
 
@@ -112,6 +113,7 @@
 	}
 }
 
+
 #define __IN(fds, n)		(fds->in + n)
 #define __OUT(fds, n)		(fds->out + n)
 #define __EX(fds, n)		(fds->ex + n)
@@ -172,7 +174,8 @@
 
 int do_select(int n, fd_set_bits *fds, long *timeout)
 {
-	poll_table table, *wait;
+	struct poll_wqueues table;
+	poll_table *wait;
 	int retval, i, off;
 	long __timeout = *timeout;
 
@@ -185,7 +188,7 @@
 	n = retval;
 
 	poll_initwait(&table);
-	wait = &table;
+	wait = &table.pt;
 	if (!__timeout)
 		wait = NULL;
 	retval = 0;
@@ -392,10 +395,10 @@
 }
 
 static int do_poll(unsigned int nfds, unsigned int nchunks, unsigned int nleft, 
-	struct pollfd *fds[], poll_table *wait, long timeout)
+	struct pollfd *fds[], struct poll_wqueues *wait, long timeout)
 {
 	int count;
-	poll_table* pt = wait;
+	poll_table* pt = &wait->pt;
 
 	for (;;) {
 		unsigned int i;
@@ -422,7 +425,7 @@
 {
 	int i, j, fdcount, err;
 	struct pollfd **fds;
-	poll_table table, *wait;
+	struct poll_wqueues table, *wait;
 	int nchunks, nleft;
 
 	/* Do a sanity check on nfds ... */
diff -Nru a/fs/smbfs/cache.c b/fs/smbfs/cache.c
--- a/fs/smbfs/cache.c	Sun Nov 17 20:30:14 2002
+++ b/fs/smbfs/cache.c	Sun Nov 17 20:30:14 2002
@@ -16,6 +16,7 @@
 #include <linux/dirent.h>
 #include <linux/smb_fs.h>
 #include <linux/pagemap.h>
+#include <linux/net.h>
 
 #include <asm/page.h>
 
diff -Nru a/fs/smbfs/dir.c b/fs/smbfs/dir.c
--- a/fs/smbfs/dir.c	Sun Nov 17 20:30:15 2002
+++ b/fs/smbfs/dir.c	Sun Nov 17 20:30:15 2002
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/ctype.h>
+#include <linux/net.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smb_mount.h>
@@ -511,7 +512,7 @@
 
 	lock_kernel();
 	smb_invalid_dir_cache(dir);
-	error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
+	error = smb_proc_create(dentry, 0, get_seconds(), &fileid);
 	if (!error) {
 		if (server->opt.capabilities & SMB_CAP_UNIX) {
 			/* Set attributes for new file */
diff -Nru a/fs/smbfs/file.c b/fs/smbfs/file.c
--- a/fs/smbfs/file.c	Sun Nov 17 20:30:15 2002
+++ b/fs/smbfs/file.c	Sun Nov 17 20:30:15 2002
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/net.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/smbfs/getopt.c b/fs/smbfs/getopt.c
--- a/fs/smbfs/getopt.c	Sun Nov 17 20:30:14 2002
+++ b/fs/smbfs/getopt.c	Sun Nov 17 20:30:14 2002
@@ -4,6 +4,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/net.h>
 
 #include "getopt.h"
 
diff -Nru a/fs/smbfs/inode.c b/fs/smbfs/inode.c
--- a/fs/smbfs/inode.c	Sun Nov 17 20:30:03 2002
+++ b/fs/smbfs/inode.c	Sun Nov 17 20:30:03 2002
@@ -22,6 +22,8 @@
 #include <linux/smp_lock.h>
 #include <linux/nls.h>
 #include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/net.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -183,7 +185,7 @@
 	 * A size change should have a different mtime, or same mtime
 	 * but different size.
 	 */
-	time_t last_time = inode->i_mtime;
+	time_t last_time = inode->i_mtime.tv_sec;
 	loff_t last_sz = inode->i_size;
 
 	inode->i_mode	= fattr->f_mode;
@@ -203,7 +205,7 @@
 	 */
 	ei->oldmtime = jiffies;
 
-	if (inode->i_mtime != last_time || inode->i_size != last_sz) {
+	if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {
 		VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
 			inode->i_ino,
 			(long) last_time, (long) inode->i_mtime,
diff -Nru a/fs/smbfs/ioctl.c b/fs/smbfs/ioctl.c
--- a/fs/smbfs/ioctl.c	Sun Nov 17 20:30:02 2002
+++ b/fs/smbfs/ioctl.c	Sun Nov 17 20:30:02 2002
@@ -13,6 +13,7 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/highuid.h>
+#include <linux/net.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smb_mount.h>
diff -Nru a/fs/smbfs/proc.c b/fs/smbfs/proc.c
--- a/fs/smbfs/proc.c	Sun Nov 17 20:30:03 2002
+++ b/fs/smbfs/proc.c	Sun Nov 17 20:30:03 2002
@@ -18,6 +18,7 @@
 #include <linux/dirent.h>
 #include <linux/nls.h>
 #include <linux/smp_lock.h>
+#include <linux/net.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -514,23 +515,25 @@
  * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
  * into Unix UTC (based 1970-01-01, in seconds).
  */
-static time_t
+static struct timespec
 smb_ntutc2unixutc(u64 ntutc)
 {
+	struct timespec ts;
 	/* FIXME: what about the timezone difference? */
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
 	u64 t = ntutc - NTFS_TIME_OFFSET;
-	do_div(t, 10000000);
-	return (time_t)t;
+	ts.tv_nsec = do_div(t, 10000000) * 100;
+	ts.tv_sec = t; 
+	return ts;
 }
 
 /* Convert the Unix UTC into NT time */
 static u64
-smb_unixutc2ntutc(time_t t)
+smb_unixutc2ntutc(struct timespec ts)
 {
 	/* Note: timezone conversion is probably wrong. */
 	/* return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET; */
-	return ((u64)t) * 10000000 + NTFS_TIME_OFFSET;
+	return ((u64)ts.tv_sec) * 10000000 + ts.tv_nsec/100 + NTFS_TIME_OFFSET;
 }
 
 #define MAX_FILE_MODE	6
@@ -1239,10 +1242,14 @@
 		 * two seconds ... round the times to avoid needless
 		 * cache invalidations!
 		 */
-		if (ino->i_mtime & 1)
-			ino->i_mtime--;
-		if (ino->i_atime & 1)
-			ino->i_atime--;
+		if (ino->i_mtime.tv_sec & 1) { 
+			ino->i_mtime.tv_sec--;
+			ino->i_mtime.tv_nsec = 0; 
+		}
+		if (ino->i_atime.tv_sec & 1) {
+			ino->i_atime.tv_sec--;
+			ino->i_atime.tv_nsec = 0;
+		}
 		/*
 		 * If the file is open with write permissions,
 		 * update the time stamps to sync mtime and atime.
@@ -1256,7 +1263,7 @@
 			smb_proc_setattr_ext(server, ino, &fattr);
 		}
 
-		result = smb_proc_close(server, ei->fileid, ino->i_mtime);
+		result = smb_proc_close(server, ei->fileid, ino->i_mtime.tv_sec);
 		/*
 		 * Force a revalidation after closing ... some servers
 		 * don't post the size until the file has been closed.
@@ -1290,7 +1297,7 @@
 	struct smb_sb_info *server = server_from_dentry(dentry);
 	int result;
 
-	result = smb_proc_close(server, fileid, CURRENT_TIME);
+	result = smb_proc_close(server, fileid, get_seconds());
 	return result;
 }
 
@@ -1875,7 +1882,8 @@
 
 	p += SMB_STATUS_SIZE;	/* reserved (search_status) */
 	fattr->attr = *p;
-	fattr->f_mtime = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
+	fattr->f_mtime.tv_sec = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
+	fattr->f_mtime.tv_nsec = 0;
 	fattr->f_size = DVAL(p, 5);
 	fattr->f_ctime = fattr->f_mtime;
 	fattr->f_atime = fattr->f_mtime;
@@ -2136,15 +2144,18 @@
 
 		date = WVAL(p, 0);
 		time = WVAL(p, 2);
-		fattr->f_ctime = date_dos2unix(server, date, time);
+		fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
+		fattr->f_ctime.tv_nsec = 0;
 
 		date = WVAL(p, 4);
 		time = WVAL(p, 6);
-		fattr->f_atime = date_dos2unix(server, date, time);
+		fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
+		fattr->f_atime.tv_nsec = 0;
 
 		date = WVAL(p, 8);
 		time = WVAL(p, 10);
-		fattr->f_mtime = date_dos2unix(server, date, time);
+		fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
+		fattr->f_mtime.tv_nsec = 0;
 		fattr->f_size = DVAL(p, 12);
 		/* ULONG allocation size */
 		fattr->attr = WVAL(p, 20);
@@ -2535,15 +2546,18 @@
 	 */
 	date = WVAL(req->rq_data, 0);
 	time = WVAL(req->rq_data, 2);
-	fattr->f_ctime = date_dos2unix(server, date, time);
+	fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
+	fattr->f_ctime.tv_nsec = 0;
 
 	date = WVAL(req->rq_data, 4);
 	time = WVAL(req->rq_data, 6);
-	fattr->f_atime = date_dos2unix(server, date, time);
+	fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
+	fattr->f_atime.tv_nsec = 0;
 
 	date = WVAL(req->rq_data, 8);
 	time = WVAL(req->rq_data, 10);
-	fattr->f_mtime = date_dos2unix(server, date, time);
+	fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
+	fattr->f_mtime.tv_nsec = 0;
 	VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
 		mask, date, time, fattr->f_mtime);
 	fattr->f_size = DVAL(req->rq_data, 12);
@@ -2578,7 +2592,8 @@
 	if ((result = smb_request_ok(req, SMBgetatr, 10, 0)) < 0)
 		goto out_free;
 	fattr->attr    = WVAL(req->rq_header, smb_vwv0);
-	fattr->f_mtime = local2utc(server, DVAL(req->rq_header, smb_vwv1));
+	fattr->f_mtime.tv_sec = local2utc(server, DVAL(req->rq_header, smb_vwv1));
+	fattr->f_mtime.tv_nsec = 0;
 	fattr->f_size  = DVAL(req->rq_header, smb_vwv3);
 	fattr->f_ctime = fattr->f_mtime; 
 	fattr->f_atime = fattr->f_mtime; 
@@ -2667,15 +2682,18 @@
 	}
 	date = WVAL(req->rq_data, off_date);
 	time = WVAL(req->rq_data, off_time);
-	attr->f_ctime = date_dos2unix(server, date, time);
+	attr->f_ctime.tv_sec = date_dos2unix(server, date, time);
+	attr->f_ctime.tv_nsec = 0;
 
 	date = WVAL(req->rq_data, 4 + off_date);
 	time = WVAL(req->rq_data, 4 + off_time);
-	attr->f_atime = date_dos2unix(server, date, time);
+	attr->f_atime.tv_sec = date_dos2unix(server, date, time);
+	attr->f_atime.tv_nsec = 0;
 
 	date = WVAL(req->rq_data, 8 + off_date);
 	time = WVAL(req->rq_data, 8 + off_time);
-	attr->f_mtime = date_dos2unix(server, date, time);
+	attr->f_mtime.tv_sec = date_dos2unix(server, date, time);
+	attr->f_mtime.tv_nsec = 0;
 #ifdef SMBFS_DEBUG_TIMESTAMP
 	printk(KERN_DEBUG "getattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n",
 	       DENTRY_PATH(dir), date, time, attr->f_mtime);
@@ -2877,10 +2895,10 @@
 	/* We don't change the creation time */
 	WSET(req->rq_header, smb_vwv1, 0);
 	WSET(req->rq_header, smb_vwv2, 0);
-	date_unix2dos(server, fattr->f_atime, &date, &time);
+	date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
 	WSET(req->rq_header, smb_vwv3, date);
 	WSET(req->rq_header, smb_vwv4, time);
-	date_unix2dos(server, fattr->f_mtime, &date, &time);
+	date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
 	WSET(req->rq_header, smb_vwv5, date);
 	WSET(req->rq_header, smb_vwv6, time);
 #ifdef SMBFS_DEBUG_TIMESTAMP
@@ -2928,10 +2946,10 @@
 
 	WSET(data, 0, 0); /* creation time */
 	WSET(data, 2, 0);
-	date_unix2dos(server, fattr->f_atime, &date, &time);
+	date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
 	WSET(data, 4, date);
 	WSET(data, 6, time);
-	date_unix2dos(server, fattr->f_mtime, &date, &time);
+	date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
 	WSET(data, 8, date);
 	WSET(data, 10, time);
 #ifdef SMBFS_DEBUG_TIMESTAMP
diff -Nru a/fs/smbfs/request.c b/fs/smbfs/request.c
--- a/fs/smbfs/request.c	Sun Nov 17 20:30:16 2002
+++ b/fs/smbfs/request.c	Sun Nov 17 20:30:16 2002
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/net.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
diff -Nru a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
--- a/fs/smbfs/smbiod.c	Sun Nov 17 20:30:14 2002
+++ b/fs/smbfs/smbiod.c	Sun Nov 17 20:30:14 2002
@@ -19,6 +19,7 @@
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
+#include <linux/net.h>
 #include <net/ip.h>
 
 #include <linux/smb_fs.h>
diff -Nru a/fs/smbfs/sock.c b/fs/smbfs/sock.c
--- a/fs/smbfs/sock.c	Sun Nov 17 20:30:12 2002
+++ b/fs/smbfs/sock.c	Sun Nov 17 20:30:12 2002
@@ -20,6 +20,7 @@
 #include <linux/netdevice.h>
 #include <linux/smp_lock.h>
 #include <linux/workqueue.h>
+#include <linux/net.h>
 #include <net/scm.h>
 #include <net/ip.h>
 
diff -Nru a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c
--- a/fs/smbfs/symlink.c	Sun Nov 17 20:30:15 2002
+++ b/fs/smbfs/symlink.c	Sun Nov 17 20:30:15 2002
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/net.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c	Sun Nov 17 20:30:04 2002
+++ b/fs/stat.c	Sun Nov 17 20:30:04 2002
@@ -128,9 +128,9 @@
 		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_atime = stat->atime.tv_sec;
+	tmp.st_mtime = stat->mtime.tv_sec;
+	tmp.st_ctime = stat->ctime.tv_sec;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -184,9 +184,14 @@
 		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_atime = stat->atime.tv_sec;
+	tmp.st_mtime = stat->mtime.tv_sec;
+	tmp.st_ctime = stat->ctime.tv_sec;
+#ifdef STAT_HAVE_NSEC
+	tmp.st_atime_nsec = stat->atime.tv_nsec;
+	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+#endif
 	tmp.st_blocks = stat->blocks;
 	tmp.st_blksize = stat->blksize;
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
@@ -256,7 +261,7 @@
 {
 	struct stat64 tmp;
 
-	memset(&tmp, 0, sizeof(tmp));
+	memset(&tmp, 0, sizeof(struct stat64));
 	tmp.st_dev = stat->dev;
 	tmp.st_ino = stat->ino;
 #ifdef STAT64_HAS_BROKEN_ST_INO
@@ -267,9 +272,12 @@
 	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_atime = stat->atime.tv_sec;
+	tmp.st_atime_nsec = stat->atime.tv_nsec;
+	tmp.st_mtime = stat->mtime.tv_sec;
+	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+	tmp.st_ctime = stat->ctime.tv_sec;
+	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
 	tmp.st_size = stat->size;
 	tmp.st_blocks = stat->blocks;
 	tmp.st_blksize = stat->blksize;
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Sun Nov 17 20:30:13 2002
+++ b/fs/super.c	Sun Nov 17 20:30:13 2002
@@ -28,6 +28,7 @@
 #include <linux/quotaops.h>
 #include <linux/namei.h>
 #include <linux/buffer_head.h>		/* for fsync_super() */
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 #include <linux/security.h>
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- a/fs/sysfs/inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/sysfs/inode.c	Sun Nov 17 20:30:15 2002
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/backing-dev.h>
 #include <linux/kobject.h>
-
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 /* Random magic number */
diff -Nru a/fs/sysv/balloc.c b/fs/sysv/balloc.c
--- a/fs/sysv/balloc.c	Sun Nov 17 20:30:13 2002
+++ b/fs/sysv/balloc.c	Sun Nov 17 20:30:13 2002
@@ -20,6 +20,7 @@
  */
 
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 #include "sysv.h"
 
 /* We don't trust the value of
diff -Nru a/fs/sysv/inode.c b/fs/sysv/inode.c
--- a/fs/sysv/inode.c	Sun Nov 17 20:30:02 2002
+++ b/fs/sysv/inode.c	Sun Nov 17 20:30:02 2002
@@ -33,7 +33,7 @@
 static void sysv_write_super(struct super_block *sb)
 {
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
-	unsigned long time = CURRENT_TIME, old_time;
+	unsigned long time = get_seconds(), old_time;
 
 	lock_kernel();
 	if (sb->s_flags & MS_RDONLY)
@@ -184,9 +184,12 @@
 	inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid);
 	inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink);
 	inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
-	inode->i_atime = fs32_to_cpu(sbi, raw_inode->i_atime);
-	inode->i_mtime = fs32_to_cpu(sbi, raw_inode->i_mtime);
-	inode->i_ctime = fs32_to_cpu(sbi, raw_inode->i_ctime);
+	inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime);
+	inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime);
+	inode->i_ctime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_ctime);
+	inode->i_ctime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_mtime.tv_nsec = 0;
 	inode->i_blocks = inode->i_blksize = 0;
 
 	si = SYSV_I(inode);
@@ -231,9 +234,9 @@
 	raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid));
 	raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink);
 	raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size);
-	raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime);
-	raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime);
-	raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime);
+	raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime.tv_sec);
+	raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime.tv_sec);
+	raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime.tv_sec);
 
 	si = SYSV_I(inode);
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
diff -Nru a/fs/sysv/itree.c b/fs/sysv/itree.c
--- a/fs/sysv/itree.c	Sun Nov 17 20:30:12 2002
+++ b/fs/sysv/itree.c	Sun Nov 17 20:30:12 2002
@@ -6,6 +6,8 @@
  */
 
 #include <linux/buffer_head.h>
+#include <linux/mount.h>
+#include <linux/string.h>
 #include "sysv.h"
 
 enum {DIRECT = 10, DEPTH = 4};	/* Have triple indirect */
diff -Nru a/fs/udf/balloc.c b/fs/udf/balloc.c
--- a/fs/udf/balloc.c	Sun Nov 17 20:30:12 2002
+++ b/fs/udf/balloc.c	Sun Nov 17 20:30:12 2002
@@ -461,8 +461,7 @@
 	elen = 0;
 	obloc = nbloc = UDF_I_LOCATION(table);
 
-	obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0));
-	atomic_inc(&nbh->b_count);
+	obh = nbh = NULL;
 
 	while (count && (etype =
 		udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
@@ -506,7 +505,7 @@
 			udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
 		}
 
-		if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+		if (nbh != obh)
 		{
 			i = -1;
 			obloc = nbloc;
@@ -580,7 +579,10 @@
 			{
 				loffset = nextoffset;
 				aed->lengthAllocDescs = cpu_to_le32(adsize);
-				sptr = (obh)->b_data + nextoffset - adsize;
+				if (obh)
+					sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
+				else
+					sptr = obh->b_data + nextoffset - adsize;
 				dptr = nbh->b_data + sizeof(struct allocExtDesc);
 				memcpy(dptr, sptr, adsize);
 				nextoffset = sizeof(struct allocExtDesc) + adsize;
@@ -591,8 +593,8 @@
 				aed->lengthAllocDescs = cpu_to_le32(0);
 				sptr = (obh)->b_data + nextoffset;
 				nextoffset = sizeof(struct allocExtDesc);
-	
-				if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
+
+				if (obh)
 				{
 					aed = (struct allocExtDesc *)(obh)->b_data;
 					aed->lengthAllocDescs =
@@ -631,15 +633,20 @@
 					break;
 				}
 			}
-			udf_update_tag(obh->b_data, loffset);
-			mark_buffer_dirty(obh);
+			if (obh)
+			{
+				udf_update_tag(obh->b_data, loffset);
+				mark_buffer_dirty(obh);
+			}
+			else
+				mark_inode_dirty(table);
 		}
 
 		if (elen) /* It's possible that stealing the block emptied the extent */
 		{
 			udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
 
-			if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
+			if (!nbh)
 			{
 				UDF_I_LENALLOC(table) += adsize;
 				mark_inode_dirty(table);
@@ -690,7 +697,7 @@
 	extoffset = sizeof(struct unallocSpaceEntry);
 	bloc = UDF_I_LOCATION(table);
 
-	bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
+	bh = NULL;
 	eloc.logicalBlockNum = 0xFFFFFFFF;
 
 	while (first_block != eloc.logicalBlockNum && (etype =
@@ -768,8 +775,7 @@
 	extoffset = sizeof(struct unallocSpaceEntry);
 	bloc = UDF_I_LOCATION(table);
 
-	goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
-	atomic_inc(&goal_bh->b_count);
+	goal_bh = bh = NULL;
 
 	while (spread && (etype =
 		udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
diff -Nru a/fs/udf/dir.c b/fs/udf/dir.c
--- a/fs/udf/dir.c	Sun Nov 17 20:30:12 2002
+++ b/fs/udf/dir.c	Sun Nov 17 20:30:12 2002
@@ -89,13 +89,14 @@
 
 	if ( filp->f_pos == 0 ) 
 	{
-		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
+		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
+		{
 			unlock_kernel();
 			return 0;
 		}
 		filp->f_pos ++;
 	}
- 
+
 	result = do_udf_readdir(dir, filp, filldir, dirent);
 	UPDATE_ATIME(dir);
 	unlock_kernel();
@@ -129,7 +130,9 @@
 		nf_pos = (udf_ext0_offset(dir) >> 2);
 
 	fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-	if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+		fibh.sbh = fibh.ebh = NULL;
+	else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
 		offset >>= dir->i_sb->s_blocksize_bits;
@@ -143,39 +146,39 @@
 		}
 		else
 			offset = 0;
-	}
-	else
-	{
-		udf_release_data(bh);
-		return -ENOENT;
-	}
-
-	if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-	{
-		udf_release_data(bh);
-		return -EIO;
-	}
 
-	if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
-	{
-		i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
-		if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
-			i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
-		for (num=0; i>0; i--)
+		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		{
-			block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
-			tmp = udf_tgetblk(dir->i_sb, block);
-			if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
-				bha[num++] = tmp;
-			else
-				brelse(tmp);
+			udf_release_data(bh);
+			return -EIO;
 		}
-		if (num)
+	
+		if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
 		{
-			ll_rw_block(READA, num, bha);
-			for (i=0; i<num; i++)
-				brelse(bha[i]);
+			i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
+			if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
+				i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
+			for (num=0; i>0; i--)
+			{
+				block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
+				tmp = udf_tgetblk(dir->i_sb, block);
+				if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
+					bha[num++] = tmp;
+				else
+					brelse(tmp);
+			}
+			if (num)
+			{
+				ll_rw_block(READA, num, bha);
+				for (i=0; i<num; i++)
+					brelse(bha[i]);
+			}
 		}
+	}
+	else
+	{
+		udf_release_data(bh);
+		return -ENOENT;
 	}
 
 	while ( nf_pos < size )
diff -Nru a/fs/udf/directory.c b/fs/udf/directory.c
--- a/fs/udf/directory.c	Sun Nov 17 20:30:15 2002
+++ b/fs/udf/directory.c	Sun Nov 17 20:30:15 2002
@@ -17,6 +17,7 @@
  */
 
 #include "udfdecl.h"
+#include "udf_i.h"
 
 #include <linux/fs.h>
 #include <linux/string.h>
@@ -85,6 +86,24 @@
 
 	fibh->soffset = fibh->eoffset;
 
+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+	{
+		fi = udf_get_fileident(UDF_I_DATA(dir) -
+			(UDF_I_EFE(dir) ?
+				sizeof(struct extendedFileEntry) :
+				sizeof(struct fileEntry)),
+			dir->i_sb->s_blocksize, &(fibh->eoffset));
+
+		if (!fi)
+			return NULL;
+
+		*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
+
+		memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
+
+		return fi;
+	}
+
 	if (fibh->eoffset == dir->i_sb->s_blocksize)
 	{
 		int lextoffset = *extoffset;
@@ -276,53 +295,43 @@
 }
 
 short_ad *
-udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
+udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
 {
-	short_ad * sa;
-	uint8_t * ptr;
+	short_ad *sa;
 
-	if ( (!buffer) || (!offset) )
+	if ( (!ptr) || (!offset) )
 	{
 		printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
 		return NULL;
 	}
 
-	ptr = (uint8_t *)buffer;
-
-	if ( (*offset > 0) && (*offset < maxoffset) )
-		ptr += *offset;
-	else
+	if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
 		return NULL;
-
-	if ((sa = (short_ad *)ptr)->extLength == 0)
+	else if ((sa = (short_ad *)ptr)->extLength == 0)
 		return NULL;
-	else if (inc)
-		(*offset) += sizeof(short_ad);
+
+	if (inc)
+		*offset += sizeof(short_ad);
 	return sa;
 }
 
 long_ad *
-udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
+udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
 {
-	long_ad * la;
-	uint8_t * ptr;
+	long_ad *la;
 
-	if ( (!buffer) || !(offset) ) 
+	if ( (!ptr) || (!offset) ) 
 	{
 		printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
 		return NULL;
 	}
 
-	ptr = (uint8_t *)buffer;
-
-	if ( (*offset > 0) && (*offset < maxoffset) )
-		ptr += *offset;
-	else
+	if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
 		return NULL;
-
-	if ((la = (long_ad *)ptr)->extLength == 0)
+	else if ((la = (long_ad *)ptr)->extLength == 0)
 		return NULL;
-	else if (inc)
-		(*offset) += sizeof(long_ad);
+
+	if (inc)
+		*offset += sizeof(long_ad);
 	return la;
 }
diff -Nru a/fs/udf/file.c b/fs/udf/file.c
--- a/fs/udf/file.c	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/file.c	Sun Nov 17 20:30:14 2002
@@ -47,64 +47,36 @@
 static int udf_adinicb_readpage(struct file *file, struct page * page)
 {
 	struct inode *inode = page->mapping->host;
-
-	struct buffer_head *bh;
-	int block;
 	char *kaddr;
-	int err = 0;
 
 	if (!PageLocked(page))
 		PAGE_BUG(page);
 
 	kaddr = kmap(page);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = sb_bread(inode->i_sb, block);
-	if (!bh)
-	{
-		SetPageError(page);
-		err = -EIO;
-		goto out;
-	}
-	memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
-	brelse(bh);
+	memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
 	flush_dcache_page(page);
 	SetPageUptodate(page);
-out:
 	kunmap(page);
 	unlock_page(page);
-	return err;
+	return 0;
 }
 
 static int udf_adinicb_writepage(struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-
-	struct buffer_head *bh;
-	int block;
 	char *kaddr;
-	int err = 0;
 
 	if (!PageLocked(page))
 		PAGE_BUG(page);
 
 	kaddr = kmap(page);
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = sb_bread(inode->i_sb, block);
-	if (!bh)
-	{
-		SetPageError(page);
-		err = -EIO;
-		goto out;
-	}
-	memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
-	mark_buffer_dirty(bh);
-	brelse(bh);
+	memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
+	mark_inode_dirty(inode);
 	SetPageUptodate(page);
-out:
 	kunmap(page);
 	unlock_page(page);
-	return err;
+	return 0;
 }
 
 static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
@@ -116,31 +88,17 @@
 static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
 	struct inode *inode = page->mapping->host;
-
-	struct buffer_head *bh;
-	int block;
 	char *kaddr = page_address(page);
-	int err = 0;
 
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = sb_bread(inode->i_sb, block);
-	if (!bh)
-	{
-		SetPageError(page);
-		err = -EIO;
-		goto out;
-	}
-	memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
+	memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
 		kaddr + offset, to - offset);
-	mark_buffer_dirty(bh);
-	brelse(bh);
+	mark_inode_dirty(inode);
 	SetPageUptodate(page);
-out:
 	kunmap(page);
 	/* only one page here */
 	if (to > inode->i_size)
 		inode->i_size = to;
-	return err;
+	return 0;
 }
 
 struct address_space_operations udf_adinicb_aops = {
@@ -232,9 +190,6 @@
 	unsigned long arg)
 {
 	int result = -EINVAL;
-	struct buffer_head *bh = NULL;
-	long_ad eaicb;
-	uint8_t *ea = NULL;
 
 	if ( permission(inode, MAY_READ) != 0 )
 	{
@@ -249,7 +204,6 @@
 		return -EINVAL;
 	}
 
-	/* first, do ioctls that don't need to udf_read */
 	switch (cmd)
 	{
 		case UDF_GETVOLIDENT:
@@ -267,50 +221,16 @@
 
 			return result;
 		}
-	}
-
-	/* ok, we need to read the inode */
-	bh = udf_tread(inode->i_sb,
-		udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
-
-	if (!bh)
-	{
-		udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
-		return -EIO;
-	}
-
-	if (UDF_I_EXTENDED_FE(inode) == 0)
-	{
-		struct fileEntry *fe;
-
-		fe = (struct fileEntry *)bh->b_data;
-		eaicb = lela_to_cpu(fe->extendedAttrICB);
-		if (UDF_I_LENEATTR(inode))
-			ea = fe->extendedAttr;
-	}
-	else
-	{
-		struct extendedFileEntry *efe;
-
-		efe = (struct extendedFileEntry *)bh->b_data;
-		eaicb = lela_to_cpu(efe->extendedAttrICB);
-		if (UDF_I_LENEATTR(inode))
-			ea = efe->extendedAttr;
-	}
-
-	switch (cmd) 
-	{
 		case UDF_GETEASIZE:
 			result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
 			break;
 
 		case UDF_GETEABLOCK:
-			result = copy_to_user((char *)arg, ea,
+			result = copy_to_user((char *)arg, UDF_I_DATA(inode),
 				UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
 			break;
 	}
 
-	udf_release_data(bh);
 	return result;
 }
 
diff -Nru a/fs/udf/ialloc.c b/fs/udf/ialloc.c
--- a/fs/udf/ialloc.c	Sun Nov 17 20:30:13 2002
+++ b/fs/udf/ialloc.c	Sun Nov 17 20:30:13 2002
@@ -28,6 +28,7 @@
 #include <linux/quotaops.h>
 #include <linux/udf_fs.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -135,24 +136,30 @@
 	inode->i_blocks = 0;
 	UDF_I_LENEATTR(inode) = 0;
 	UDF_I_LENALLOC(inode) = 0;
+	UDF_I_USE(inode) = 0;
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
 	{
-		UDF_I_EXTENDED_FE(inode) = 1;
+		UDF_I_EFE(inode) = 1;
 		UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+		memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
 	}
 	else
-		UDF_I_EXTENDED_FE(inode) = 0;
+	{
+		UDF_I_EFE(inode) = 0;
+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+		memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+	}
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
 	else
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
-	inode->i_mtime = inode->i_atime = inode->i_ctime =
-		UDF_I_CRTIME(inode) = CURRENT_TIME;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		UDF_I_CRTIME(inode) = get_seconds();
 	UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
-		UDF_I_UCRTIME(inode) = CURRENT_UTIME;
-	UDF_I_NEW_INODE(inode) = 1;
+		UDF_I_UCRTIME(inode) = get_seconds();
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 
diff -Nru a/fs/udf/inode.c b/fs/udf/inode.c
--- a/fs/udf/inode.c	Sun Nov 17 20:30:16 2002
+++ b/fs/udf/inode.c	Sun Nov 17 20:30:16 2002
@@ -39,6 +39,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/slab.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -122,6 +123,11 @@
 	clear_inode(inode);
 }
 
+void udf_clear_inode(struct inode *inode)
+{
+	kfree(UDF_I_DATA(inode));
+}
+
 void udf_discard_prealloc(struct inode * inode)
 {
 	if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
@@ -162,10 +168,8 @@
 
 void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 {
-	struct buffer_head *bh = NULL;
 	struct page *page;
 	char *kaddr;
-	int block;
 
 	/* from now on we have normal address_space methods */
 	inode->i_data.a_ops = &udf_aops;
@@ -180,10 +184,6 @@
 		return;
 	}
 
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = udf_tread(inode->i_sb, block);
-	if (!bh)
-		return;
 	page = grab_cache_page(inode->i_mapping, 0);
 	if (!PageLocked(page))
 		PAGE_BUG(page);
@@ -192,21 +192,19 @@
 		kaddr = kmap(page);
 		memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
 			PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
-		memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
+		memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
 			UDF_I_LENALLOC(inode));
 		flush_dcache_page(page);
 		SetPageUptodate(page);
 		kunmap(page);
 	}
-	memset(bh->b_data + udf_file_entry_alloc_offset(inode),
-		0, UDF_I_LENALLOC(inode));
+	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
+		UDF_I_LENALLOC(inode));
 	UDF_I_LENALLOC(inode) = 0;
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
 	else
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
-	mark_buffer_dirty_inode(bh, inode);
-	udf_release_data(bh);
 
 	if (inode->i_data.a_ops->writepage(page) == -EAGAIN)
 		__set_page_dirty_nobuffers(page);
@@ -221,18 +219,21 @@
 	struct buffer_head *sbh = NULL, *dbh = NULL;
 	lb_addr bloc, eloc;
 	uint32_t elen, extoffset;
+	uint8_t alloctype;
 
 	struct udf_fileident_bh sfibh, dfibh;
 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
 	int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
 	struct fileIdentDesc cfi, *sfi, *dfi;
 
+	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+		alloctype = ICBTAG_FLAG_AD_SHORT;
+	else
+		alloctype = ICBTAG_FLAG_AD_LONG;
+
 	if (!inode->i_size)
 	{
-		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
-		else
-			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
+		UDF_I_ALLOCTYPE(inode) = alloctype;
 		mark_inode_dirty(inode);
 		return NULL;
 	}
@@ -248,9 +249,6 @@
 		UDF_I_LOCATION(inode).partitionReferenceNum, 0);
 	if (!newblock)
 		return NULL;
-	sbh = udf_tread(inode->i_sb, inode->i_ino);
-	if (!sbh)
-		return NULL;
 	dbh = udf_tgetblk(inode->i_sb, newblock);
 	if (!dbh)
 		return NULL;
@@ -261,18 +259,19 @@
 	mark_buffer_dirty_inode(dbh, inode);
 
 	sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
-	sfibh.sbh = sfibh.ebh = sbh;
+	sbh = sfibh.sbh = sfibh.ebh = NULL;
 	dfibh.soffset = dfibh.eoffset = 0;
 	dfibh.sbh = dfibh.ebh = dbh;
 	while ( (f_pos < size) )
 	{
+		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
 		if (!sfi)
 		{
-			udf_release_data(sbh);
 			udf_release_data(dbh);
 			return NULL;
 		}
+		UDF_I_ALLOCTYPE(inode) = alloctype;
 		sfi->descTag.tagLocation = *block;
 		dfibh.soffset = dfibh.eoffset;
 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
@@ -280,21 +279,15 @@
 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
 			sfi->fileIdent + sfi->lengthOfImpUse))
 		{
-			udf_release_data(sbh);
+			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 			udf_release_data(dbh);
 			return NULL;
 		}
 	}
 	mark_buffer_dirty_inode(dbh, inode);
 
-	memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
-		0, UDF_I_LENALLOC(inode));
-
+	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
 	UDF_I_LENALLOC(inode) = 0;
-	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
-	else
-		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
 	bloc = UDF_I_LOCATION(inode);
 	eloc.logicalBlockNum = *block;
 	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
@@ -304,7 +297,6 @@
 	udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
 	/* UniqueID stuff */
 
-	mark_buffer_dirty(sbh);
 	udf_release_data(sbh);
 	mark_inode_dirty(inode);
 	return dbh;
@@ -725,7 +717,7 @@
 
 				if (elen > numalloc)
 				{
-					laarr[c].extLength -=
+					laarr[i].extLength -=
 						(numalloc << inode->i_sb->s_blocksize_bits);
 					numalloc = 0;
 				}
@@ -847,7 +839,6 @@
 void udf_truncate(struct inode * inode)
 {
 	int offset;
-	struct buffer_head *bh;
 	int err;
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -874,16 +865,8 @@
 		}
 		else
 		{
-			offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
-				udf_file_entry_alloc_offset(inode);
-
-			if ((bh = udf_tread(inode->i_sb,
-				udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0))))
-			{
-				memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
-				mark_buffer_dirty(bh);
-				udf_release_data(bh);
-			}
+			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
+			memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
 			UDF_I_LENALLOC(inode) = inode->i_size;
 		}
 	}
@@ -1031,8 +1014,6 @@
 	long convtime_usec;
 	int offset, alen;
 
-	UDF_I_NEW_INODE(inode) = 0;
-
 	fe = (struct fileEntry *)bh->b_data;
 	efe = (struct extendedFileEntry *)bh->b_data;
 
@@ -1053,14 +1034,28 @@
 	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
 	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
-		UDF_I_EXTENDED_FE(inode) = 1;
+	{
+		UDF_I_EFE(inode) = 1;
+		UDF_I_USE(inode) = 0;
+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
+	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
-		UDF_I_EXTENDED_FE(inode) = 0;
+	{
+		UDF_I_EFE(inode) = 0;
+		UDF_I_USE(inode) = 0;
+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+	}
 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
 	{
+		UDF_I_EFE(inode) = 0;
+		UDF_I_USE(inode) = 1;
 		UDF_I_LENALLOC(inode) =
 			le32_to_cpu(
 				((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
 		return;
 	}
 
@@ -1080,7 +1075,7 @@
 	inode->i_mode = udf_convert_permissions(fe);
 	inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
 
-	if (UDF_I_EXTENDED_FE(inode) == 0)
+	if (UDF_I_EFE(inode) == 0)
 	{
 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
 			(inode->i_sb->s_blocksize_bits - 9);
@@ -1088,34 +1083,40 @@
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(fe->accessTime)) )
 		{
-			inode->i_atime = convtime;
+			inode->i_atime.tv_sec = convtime;
+			inode->i_atime.tv_nsec = 0;
 		}
 		else
 		{
-			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_atime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_atime.tv_nsec = 0;
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(fe->modificationTime)) )
 		{
-			inode->i_mtime = convtime;
+			inode->i_mtime.tv_sec = convtime;
+			inode->i_mtime.tv_nsec = 0;
 			UDF_I_UMTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_mtime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_mtime.tv_nsec = 0;
 			UDF_I_UMTIME(inode) = 0;
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(fe->attrTime)) )
 		{
-			inode->i_ctime = convtime;
+			inode->i_ctime.tv_sec = convtime;
+			inode->i_ctime.tv_nsec = 0;
 			UDF_I_UCTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_ctime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_ctime.tv_nsec = 0;
 			UDF_I_UCTIME(inode) = 0;
 		}
 
@@ -1133,22 +1134,26 @@
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(efe->accessTime)) )
 		{
-			inode->i_atime = convtime;
+			inode->i_atime.tv_sec = convtime;
+			inode->i_atime.tv_nsec = 0;
 		}
 		else
 		{
-			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_atime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_atime.tv_nsec = 0;
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(efe->modificationTime)) )
 		{
-			inode->i_mtime = convtime;
+			inode->i_mtime.tv_sec = convtime;
+			inode->i_mtime.tv_nsec = 0;
 			UDF_I_UMTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_mtime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_mtime.tv_nsec = 0;
 			UDF_I_UMTIME(inode) = 0;
 		}
 
@@ -1167,12 +1172,14 @@
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(efe->attrTime)) )
 		{
-			inode->i_ctime = convtime;
+			inode->i_ctime.tv_sec = convtime;
+			inode->i_ctime.tv_nsec = 0;
 			UDF_I_UCTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_ctime.tv_sec = UDF_SB_RECORDTIME(inode->i_sb);
+			inode->i_ctime.tv_nsec = 0;
 			UDF_I_UCTIME(inode) = 0;
 		}
 
@@ -1326,19 +1333,11 @@
 		udf_debug("bread failure\n");
 		return -EIO;
 	}
+
+	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
+
 	fe = (struct fileEntry *)bh->b_data;
 	efe = (struct extendedFileEntry *)bh->b_data;
-	if (UDF_I_NEW_INODE(inode) == 1)
-	{
-		if (UDF_I_EXTENDED_FE(inode) == 0)
-			memset(bh->b_data, 0x00, sizeof(struct fileEntry));
-		else
-			memset(bh->b_data, 0x00, sizeof(struct extendedFileEntry));
-		memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
-			UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
-			udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
-		UDF_I_NEW_INODE(inode) = 0;
-	}
 
 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
 	{
@@ -1346,6 +1345,7 @@
 			(struct unallocSpaceEntry *)bh->b_data;
 
 		use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
+		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
 		crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
 			sizeof(tag);
 		use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
@@ -1416,17 +1416,18 @@
 		udf_release_data(tbh);
 	}
 
-	if (UDF_I_EXTENDED_FE(inode) == 0)
+	if (UDF_I_EFE(inode) == 0)
 	{
+		memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
 		fe->logicalBlocksRecorded = cpu_to_le64(
 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
 			(inode->i_sb->s_blocksize_bits - 9));
 
-		if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
+		if (udf_time_to_stamp(&cpu_time, inode->i_atime.tv_sec, 0))
 			fe->accessTime = cpu_to_lets(cpu_time);
-		if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
+		if (udf_time_to_stamp(&cpu_time, inode->i_mtime.tv_sec, UDF_I_UMTIME(inode)))
 			fe->modificationTime = cpu_to_lets(cpu_time);
-		if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
+		if (udf_time_to_stamp(&cpu_time, inode->i_ctime.tv_sec, UDF_I_UCTIME(inode)))
 			fe->attrTime = cpu_to_lets(cpu_time);
 		memset(&(fe->impIdent), 0, sizeof(regid));
 		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
@@ -1440,38 +1441,39 @@
 	}
 	else
 	{
+		memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
 		efe->objectSize = cpu_to_le64(inode->i_size);
 		efe->logicalBlocksRecorded = cpu_to_le64(
 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
 			(inode->i_sb->s_blocksize_bits - 9));
 
-		if (UDF_I_CRTIME(inode) >= inode->i_atime)
+		if (UDF_I_CRTIME(inode) >= inode->i_atime.tv_sec)
 		{
-			UDF_I_CRTIME(inode) = inode->i_atime;
+			UDF_I_CRTIME(inode) = inode->i_atime.tv_sec;
 			UDF_I_UCRTIME(inode) = 0;
 		}
-		if (UDF_I_CRTIME(inode) > inode->i_mtime ||
-			(UDF_I_CRTIME(inode) == inode->i_mtime &&
+		if (UDF_I_CRTIME(inode) > inode->i_mtime.tv_sec ||
+			(UDF_I_CRTIME(inode) == inode->i_mtime.tv_sec &&
 			 UDF_I_UCRTIME(inode) > UDF_I_UMTIME(inode)))
 		{
-			UDF_I_CRTIME(inode) = inode->i_mtime;
+			UDF_I_CRTIME(inode) = inode->i_mtime.tv_sec;
 			UDF_I_UCRTIME(inode) = UDF_I_UMTIME(inode);
 		}
-		if (UDF_I_CRTIME(inode) > inode->i_ctime ||
-			(UDF_I_CRTIME(inode) == inode->i_ctime &&
+		if (UDF_I_CRTIME(inode) > inode->i_ctime.tv_sec ||
+			(UDF_I_CRTIME(inode) == inode->i_ctime.tv_sec &&
 			 UDF_I_UCRTIME(inode) > UDF_I_UCTIME(inode)))
 		{
-			UDF_I_CRTIME(inode) = inode->i_ctime;
+			UDF_I_CRTIME(inode) = inode->i_ctime.tv_sec;
 			UDF_I_UCRTIME(inode) = UDF_I_UCTIME(inode);
 		}
 
-		if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
+		if (udf_time_to_stamp(&cpu_time, inode->i_atime.tv_sec, 0))
 			efe->accessTime = cpu_to_lets(cpu_time);
-		if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
+		if (udf_time_to_stamp(&cpu_time, inode->i_mtime.tv_sec, UDF_I_UMTIME(inode)))
 			efe->modificationTime = cpu_to_lets(cpu_time);
 		if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode), UDF_I_UCRTIME(inode)))
 			efe->createTime = cpu_to_lets(cpu_time);
-		if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
+		if (udf_time_to_stamp(&cpu_time, inode->i_ctime.tv_sec, UDF_I_UCTIME(inode)))
 			efe->attrTime = cpu_to_lets(cpu_time);
 
 		memset(&(efe->impIdent), 0, sizeof(regid));
@@ -1620,17 +1622,12 @@
 	long_ad *lad = NULL;
 	struct allocExtDesc *aed;
 	int8_t etype;
+	uint8_t *ptr;
 
-	if (!(*bh))
-	{
-		if (!(*bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
-		{
-			udf_debug("reading block %d failed!\n",
-				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
-			return -1;
-		}
-	}
+	if (!*bh)
+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+	else
+		ptr = (*bh)->b_data + *extoffset;
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(short_ad);
@@ -1669,7 +1666,7 @@
 		{
 			loffset = *extoffset;
 			aed->lengthAllocDescs = cpu_to_le32(adsize);
-			sptr = (*bh)->b_data + *extoffset - adsize;
+			sptr = ptr - adsize;
 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
 			memcpy(dptr, sptr, adsize);
 			*extoffset = sizeof(struct allocExtDesc) + adsize;
@@ -1678,10 +1675,10 @@
 		{
 			loffset = *extoffset + adsize;
 			aed->lengthAllocDescs = cpu_to_le32(0);
-			sptr = (*bh)->b_data + *extoffset;
+			sptr = ptr;
 			*extoffset = sizeof(struct allocExtDesc);
 
-			if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+			if (*bh)
 			{
 				aed = (struct allocExtDesc *)(*bh)->b_data;
 				aed->lengthAllocDescs =
@@ -1721,18 +1718,23 @@
 				break;
 			}
 		}
-		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-			udf_update_tag((*bh)->b_data, loffset);
+		if (*bh)
+		{
+			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
+				udf_update_tag((*bh)->b_data, loffset);
+			else
+				udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
+			mark_buffer_dirty_inode(*bh, inode);
+			udf_release_data(*bh);
+		}
 		else
-			udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-		mark_buffer_dirty_inode(*bh, inode);
-		udf_release_data(*bh);
+			mark_inode_dirty(inode);
 		*bh = nbh;
 	}
 
 	etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
 
-	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+	if (!*bh)
 	{
 		UDF_I_LENALLOC(inode) += adsize;
 		mark_inode_dirty(inode);
@@ -1756,49 +1758,40 @@
     lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
 {
 	int adsize;
-	short_ad *sad = NULL;
-	long_ad *lad = NULL;
+	uint8_t *ptr;
 
-	if (!(bh))
-	{
-		if (!(bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, bloc, 0))))
-		{
-			udf_debug("reading block %d failed!\n",
-				udf_get_lb_pblock(inode->i_sb, bloc, 0));
-			return -1;
-		}
-	}
+	if (!bh)
+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
 	else
+	{
+		ptr = bh->b_data + *extoffset;
 		atomic_inc(&bh->b_count);
-
-	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-		adsize = sizeof(short_ad);
-	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-		adsize = sizeof(long_ad);
-	else
-		return -1;
+	}
 
 	switch (UDF_I_ALLOCTYPE(inode))
 	{
 		case ICBTAG_FLAG_AD_SHORT:
 		{
-			sad = (short_ad *)((bh)->b_data + *extoffset);
+			short_ad *sad = (short_ad *)ptr;
 			sad->extLength = cpu_to_le32(elen);
 			sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
+			adsize = sizeof(short_ad);
 			break;
 		}
 		case ICBTAG_FLAG_AD_LONG:
 		{
-			lad = (long_ad *)((bh)->b_data + *extoffset);
+			long_ad *lad = (long_ad *)ptr;
 			lad->extLength = cpu_to_le32(elen);
 			lad->extLocation = cpu_to_lelb(eloc);
 			memset(lad->impUse, 0x00, sizeof(lad->impUse));
+			adsize = sizeof(long_ad);
 			break;
 		}
+		default:
+			return -1;
 	}
 
-	if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+	if (bh)
 	{
 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
 		{
@@ -1807,30 +1800,28 @@
 				le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
 		}
 		mark_buffer_dirty_inode(bh, inode);
+		udf_release_data(bh);
 	}
 	else
-	{
 		mark_inode_dirty(inode);
-		mark_buffer_dirty(bh);
-	}
 
 	if (inc)
 		*extoffset += adsize;
-	udf_release_data(bh);
 	return (elen >> 30);
 }
 
 int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
-	uint16_t tagIdent;
-	int pos, alen;
 	int8_t etype;
 
-	if (!(*bh))
+	while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
+		(EXT_NEXT_EXTENT_ALLOCDECS >> 30))
 	{
-		if (!(*bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
+		*bloc = *eloc;
+		*extoffset = sizeof(struct allocExtDesc);
+		udf_release_data(*bh);
+		if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
 		{
 			udf_debug("reading block %d failed!\n",
 				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
@@ -1838,154 +1829,38 @@
 		}
 	}
 
-	tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent);
-
-	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
-	{
-		if (tagIdent == TAG_IDENT_FE || tagIdent == TAG_IDENT_EFE ||
-			UDF_I_NEW_INODE(inode))
-		{
-			pos = udf_file_entry_alloc_offset(inode);
-			alen = UDF_I_LENALLOC(inode) + pos;
-		}
-		else if (tagIdent == TAG_IDENT_USE)
-		{
-			pos = sizeof(struct unallocSpaceEntry);
-			alen = UDF_I_LENALLOC(inode) + pos;
-		}
-		else
-			return -1;
-	}
-	else if (tagIdent == TAG_IDENT_AED)
-	{
-		struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
-		pos = sizeof(struct allocExtDesc);
-		alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
-	}
-	else
-		return -1;
-
-	if (!(*extoffset))
-		*extoffset = pos;
-
-	switch (UDF_I_ALLOCTYPE(inode))
-	{
-		case ICBTAG_FLAG_AD_SHORT:
-		{
-			short_ad *sad;
-
-			if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
-				return -1;
-
-			if ((etype = le32_to_cpu(sad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
-			{
-				bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
-				*extoffset = 0;
-				udf_release_data(*bh);
-				*bh = NULL;
-				return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
-			}
-			else
-			{
-				eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
-				eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
-				*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
-			}
-			break;
-		}
-		case ICBTAG_FLAG_AD_LONG:
-		{
-			long_ad *lad;
-
-			if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
-				return -1;
-
-			if ((etype = le32_to_cpu(lad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
-			{
-				*bloc = lelb_to_cpu(lad->extLocation);
-				*extoffset = 0;
-				udf_release_data(*bh);
-				*bh = NULL;
-				return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
-			}
-			else
-			{
-				*eloc = lelb_to_cpu(lad->extLocation);
-				*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
-			}
-			break;
-		}
-		case ICBTAG_FLAG_AD_IN_ICB:
-		{
-			if (UDF_I_LENALLOC(inode) == 0)
-				return -1;
-			etype = (EXT_RECORDED_ALLOCATED >> 30);
-			*eloc = UDF_I_LOCATION(inode);
-			*elen = UDF_I_LENALLOC(inode);
-			break;
-		}
-		default:
-		{
-			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
-			return -1;
-		}
-	}
-	if (*elen)
-		return etype;
-
-	udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
-		inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
-	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-		*extoffset -= sizeof(short_ad);
-	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-		*extoffset -= sizeof(long_ad);
-	return -1;
+	return etype;
 }
 
 int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
-	int pos, alen;
+	int alen;
 	int8_t etype;
+	uint8_t *ptr;
 
-	if (!(*bh))
-	{
-		if (!(*bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
-		{
-			udf_debug("reading block %d failed!\n",
-				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
-			return -1;
-		}
-	}
-
-	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+	if (!*bh)
 	{
-		if (!(UDF_I_EXTENDED_FE(inode)))
-			pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
-		else
-			pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
-		alen = UDF_I_LENALLOC(inode) + pos;
+		if (!(*extoffset))
+			*extoffset = udf_file_entry_alloc_offset(inode);
+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
 	}
 	else
 	{
-		struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
-		pos = sizeof(struct allocExtDesc);
-		alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
+		if (!(*extoffset))
+			*extoffset = sizeof(struct allocExtDesc);
+		ptr = (*bh)->b_data + *extoffset;
+		alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
 	}
 
-	if (!(*extoffset))
-		*extoffset = pos;
-
 	switch (UDF_I_ALLOCTYPE(inode))
 	{
 		case ICBTAG_FLAG_AD_SHORT:
 		{
 			short_ad *sad;
 
-			if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
+			if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
 				return -1;
 
 			etype = le32_to_cpu(sad->extLength) >> 30;
@@ -1998,7 +1873,7 @@
 		{
 			long_ad *lad;
 
-			if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
+			if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
 				return -1;
 
 			etype = le32_to_cpu(lad->extLength) >> 30;
@@ -2012,15 +1887,8 @@
 			return -1;
 		}
 	}
-	if (*elen)
-		return etype;
 
-	udf_debug("Empty Extent!\n");
-	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-		*extoffset -= sizeof(short_ad);
-	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-		*extoffset -= sizeof(long_ad);
-	return -1;
+	return etype;
 }
 
 int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
@@ -2030,17 +1898,7 @@
 	uint32_t oelen;
 	int8_t etype;
 
-	if (!bh)
-	{
-		if (!(bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, bloc, 0))))
-		{
-			udf_debug("reading block %d failed!\n",
-				udf_get_lb_pblock(inode->i_sb, bloc, 0));
-			return -1;
-		}
-	}
-	else
+	if (bh)
 		atomic_inc(&bh->b_count);
 
 	while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
@@ -2064,19 +1922,11 @@
 	int8_t etype;
 	struct allocExtDesc *aed;
 
-	if (!(nbh))
+	if (nbh)
 	{
-		if (!(nbh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
-		{
-			udf_debug("reading block %d failed!\n",
-				udf_get_lb_pblock(inode->i_sb, nbloc, 0));
-			return -1;
-		}
-	}
-	else
 		atomic_inc(&nbh->b_count);
-	atomic_inc(&nbh->b_count);
+		atomic_inc(&nbh->b_count);
+	}
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(short_ad);
@@ -2095,7 +1945,7 @@
 	while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
 	{
 		udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
-		if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+		if (obh != nbh)
 		{
 			obloc = nbloc;
 			udf_release_data(obh);
@@ -2107,12 +1957,12 @@
 	memset(&eloc, 0x00, sizeof(lb_addr));
 	elen = 0;
 
-	if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+	if (nbh != obh)
 	{
 		udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-		if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+		if (!obh)
 		{
 			UDF_I_LENALLOC(inode) -= (adsize * 2);
 			mark_inode_dirty(inode);
@@ -2132,7 +1982,7 @@
 	else
 	{
 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-		if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+		if (!obh)
 		{
 			UDF_I_LENALLOC(inode) -= adsize;
 			mark_inode_dirty(inode);
@@ -2207,9 +2057,7 @@
 		ret = 0;
 
 	unlock_kernel();
-
-	if (bh)
-		udf_release_data(bh);
+	udf_release_data(bh);
 
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
 		return udf_fixed_to_variable(ret);
diff -Nru a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
--- a/fs/udf/lowlevel.c	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/lowlevel.c	Sun Nov 17 20:30:14 2002
@@ -71,15 +71,10 @@
 udf_get_last_block(struct super_block *sb)
 {
 	struct block_device *bdev = sb->s_bdev;
-	int ret;
 	unsigned long lblock = 0;
 
-	ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
-
-	if (ret) /* Hard Disk */
-	{
+	if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock))
 		lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
-	}
 
 	if (lblock)
 		return lblock - 1;
diff -Nru a/fs/udf/misc.c b/fs/udf/misc.c
--- a/fs/udf/misc.c	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/misc.c	Sun Nov 17 20:30:14 2002
@@ -74,7 +74,7 @@
 
 	*bh = udf_tread(inode->i_sb, inode->i_ino);
 
-	if (UDF_I_EXTENDED_FE(inode) == 0)
+	if (UDF_I_EFE(inode) == 0)
 	{
 		struct fileEntry *fe;
 
@@ -190,7 +190,7 @@
 
 	*bh = udf_tread(inode->i_sb, inode->i_ino);
 
-	if (UDF_I_EXTENDED_FE(inode) == 0)
+	if (UDF_I_EFE(inode) == 0)
 	{
 		struct fileEntry *fe;
 
@@ -269,10 +269,10 @@
 	if (block == 0xFFFFFFFF)
 		return NULL;
 
-	bh = udf_tread(sb, block);
+	bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
 	if (!bh)
 	{
-		udf_debug("block=%d, location=%d: read failed\n", block, location);
+		udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
 		return NULL;
 	}
 
@@ -283,7 +283,7 @@
 	if ( location != le32_to_cpu(tag_p->tagLocation) )
 	{
 		udf_debug("location mismatch block %u, tag %u != %u\n",
-			block, le32_to_cpu(tag_p->tagLocation), location);
+			block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
 		goto error_out;
 	}
 	
@@ -315,7 +315,7 @@
 		return bh;
 	}
 	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
-		block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
+		block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
 
 error_out:
 	brelse(bh);
diff -Nru a/fs/udf/namei.c b/fs/udf/namei.c
--- a/fs/udf/namei.c	Sun Nov 17 20:30:15 2002
+++ b/fs/udf/namei.c	Sun Nov 17 20:30:15 2002
@@ -56,12 +56,16 @@
 	uint8_t lfi = cfi->lengthFileIdent;
 	int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
 		sizeof(struct fileIdentDesc);
+	int adinicb = 0;
+
+	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
+		adinicb = 1;
 
 	offset = fibh->soffset + sizeof(struct fileIdentDesc);
 
 	if (impuse)
 	{
-		if (offset + liu < 0)
+		if (adinicb || (offset + liu < 0))
 			memcpy((uint8_t *)sfi->impUse, impuse, liu);
 		else if (offset >= 0)
 			memcpy(fibh->ebh->b_data + offset, impuse, liu);
@@ -76,7 +80,7 @@
 
 	if (fileident)
 	{
-		if (offset + lfi < 0)
+		if (adinicb || (offset + lfi < 0))
 			memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
 		else if (offset >= 0)
 			memcpy(fibh->ebh->b_data + offset, fileident, lfi);
@@ -89,7 +93,7 @@
 
 	offset += lfi;
 
-	if (offset + padlen < 0)
+	if (adinicb || (offset + padlen < 0))
 		memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
 	else if (offset >= 0)
 		memset(fibh->ebh->b_data + offset, 0x00, padlen);
@@ -123,7 +127,7 @@
 			checksum += ((uint8_t *)&cfi->descTag)[i];
 
 	cfi->descTag.tagChecksum = checksum;
-	if (sizeof(struct fileIdentDesc) <= -fibh->soffset)
+	if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
 		memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
 	else
 	{
@@ -132,9 +136,14 @@
 			sizeof(struct fileIdentDesc) + fibh->soffset);
 	}
 
-	if (fibh->sbh != fibh->ebh)
-		mark_buffer_dirty_inode(fibh->ebh, inode);
-	mark_buffer_dirty_inode(fibh->sbh, inode);
+	if (adinicb)
+		mark_inode_dirty(inode);
+	else
+	{
+		if (fibh->sbh != fibh->ebh)
+			mark_buffer_dirty_inode(fibh->ebh, inode);
+		mark_buffer_dirty_inode(fibh->sbh, inode);
+	}
 	return 0;
 }
 
@@ -161,7 +170,9 @@
 	f_pos = (udf_ext0_offset(dir) >> 2);
 
 	fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+		fibh->sbh = fibh->ebh = NULL;
+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
 		offset >>= dir->i_sb->s_blocksize_bits;
@@ -175,6 +186,12 @@
 		}
 		else
 			offset = 0;
+
+		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
+		{
+			udf_release_data(bh);
+			return NULL;
+		}
 	}
 	else
 	{
@@ -182,12 +199,6 @@
 		return NULL;
 	}
 
-	if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
-	{
-		udf_release_data(bh);
-		return NULL;
-	}
-
 	while ( (f_pos < size) )
 	{
 		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
@@ -304,7 +315,8 @@
 	{
 		lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
 		inode = udf_iget(dir->i_sb, lb);
-		if (!inode) {
+		if (!inode)
+		{
 			unlock_kernel();
 			return ERR_PTR(-EACCES);
 		}
@@ -319,7 +331,8 @@
 		udf_release_data(fibh.sbh);
 
 		inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
-		if ( !inode ) {
+		if ( !inode )
+		{
 			unlock_kernel();
 			return ERR_PTR(-EACCES);
 		}
@@ -336,7 +349,6 @@
 {
 	struct super_block *sb;
 	struct fileIdentDesc *fi=NULL;
-	struct ustr unifilename;
 	char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
 	int namelen;
 	loff_t f_pos;
@@ -361,30 +373,11 @@
 			return NULL;
 		}
 
-		if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
+		if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
 		{
 			*err = -ENAMETOOLONG;
 			return NULL;
 		}
-
-		if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
-		{
-			if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
-			{
-				*err = -ENAMETOOLONG;
-				return NULL;
-			}
-		}
-		else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
-		{
-			if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) )
-			{
-				*err = -ENAMETOOLONG;
-				return NULL;
-			}
-		}
-		else
-			return NULL;
 	}
 	else
 		namelen = 0;
@@ -394,7 +387,9 @@
 	f_pos = (udf_ext0_offset(dir) >> 2);
 
 	fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+		fibh->sbh = fibh->ebh = NULL;
+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
 		offset >>= dir->i_sb->s_blocksize_bits;
@@ -415,94 +410,89 @@
 			*err = -EIO;
 			return NULL;
 		}
-	
+
 		block = UDF_I_LOCATION(dir).logicalBlockNum;
-	
-		while ( (f_pos < size) )
+
+	}
+	else
+	{
+		block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
+		fibh->sbh = fibh->ebh = NULL;
+		fibh->soffset = fibh->eoffset = sb->s_blocksize;
+		goto add;
+	}
+
+	while ( (f_pos < size) )
+	{
+		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+
+		if (!fi)
 		{
-			fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-	
-			if (!fi)
-			{
-				if (fibh->sbh != fibh->ebh)
-					udf_release_data(fibh->ebh);
-				udf_release_data(fibh->sbh);
-				udf_release_data(bh);
-				*err = -EIO;
-				return NULL;
-			}
-	
-			liu = le16_to_cpu(cfi->lengthOfImpUse);
-			lfi = cfi->lengthFileIdent;
-	
-			if (fibh->sbh == fibh->ebh)
-				nameptr = fi->fileIdent + liu;
+			if (fibh->sbh != fibh->ebh)
+				udf_release_data(fibh->ebh);
+			udf_release_data(fibh->sbh);
+			udf_release_data(bh);
+			*err = -EIO;
+			return NULL;
+		}
+
+		liu = le16_to_cpu(cfi->lengthOfImpUse);
+		lfi = cfi->lengthFileIdent;
+
+		if (fibh->sbh == fibh->ebh)
+			nameptr = fi->fileIdent + liu;
+		else
+		{
+			int poffset;	/* Unpaded ending offset */
+
+			poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
+
+			if (poffset >= lfi)
+				nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
 			else
 			{
-				int poffset;	/* Unpaded ending offset */
-	
-				poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
-	
-				if (poffset >= lfi)
-					nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
-				else
-				{
-					nameptr = fname;
-					memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
-					memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
-				}
+				nameptr = fname;
+				memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
+				memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
 			}
-	
-			if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
+		}
+
+		if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
+		{
+			if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
 			{
-				if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
+				udf_release_data(bh);
+				cfi->descTag.tagSerialNum = cpu_to_le16(1);
+				cfi->fileVersionNum = cpu_to_le16(1);
+				cfi->fileCharacteristics = 0;
+				cfi->lengthFileIdent = namelen;
+				cfi->lengthOfImpUse = cpu_to_le16(0);
+				if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
+					return fi;
+				else
 				{
-					udf_release_data(bh);
-					cfi->descTag.tagSerialNum = cpu_to_le16(1);
-					cfi->fileVersionNum = cpu_to_le16(1);
-					cfi->fileCharacteristics = 0;
-					cfi->lengthFileIdent = namelen;
-					cfi->lengthOfImpUse = cpu_to_le16(0);
-					if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
-						return fi;
-					else
-					{
-						*err = -EIO;
-						return NULL;
-					}
+					*err = -EIO;
+					return NULL;
 				}
 			}
+		}
 
-			if (!lfi || !dentry)
-				continue;
+		if (!lfi || !dentry)
+			continue;
 
-			if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
-				udf_match(flen, fname, &(dentry->d_name)))
-			{
-				if (fibh->sbh != fibh->ebh)
-					udf_release_data(fibh->ebh);
-				udf_release_data(fibh->sbh);
-				udf_release_data(bh);
-				*err = -EEXIST;
-				return NULL;
-			}
-		}
-	}
-	else
-	{
-		block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
-		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-		{
-			fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
-			fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
-		}
-		else
+		if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
+			udf_match(flen, fname, &(dentry->d_name)))
 		{
-			fibh->sbh = fibh->ebh = NULL;
-			fibh->soffset = fibh->eoffset = sb->s_blocksize;
+			if (fibh->sbh != fibh->ebh)
+				udf_release_data(fibh->ebh);
+			udf_release_data(fibh->sbh);
+			udf_release_data(bh);
+			*err = -EEXIST;
+			return NULL;
 		}
 	}
 
+add:
 	f_pos += nfidlen;
 
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
@@ -539,13 +529,17 @@
 			fibh->sbh = fibh->ebh;
 		}
 
-		if (UDF_I_ALLOCTYPE(dir) != ICBTAG_FLAG_AD_IN_ICB)
+		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+		{
+			block = UDF_I_LOCATION(dir).logicalBlockNum;
+			fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));
+		}
+		else
+		{
 			block = eloc.logicalBlockNum + ((elen - 1) >>
 				dir->i_sb->s_blocksize_bits);
-		else
-			block = UDF_I_LOCATION(dir).logicalBlockNum;
-				
-		fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+			fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+		}
 	}
 	else
 	{
@@ -635,7 +629,8 @@
 
 	lock_kernel();
 	inode = udf_new_inode(dir, mode, &err);
-	if (!inode) {
+	if (!inode)
+	{
 		unlock_kernel();
 		return err;
 	}
@@ -796,7 +791,10 @@
 	f_pos = (udf_ext0_offset(dir) >> 2);
 
 	fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+
+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+		fibh.sbh = fibh.ebh = NULL;
+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
 		offset >>= dir->i_sb->s_blocksize_bits;
@@ -810,6 +808,12 @@
 		}
 		else
 			offset = 0;
+
+		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
+		{
+			udf_release_data(bh);
+			return 0;
+		}
 	}
 	else
 	{
@@ -817,8 +821,6 @@
 		return 0;
 	}
 
-	if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-		return 0;
 
 	while ( (f_pos < size) )
 	{
@@ -835,6 +837,9 @@
 
 		if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
 		{
+			if (fibh.sbh != fibh.ebh)
+				udf_release_data(fibh.ebh);
+			udf_release_data(fibh.sbh);
 			udf_release_data(bh);
 			return 0;
 		}
@@ -950,6 +955,8 @@
 	char *ea;
 	int err;
 	int block;
+	char name[UDF_NAME_LEN];
+	int namelen;
 
 	lock_kernel();
 	if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
@@ -987,13 +994,10 @@
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
 		mark_buffer_dirty_inode(bh, inode);
+		ea = bh->b_data + udf_ext0_offset(inode);
 	}
 	else
-	{
-		block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-		bh = udf_tread(inode->i_sb, block);
-	}
-	ea = bh->b_data + udf_ext0_offset(inode);
+		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
 
 	eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
 	pc = (struct pathComponent *)ea;
@@ -1031,22 +1035,25 @@
 		pc->componentType = 5;
 		pc->lengthComponentIdent = 0;
 		pc->componentFileVersionNum = 0;
-		if (pc->componentIdent[0] == '.')
+		if (compstart[0] == '.')
 		{
-			if (pc->lengthComponentIdent == 1)
+			if ((symname-compstart) == 1)
 				pc->componentType = 4;
-			else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
+			else if ((symname-compstart) == 2 && compstart[1] == '.')
 				pc->componentType = 3;
 		}
 
 		if (pc->componentType == 5)
 		{
-			if (elen + sizeof(struct pathComponent) + symname - compstart > eoffset)
+			if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))
+				goto out_no_entry;
+
+			if (elen + sizeof(struct pathComponent) + namelen > eoffset)
 				goto out_no_entry;
 			else
-				pc->lengthComponentIdent = symname - compstart;
+				pc->lengthComponentIdent = namelen;
 
-			memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
+			memcpy(pc->componentIdent, name, namelen);
 		}
 
 		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
@@ -1114,12 +1121,14 @@
 	struct fileIdentDesc cfi, *fi;
 
 	lock_kernel();
-	if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
+	if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
+	{
 		unlock_kernel();
 		return -EMLINK;
 	}
 
-	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
+	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
+	{
 		unlock_kernel();
 		return err;
 	}
@@ -1204,10 +1213,21 @@
 				goto end_rename;
 		}
 		retval = -EIO;
-		dir_bh = udf_bread(old_inode, 0, 0, &retval);
-		if (!dir_bh)
-			goto end_rename;
-		dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
+		{
+			dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
+				(UDF_I_EFE(old_inode) ?
+					sizeof(struct extendedFileEntry) :
+					sizeof(struct fileEntry)),
+				old_inode->i_sb->s_blocksize, &offset);
+		}
+		else
+		{
+			dir_bh = udf_bread(old_inode, 0, 0, &retval);
+			if (!dir_bh)
+				goto end_rename;
+			dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+		}
 		if (!dir_fi)
 			goto end_rename;
 		if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
@@ -1257,7 +1277,7 @@
 	UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
 	mark_inode_dirty(old_dir);
 
-	if (dir_bh)
+	if (dir_fi)
 	{
 		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
 		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
diff -Nru a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h
--- a/fs/udf/osta_udf.h	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/osta_udf.h	Sun Nov 17 20:30:14 2002
@@ -83,7 +83,7 @@
 {
 	uint8_t		impUse[8];
 } __attribute__ ((packed));
- 
+
 /* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */
 /* Implementation Use (UDF 2.01 2.2.6.4) */
 struct logicalVolIntegrityDescImpUse
diff -Nru a/fs/udf/super.c b/fs/udf/super.c
--- a/fs/udf/super.c	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/super.c	Sun Nov 17 20:30:14 2002
@@ -135,7 +135,7 @@
 	    SLAB_CTOR_CONSTRUCTOR)
 		inode_init_once(&ei->vfs_inode);
 }
- 
+
 static int init_inodecache(void)
 {
 	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
@@ -161,6 +161,7 @@
 	.write_inode		= udf_write_inode,
 	.put_inode		= udf_put_inode,
 	.delete_inode		= udf_delete_inode,
+	.clear_inode		= udf_clear_inode,
 	.put_super		= udf_put_super,
 	.write_super		= udf_write_super,
 	.statfs			= udf_statfs,
@@ -285,7 +286,8 @@
 	if (!options)
 		return 1;
 
-	while ((opt = strsep(&options, ",")) != NULL) {
+	while ((opt = strsep(&options, ",")) != NULL)
+	{
 		if (!*opt)
 			continue;
 		/* Make "opt=val" into two strings */
@@ -383,10 +385,6 @@
 	UDF_SB(sb)->s_gid   = uopt.gid;
 	UDF_SB(sb)->s_umask = uopt.umask;
 
-#if UDFFS_RW != 1
-	*flags |= MS_RDONLY;
-#endif
-
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
 	if (*flags & MS_RDONLY)
@@ -591,14 +589,14 @@
 			{
 				if (location == last[i] - UDF_SB_SESSION(sb))
 				{
-					lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
-					UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+					lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
+					UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb);
 				}
 				else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
 				{
 					UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
-					lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
-					UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+					lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb);
+					UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
 				}
 				else
 					udf_debug("Anchor found at block %d, location mismatch %d.\n",
@@ -607,7 +605,7 @@
 			else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
 			{
 				lastblock = last[i];
-				UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
+				UDF_SB_ANCHOR(sb)[3] = 512;
 			}
 			else
 			{
@@ -852,7 +850,7 @@
 		if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
 		{
 			UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
-			UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
+			UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
 			if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
 				UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
 			if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE)
@@ -1341,7 +1339,7 @@
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-		if (udf_time_to_stamp(&cpu_time, CURRENT_TIME, CURRENT_UTIME))
+		if (udf_time_to_stamp(&cpu_time, get_seconds(), CURRENT_UTIME))
 			UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
 		UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_OPEN;
 
@@ -1369,7 +1367,7 @@
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-		if (udf_time_to_stamp(&cpu_time, CURRENT_TIME, CURRENT_UTIME))
+		if (udf_time_to_stamp(&cpu_time, get_seconds(), CURRENT_UTIME))
 			UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
 		if (UDF_MAX_WRITE_VERSION > le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev))
 			UDF_SB_LVIDIU(sb)->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
@@ -1428,10 +1426,6 @@
 	sb->s_fs_info = sbi;
 	memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
 
-#if UDFFS_RW != 1
-	sb->s_flags |= MS_RDONLY;
-#endif
-
 	if (!udf_parse_options((char *)options, &uopt))
 		goto error_out;
 
@@ -1478,7 +1472,7 @@
 	UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
 	UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
 	UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
-	UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
+	UDF_SB_ANCHOR(sb)[3] = 256;
 
 	if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
 	{
@@ -1543,8 +1537,8 @@
 	{
 		timestamp ts;
 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
-		udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-			UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE,
+		udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+			UDFFS_VERSION, UDFFS_DATE,
 			UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
 			ts.typeAndTimezone);
 	}
@@ -1726,8 +1720,6 @@
 static int
 udf_statfs(struct super_block *sb, struct statfs *buf)
 {
-	lock_kernel();
-
 	buf->f_type = UDF_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
@@ -1740,8 +1732,6 @@
 	/* __kernel_fsid_t f_fsid */
 	buf->f_namelen = UDF_NAME_LEN;
 
-	unlock_kernel();
-
 	return 0;
 }
 
@@ -1763,6 +1753,8 @@
 	uint16_t ident;
 	struct spaceBitmapDesc *bm;
 
+	lock_kernel();
+
 	loc.logicalBlockNum = bitmap->s_extPosition;
 	loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
 	bh = udf_read_ptagged(sb, loc, 0, &ident);
@@ -1770,13 +1762,13 @@
 	if (!bh)
 	{
 		printk(KERN_ERR "udf: udf_count_free failed\n");
-		return 0;
+		goto out;
 	}
 	else if (ident != TAG_IDENT_SBD)
 	{
 		udf_release_data(bh);
 		printk(KERN_ERR "udf: udf_count_free failed\n");
-		return 0;
+		goto out;
 	}
 
 	bm = (struct spaceBitmapDesc *)bh->b_data;
@@ -1802,13 +1794,17 @@
 			if (!bh)
 			{
 				udf_debug("read failed\n");
-				return accum;
+				goto out;
 			}
 			index = 0;
 			ptr = (uint8_t *)bh->b_data;
 		}
 	}
 	udf_release_data(bh);
+
+out:
+	unlock_kernel();
+
 	return accum;
 }
 
@@ -1821,6 +1817,8 @@
 	int8_t etype;
 	struct buffer_head *bh = NULL;
 
+	lock_kernel();
+
 	bloc = UDF_I_LOCATION(table);
 	extoffset = sizeof(struct unallocSpaceEntry);
 
@@ -1829,6 +1827,9 @@
 		accum += (elen >> table->i_sb->s_blocksize_bits);
 	}
 	udf_release_data(bh);
+
+	unlock_kernel();
+
 	return accum;
 }
 	
diff -Nru a/fs/udf/symlink.c b/fs/udf/symlink.c
--- a/fs/udf/symlink.c	Sun Nov 17 20:30:12 2002
+++ b/fs/udf/symlink.c	Sun Nov 17 20:30:12 2002
@@ -38,7 +38,7 @@
 #include <linux/buffer_head.h>
 #include "udf_i.h"
 
-static void udf_pc_to_char(char *from, int fromlen, char *to)
+static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen, char *to)
 {
 	struct pathComponent *pc;
 	int elen = 0;
@@ -66,9 +66,9 @@
 				/* that would be . - just ignore */
 				break;
 			case 5:
-				memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
-				p += pc->lengthComponentIdent;
+				p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
 				*p++ = '/';
+				break;
 		}
 		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
 	}
@@ -85,17 +85,10 @@
 	char *symlink;
 	int err = -EIO;
 	char *p = kmap(page);
-	
+
 	lock_kernel();
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
-	{
-		bh = udf_tread(inode->i_sb, inode->i_ino);
-
-		if (!bh)
-			goto out;
-
-		symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
-	}
+		symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
 	else
 	{
 		bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
@@ -106,7 +99,7 @@
 		symlink = bh->b_data;
 	}
 
-	udf_pc_to_char(symlink, inode->i_size, p);
+	udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
 	udf_release_data(bh);
 
 	unlock_kernel();
diff -Nru a/fs/udf/truncate.c b/fs/udf/truncate.c
--- a/fs/udf/truncate.c	Sun Nov 17 20:30:13 2002
+++ b/fs/udf/truncate.c	Sun Nov 17 20:30:13 2002
@@ -95,7 +95,7 @@
 		else
 			lenalloc = extoffset - adsize;
 
-		if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+		if (!bh)
 			lenalloc -= udf_file_entry_alloc_offset(inode);
 		else
 			lenalloc -= sizeof(struct allocExtDesc);
@@ -108,15 +108,15 @@
 				extoffset = 0;
 				if (lelen)
 				{
-					if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-						memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+					if (!bh)
+						BUG();
 					else
 						memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
 					udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
 				}
 				else
 				{
-					if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+					if (!bh)
 					{
 						UDF_I_LENALLOC(inode) = lenalloc;
 						mark_inode_dirty(inode);
@@ -135,9 +135,9 @@
 				}
 
 				udf_release_data(bh);
-				bh = NULL;
-
+				extoffset = sizeof(struct allocExtDesc);
 				bloc = eloc;
+				bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
 				if (elen)
 					lelen = (elen + inode->i_sb->s_blocksize - 1) >>
 						inode->i_sb->s_blocksize_bits;
@@ -153,15 +153,15 @@
 
 		if (lelen)
 		{
-			if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-				memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+			if (!bh)
+				BUG();
 			else
 				memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
 			udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
 		}
 		else
 		{
-			if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+			if (!bh)
 			{
 				UDF_I_LENALLOC(inode) = lenalloc;
 				mark_inode_dirty(inode);
diff -Nru a/fs/udf/udf_i.h b/fs/udf/udf_i.h
--- a/fs/udf/udf_i.h	Sun Nov 17 20:30:14 2002
+++ b/fs/udf/udf_i.h	Sun Nov 17 20:30:14 2002
@@ -13,14 +13,17 @@
 #define UDF_I_LENEXTENTS(X)	( UDF_I(X)->i_lenExtents )
 #define UDF_I_UNIQUE(X)		( UDF_I(X)->i_unique )
 #define UDF_I_ALLOCTYPE(X)	( UDF_I(X)->i_alloc_type )
-#define UDF_I_EXTENDED_FE(X)	( UDF_I(X)->i_extended_fe )
-#define UDF_I_STRAT4096(X)	( UDF_I(X)->i_strat_4096 )
-#define UDF_I_NEW_INODE(X)	( UDF_I(X)->i_new_inode )
+#define UDF_I_EFE(X)		( UDF_I(X)->i_efe )
+#define UDF_I_USE(X)		( UDF_I(X)->i_use )
+#define UDF_I_STRAT4096(X)	( UDF_I(X)->i_strat4096 )
 #define UDF_I_NEXT_ALLOC_BLOCK(X)	( UDF_I(X)->i_next_alloc_block )
 #define UDF_I_NEXT_ALLOC_GOAL(X)	( UDF_I(X)->i_next_alloc_goal )
 #define UDF_I_UMTIME(X)		( UDF_I(X)->i_umtime )
 #define UDF_I_UCTIME(X)		( UDF_I(X)->i_uctime )
 #define UDF_I_CRTIME(X)		( UDF_I(X)->i_crtime )
 #define UDF_I_UCRTIME(X)	( UDF_I(X)->i_ucrtime )
+#define UDF_I_SAD(X)		( UDF_I(X)->i_ext.i_sad )
+#define UDF_I_LAD(X)		( UDF_I(X)->i_ext.i_lad )
+#define UDF_I_DATA(X)		( UDF_I(X)->i_ext.i_data )
 
 #endif /* !defined(_LINUX_UDF_I_H) */
diff -Nru a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
--- a/fs/udf/udfdecl.h	Sun Nov 17 20:30:13 2002
+++ b/fs/udf/udfdecl.h	Sun Nov 17 20:30:13 2002
@@ -16,10 +16,6 @@
 #include <linux/version.h>
 #endif
 
-#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
-#define CONFIG_UDF_FS_MODULE
-#endif
-
 #include "udfend.h"
 
 #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
@@ -35,9 +31,11 @@
 #define CURRENT_UTIME	(xtime.tv_nsec / 1000)
 
 #define udf_file_entry_alloc_offset(inode)\
-	((UDF_I_EXTENDED_FE(inode) ?\
-		sizeof(struct extendedFileEntry) :\
-		sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode))
+	(UDF_I_USE(inode) ?\
+		sizeof(struct unallocSpaceEntry) :\
+		((UDF_I_EFE(inode) ?\
+			sizeof(struct extendedFileEntry) :\
+			sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
 
 #define udf_ext0_offset(inode)\
 	(UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
@@ -114,6 +112,7 @@
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
+extern void udf_clear_inode(struct inode *);
 extern void udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, long);
 extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
@@ -134,6 +133,10 @@
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
 extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
+extern uint32_t udf64_low32(uint64_t);
+extern uint32_t udf64_high32(uint64_t);
+extern void udf_update_tag(char *, int);
+extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
 
 /* lowlevel.c */
 extern unsigned int udf_get_last_session(struct super_block *);
@@ -148,6 +151,9 @@
 
 /* unicode.c */
 extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
+extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, int);
+extern int udf_build_ustr(struct ustr *, dstring *, int);
+extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
 
 /* ialloc.c */
 extern void udf_free_inode(struct inode *);
@@ -168,40 +174,17 @@
 /* directory.c */
 extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
 extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-
-/* unicode.c */
-extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
-extern int udf_dchars_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_char_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
-extern int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
-extern int udf_build_ustr(struct ustr *, dstring *, int);
-extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
-extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
-extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *);
-extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int);
+extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
+extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
+extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
+extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
+extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 /* crc.c */
 extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
 
-/* misc.c */
-extern uint32_t udf64_low32(uint64_t);
-extern uint32_t udf64_high32(uint64_t);
-extern void udf_update_tag(char *, int);
-extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
-
 /* udftime.c */
 extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
 extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
-
-/* directory.c */
-extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
-extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
-extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 #endif /* __UDF_DECL_H */
diff -Nru a/fs/udf/unicode.c b/fs/udf/unicode.c
--- a/fs/udf/unicode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/udf/unicode.c	Sun Nov 17 20:30:15 2002
@@ -32,46 +32,9 @@
 
 #include "udf_sb.h"
 
-int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
-{
-	if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
-		return 0;
-	memcpy(dest+1, src->u_name, src->u_len);
-	dest[0] = src->u_cmpID;
-	return src->u_len + 1;
-}
-
-int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
-{
-	if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
-		return 0;
-	memcpy(dest, src->u_name, src->u_len);
-	return src->u_len;
-}
-
-int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
-{
-	if ( udf_ustr_to_dchars(dest, src, dlength-1) )
-	{
-		dest[dlength-1] = src->u_len + 1;
-		return dlength;
-	}
-	else
-		return 0;
-}
-
-int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
-{
-	if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
-		return 0;
-	memset(dest, 0, sizeof(struct ustr));
-	memcpy(dest->u_name, src+1, strlen-1);
-	dest->u_cmpID = src[0];
-	dest->u_len = strlen-1;
-	return strlen-1;
-}
+static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
 
-int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
+static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
 {
 	if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
 		return 0;
@@ -82,15 +45,6 @@
 	return strlen;
 }
 
-
-int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
-{
-	if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
-		return dlength;
-	else
-		return 0;
-}
-
 /*
  * udf_build_ustr
  */
@@ -112,7 +66,7 @@
 /*
  * udf_build_ustr_exact
  */
-int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
 {
 	if ( (!dest) || (!ptr) || (!exactsize) )
 		return -1;
@@ -224,7 +178,7 @@
  *	November 12, 1997 - Andrew E. Mileski
  *	Written, tested, and released.
  */
-int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
+static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
 {
 	unsigned c, i, max_val, utf_char;
 	int utf_cnt;
@@ -318,7 +272,7 @@
 	return u_len + 1;
 }
 
-int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
+static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
 {
 	uint8_t *ocu;
 	uint32_t c;
@@ -360,7 +314,7 @@
 	return utf_o->u_len;
 }
 
-int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
+static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
 {
 	unsigned len, i, max_val;
 	uint16_t uni_char;
@@ -434,12 +388,42 @@
 	return 0;
 }
 
+int udf_put_filename(struct super_block *sb, const uint8_t *sname, uint8_t *dname, int flen)
+{
+	struct ustr unifilename;
+	int namelen;
+
+	if ( !(udf_char_to_ustr(&unifilename, sname, flen)) )
+	{
+		return 0;
+	}
+
+	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
+	{
+		if ( !(namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN)) )
+		{
+			return 0;
+		}
+	}
+	else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+	{
+		if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, &unifilename, UDF_NAME_LEN)) )
+		{
+			return 0;
+		}
+	}
+	else
+		return 0;
+
+	return namelen;
+}
+
 #define ILLEGAL_CHAR_MARK	'_'
 #define EXT_MARK			'.'
 #define CRC_MARK			'#'
 #define EXT_SIZE			5
 
-int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
+static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
 {
 	int index, newIndex = 0, needsCRC = 0;	
 	int extIndex = 0, newExtIndex = 0, hasExt = 0;
diff -Nru a/fs/ufs/balloc.c b/fs/ufs/balloc.c
--- a/fs/ufs/balloc.c	Sun Nov 17 20:30:14 2002
+++ b/fs/ufs/balloc.c	Sun Nov 17 20:30:14 2002
@@ -434,7 +434,7 @@
 	/*
 	 * Block can be extended
 	 */
-	ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
+	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
 	for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
 		if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, fragno + i))
 			break;
@@ -532,7 +532,7 @@
 	if (!ufs_cg_chkmagic(sb, ucg)) 
 		ufs_panic (sb, "ufs_alloc_fragments",
 			"internal error, bad magic number on cg %u", cgno);
-	ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
+	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
 
 	if (count == uspi->s_fpb) {
 		result = ufs_alloccg_block (inode, ucpi, goal, err);
diff -Nru a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
--- a/fs/ufs/ialloc.c	Sun Nov 17 20:30:15 2002
+++ b/fs/ufs/ialloc.c	Sun Nov 17 20:30:15 2002
@@ -95,7 +95,7 @@
 	if (!ufs_cg_chkmagic(sb, ucg))
 		ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");
 
-	ucg->cg_time = cpu_to_fs32(sb, CURRENT_TIME);
+	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
 
 	is_directory = S_ISDIR(inode->i_mode);
 
diff -Nru a/fs/ufs/inode.c b/fs/ufs/inode.c
--- a/fs/ufs/inode.c	Sun Nov 17 20:30:04 2002
+++ b/fs/ufs/inode.c	Sun Nov 17 20:30:04 2002
@@ -514,9 +514,12 @@
 	inode->i_gid = ufs_get_inode_gid(sb, ufs_inode);
 
 	inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
-	inode->i_atime = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
-	inode->i_ctime = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
-	inode->i_mtime = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
+	inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
+	inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
+	inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
 	inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat) */
 	inode->i_version++;
@@ -602,11 +605,11 @@
 	ufs_set_inode_gid(sb, ufs_inode, inode->i_gid);
 		
 	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
-	ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime);
+	ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
 	ufs_inode->ui_atime.tv_usec = 0;
-	ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime);
+	ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
 	ufs_inode->ui_ctime.tv_usec = 0;
-	ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime);
+	ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
 	ufs_inode->ui_mtime.tv_usec = 0;
 	ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
 	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	Sun Nov 17 20:30:02 2002
+++ b/fs/ufs/super.c	Sun Nov 17 20:30:02 2002
@@ -868,7 +868,7 @@
 	usb3 = ubh_get_usb_third(USPI_UBH);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		usb1->fs_time = cpu_to_fs32(sb, CURRENT_TIME);
+		usb1->fs_time = cpu_to_fs32(sb, get_seconds());
 		if ((flags & UFS_ST_MASK) == UFS_ST_SUN 
 		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
 			ufs_set_fs_state(sb, usb1, usb3,
@@ -937,7 +937,7 @@
 	 */
 	if (*mount_flags & MS_RDONLY) {
 		ufs_put_cylinder_structures(sb);
-		usb1->fs_time = cpu_to_fs32(sb, CURRENT_TIME);
+		usb1->fs_time = cpu_to_fs32(sb, get_seconds());
 		if ((flags & UFS_ST_MASK) == UFS_ST_SUN
 		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 
 			ufs_set_fs_state(sb, usb1, usb3,
diff -Nru a/fs/umsdos/namei.c b/fs/umsdos/namei.c
--- a/fs/umsdos/namei.c	Sun Nov 17 20:30:15 2002
+++ b/fs/umsdos/namei.c	Sun Nov 17 20:30:15 2002
@@ -257,7 +257,7 @@
 	info.entry.flags = flags;
 	info.entry.uid = current->fsuid;
 	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;
+	info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds();
 	info.entry.nlink = 1;
 	ret = umsdos_newentry (dentry->d_parent, &info);
 	if (ret)
@@ -781,7 +781,7 @@
 	info.entry.rdev = 0;
 	info.entry.uid = current->fsuid;
 	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;
+	info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds();
 	info.entry.flags = 0;
 	info.entry.nlink = 1;
 	ret = umsdos_newentry (dentry->d_parent, &info);
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	Sun Nov 17 20:30:14 2002
+++ b/fs/vfat/namei.c	Sun Nov 17 20:30:14 2002
@@ -820,7 +820,7 @@
 	dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
 	mark_inode_dirty(dir);
 
-	fat_date_unix2dos(dir->i_mtime, &(*de)->time, &(*de)->date);
+	fat_date_unix2dos(dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date);
 	(*de)->ctime = (*de)->time;
 	(*de)->adate = (*de)->cdate = (*de)->date;
 
diff -Nru a/fs/xfs/linux/xfs_ioctl.c b/fs/xfs/linux/xfs_ioctl.c
--- a/fs/xfs/linux/xfs_ioctl.c	Sun Nov 17 20:30:15 2002
+++ b/fs/xfs/linux/xfs_ioctl.c	Sun Nov 17 20:30:15 2002
@@ -35,6 +35,7 @@
 #include <xfs_dfrag.h>
 #include <linux/dcache.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 
 extern int xfs_change_file_space(bhv_desc_t *, int,
diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c
--- a/fs/xfs/linux/xfs_iops.c	Sun Nov 17 20:30:12 2002
+++ b/fs/xfs/linux/xfs_iops.c	Sun Nov 17 20:30:12 2002
@@ -475,18 +475,15 @@
 	}
 	if (ia_valid & ATTR_ATIME) {
 		vattr.va_mask |= AT_ATIME;
-		vattr.va_atime.tv_sec = attr->ia_atime;
-		vattr.va_atime.tv_nsec = 0;
+		vattr.va_atime = attr->ia_atime;
 	}
 	if (ia_valid & ATTR_MTIME) {
 		vattr.va_mask |= AT_MTIME;
-		vattr.va_mtime.tv_sec = attr->ia_mtime;
-		vattr.va_mtime.tv_nsec = 0;
+		vattr.va_mtime = attr->ia_mtime;
 	}
 	if (ia_valid & ATTR_CTIME) {
 		vattr.va_mask |= AT_CTIME;
-		vattr.va_ctime.tv_sec = attr->ia_ctime;
-		vattr.va_ctime.tv_nsec = 0;
+		vattr.va_ctime = attr->ia_ctime;
 	}
 	if (ia_valid & ATTR_MODE) {
 		vattr.va_mask |= AT_MODE;
diff -Nru a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c
--- a/fs/xfs/linux/xfs_super.c	Sun Nov 17 20:30:15 2002
+++ b/fs/xfs/linux/xfs_super.c	Sun Nov 17 20:30:15 2002
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
+#include <linux/mount.h>
 #include "xfs_version.h"
 
 /* xfs_vfs[ops].c */
@@ -426,9 +427,12 @@
 	inode->i_size	= ip->i_d.di_size;
 	inode->i_blocks =
 		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
-	inode->i_atime	= ip->i_d.di_atime.t_sec;
-	inode->i_mtime	= ip->i_d.di_mtime.t_sec;
-	inode->i_ctime	= ip->i_d.di_ctime.t_sec;
+	inode->i_atime.tv_sec	= ip->i_d.di_atime.t_sec;
+	inode->i_atime.tv_nsec	= ip->i_d.di_atime.t_nsec;
+	inode->i_mtime.tv_sec	= ip->i_d.di_mtime.t_sec;
+	inode->i_mtime.tv_nsec	= ip->i_d.di_mtime.t_nsec;
+	inode->i_ctime.tv_sec	= ip->i_d.di_ctime.t_sec;
+	inode->i_ctime.tv_nsec	= ip->i_d.di_ctime.t_nsec;
 
 	vp->v_flag &= ~VMODIFIED;
 }
diff -Nru a/fs/xfs/linux/xfs_vnode.c b/fs/xfs/linux/xfs_vnode.c
--- a/fs/xfs/linux/xfs_vnode.c	Sun Nov 17 20:30:12 2002
+++ b/fs/xfs/linux/xfs_vnode.c	Sun Nov 17 20:30:12 2002
@@ -216,9 +216,12 @@
 		inode->i_gid	    = va.va_gid;
 		inode->i_size	    = va.va_size;
 		inode->i_blocks	    = va.va_nblocks;
-		inode->i_mtime	    = va.va_mtime.tv_sec;
-		inode->i_ctime	    = va.va_ctime.tv_sec;
-		inode->i_atime	    = va.va_atime.tv_sec;
+		inode->i_mtime.tv_sec	    = va.va_mtime.tv_sec;
+		inode->i_mtime.tv_nsec	    = va.va_mtime.tv_nsec;
+		inode->i_ctime.tv_sec	    = va.va_ctime.tv_sec;
+		inode->i_ctime.tv_nsec	    = va.va_ctime.tv_nsec;
+		inode->i_atime.tv_sec	    = va.va_atime.tv_sec;
+		inode->i_atime.tv_nsec	    = va.va_atime.tv_nsec;
 		VUNMODIFY(vp);
 	}
 
diff -Nru a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
--- a/fs/xfs/xfs_dquot.c	Sun Nov 17 20:30:14 2002
+++ b/fs/xfs/xfs_dquot.c	Sun Nov 17 20:30:14 2002
@@ -244,7 +244,7 @@
 		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
 		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_btimer, ARCH_CONVERT, CURRENT_TIME + XFS_QI_BTIMELIMIT(mp));
+			INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
@@ -260,7 +260,7 @@
 		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
 		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_itimer, ARCH_CONVERT, CURRENT_TIME + XFS_QI_ITIMELIMIT(mp));
+			INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
diff -Nru a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
--- a/fs/xfs/xfs_inode.c	Sun Nov 17 20:30:15 2002
+++ b/fs/xfs/xfs_inode.c	Sun Nov 17 20:30:15 2002
@@ -3564,16 +3564,16 @@
 
 	nanotime(&tv);
 	if (flags & XFS_ICHGTIME_MOD) {
-		inode->i_mtime = ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
-		ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
+		inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
+		inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
 	}
 	if (flags & XFS_ICHGTIME_ACC) {
-		inode->i_atime = ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
-		ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
+		inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
+		inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
 	}
 	if (flags & XFS_ICHGTIME_CHG) {
-		inode->i_ctime = ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
-		ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
+		inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
+		inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
 	}
 
 	/*
diff -Nru a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
--- a/fs/xfs/xfs_trans_dquot.c	Sun Nov 17 20:30:04 2002
+++ b/fs/xfs/xfs_trans_dquot.c	Sun Nov 17 20:30:04 2002
@@ -625,7 +625,7 @@
 				 * If timer or warnings has expired,
 				 * return EDQUOT
 				 */
-				if ((btimer != 0 && CURRENT_TIME > btimer) ||
+				if ((btimer != 0 && get_seconds() > btimer) ||
 				    (!INT_ISZERO(dqp->q_core.d_bwarns, ARCH_CONVERT) &&
 				     INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
 				     XFS_QI_BWARNLIMIT(dqp->q_mount))) {
@@ -648,7 +648,7 @@
 				 * return EDQUOT
 				 */
 				if ((!INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
-				     CURRENT_TIME > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
+				     get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
 				    (!INT_ISZERO(dqp->q_core.d_iwarns, ARCH_CONVERT) &&
 				     INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
 				     XFS_QI_IWARNLIMIT(dqp->q_mount))) {
diff -Nru a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
--- a/include/asm-arm/arch-pxa/pxa-regs.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-arm/arch-pxa/pxa-regs.h	Sun Nov 17 20:30:14 2002
@@ -362,7 +362,7 @@
 #define LSR_OE		(1 << 1)	/* Overrun Error */
 #define LSR_DR		(1 << 0)	/* Data Ready */
 
-#define MCR_LOOP	(1 << 4)	*/
+#define MCR_LOOP	(1 << 4)
 #define MCR_OUT2	(1 << 3)	/* force MSR_DCD in loopback mode */
 #define MCR_OUT1	(1 << 2)	/* force MSR_RI in loopback mode */
 #define MCR_RTS		(1 << 1)	/* Request to Send */
diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
--- a/include/asm-arm/ecard.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-arm/ecard.h	Sun Nov 17 20:30:15 2002
@@ -53,6 +53,9 @@
 #define MANU_SERPORT		0x003f
 #define PROD_SERPORT_DSPORT		0x00b9
 
+#define MANU_ARXE		0x0041
+#define PROD_ARXE_SCSI			0x00be
+
 #define MANU_I3			0x0046
 #define PROD_I3_ETHERLAN500		0x00d4
 #define PROD_I3_ETHERLAN600		0x00ec
@@ -95,11 +98,11 @@
 	ECARD_SYNC	 = 3
 } card_speed_t;
 
-typedef struct ecard_id {		/* Card ID structure		*/
+struct ecard_id {			/* Card ID structure		*/
 	unsigned short	manufacturer;
 	unsigned short	product;
 	void		*data;
-} card_ids;
+};
 
 struct in_ecid {			/* Packed card ID information	*/
 	unsigned short	product;	/* Product code			*/
@@ -177,16 +180,6 @@
  */
 #define ecard_release(ec) ((ec)->claimed = 0)
 
-/*
- * Start finding cards from the top of the list
- */
-extern void ecard_startfind (void);
-
-/*
- * Find an expansion card with the correct cid, product and manufacturer code
- */
-extern struct expansion_card *ecard_find (int cid, const card_ids *ids);
- 
 /*
  * Read a chunk from an expansion card
  * cd : where to put read data
diff -Nru a/include/asm-arm/proc-armv/cache.h b/include/asm-arm/proc-armv/cache.h
--- a/include/asm-arm/proc-armv/cache.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-arm/proc-armv/cache.h	Sun Nov 17 20:30:14 2002
@@ -93,11 +93,7 @@
 #define mapping_mapped(map)	(!list_empty(&(map)->i_mmap) || \
 				 !list_empty(&(map)->i_mmap_shared))
 
-static inline void __flush_dcache_page(struct page *page)
-{
-	unsigned long virt = (unsigned long)page_address(page);
-	cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
-}
+extern void __flush_dcache_page(struct page *);
 
 static inline void flush_dcache_page(struct page *page)
 {
@@ -115,8 +111,6 @@
  * duplicate cache flushing elsewhere performed by flush_dcache_page().
  */
 #define flush_icache_page(vma,page)	do { } while (0)
-
-#define clean_dcache_entry(_s)		cpu_dcache_clean_entry((unsigned long)(_s))
 
 /*
  * I cache coherency stuff.
diff -Nru a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h
--- a/include/asm-arm/proc-armv/pgalloc.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-arm/proc-armv/pgalloc.h	Sun Nov 17 20:30:14 2002
@@ -96,7 +96,7 @@
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
 {
 	unsigned long pte_ptr = (unsigned long)ptep;
-	pmd_t pmd;
+	unsigned long pmdval;
 
 	BUG_ON(mm != &init_mm);
 
@@ -105,21 +105,21 @@
 	 * address of the PTE table
 	 */
 	pte_ptr -= PTRS_PER_PTE * sizeof(void *);
-	pmd_val(pmd) = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
-	set_pmd(pmdp, pmd);
-	pmd_val(pmd) += 256 * sizeof(pte_t);
-	set_pmd(pmdp + 1, pmd);
+	pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
+	pmdp[0] = __pmd(pmdval);
+	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
+	cpu_flush_pmd(pmdp);
 }
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
 {
-	pmd_t pmd;
+	unsigned long pmdval;
 
 	BUG_ON(mm == &init_mm);
 
-	pmd_val(pmd) = __pa(page_address(ptep)) | _PAGE_USER_TABLE;
-	set_pmd(pmdp, pmd);
-	pmd_val(pmd) += 256 * sizeof(pte_t);
-	set_pmd(pmdp + 1, pmd);
+	pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
+	pmdp[0] = __pmd(pmdval);
+	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
+	cpu_flush_pmd(pmdp);
 }
diff -Nru a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h
--- a/include/asm-arm/proc-armv/pgtable.h	Sun Nov 17 20:30:03 2002
+++ b/include/asm-arm/proc-armv/pgtable.h	Sun Nov 17 20:30:03 2002
@@ -115,16 +115,17 @@
 
 #include <asm/proc/domain.h>
 
-#define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
-#define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
+#define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
+#define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
 
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-#define set_pmd(pmdp,pmd)	cpu_set_pmd(pmdp, pmd)
+#define set_pmd(pmdp,pmd)	do { *pmdp = pmd; cpu_flush_pmd(pmdp); } while (0)
 
 static inline void pmd_clear(pmd_t *pmdp)
 {
-	set_pmd(pmdp, __pmd(0));
-	set_pmd(pmdp + 1, __pmd(0));
+	pmdp[0], __pmd(0));
+	pmdp[1], __pmd(0));
+	cpu_flush_pmd(pmdp);
 }
 
 static inline pte_t *pmd_page_kernel(pmd_t pmd)
diff -Nru a/include/asm-arm/stat.h b/include/asm-arm/stat.h
--- a/include/asm-arm/stat.h	Sun Nov 17 20:30:03 2002
+++ b/include/asm-arm/stat.h	Sun Nov 17 20:30:03 2002
@@ -15,6 +15,8 @@
 	unsigned long  st_ctime;
 };
 
+#define STAT_HAVE_NSEC 
+
 struct stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
@@ -29,11 +31,11 @@
 	unsigned long  st_blksize;
 	unsigned long  st_blocks;
 	unsigned long  st_atime;
-	unsigned long  __unused1;
+	unsigned long  st_atime_nsec;
 	unsigned long  st_mtime;
-	unsigned long  __unused2;
+	unsigned long  st_mtime_nsec;
 	unsigned long  st_ctime;
-	unsigned long  __unused3;
+	unsigned long  st_ctime_nsec;
 	unsigned long  __unused4;
 	unsigned long  __unused5;
 };
@@ -82,13 +84,13 @@
 #endif
 
 	unsigned long	st_atime;
-	unsigned long	__pad5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__pad6;
+	unsigned long	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec;
 
 	unsigned long long	st_ino;
 };
diff -Nru a/include/asm-cris/stat.h b/include/asm-cris/stat.h
--- a/include/asm-cris/stat.h	Sun Nov 17 20:30:02 2002
+++ b/include/asm-cris/stat.h	Sun Nov 17 20:30:02 2002
@@ -18,6 +18,8 @@
 	unsigned long  st_ctime;
 };
 
+#define STAT_HAVE_NSEC 1
+
 struct stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
@@ -32,11 +34,11 @@
 	unsigned long  st_blksize;
 	unsigned long  st_blocks;
 	unsigned long  st_atime;
-	unsigned long  __unused1;
+	unsigned long  st_atime_nsec;
 	unsigned long  st_mtime;
-	unsigned long  __unused2;
+	unsigned long  st_mtime_nsec;
 	unsigned long  st_ctime;
-	unsigned long  __unused3;
+	unsigned long  st_ctime_nsec;
 	unsigned long  __unused4;
 	unsigned long  __unused5;
 };
@@ -67,13 +69,13 @@
 	unsigned long	__pad4;		/* future possible st_blocks high bits */
 
 	unsigned long	st_atime;
-	unsigned long	__pad5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__pad6;
+	unsigned long	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec;	/* will be high 32 bits of ctime someday */
 
 	unsigned long long	st_ino;
 };
diff -Nru a/include/asm-i386/module.h b/include/asm-i386/module.h
--- a/include/asm-i386/module.h	Sun Nov 17 20:30:03 2002
+++ b/include/asm-i386/module.h	Sun Nov 17 20:30:03 2002
@@ -1,12 +1,11 @@
 #ifndef _ASM_I386_MODULE_H
 #define _ASM_I386_MODULE_H
-/*
- * This file contains the i386 architecture specific module code.
- */
-
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
+/* x86 is simple */
+struct mod_arch_specific
+{
+};
 
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
 #endif /* _ASM_I386_MODULE_H */
diff -Nru a/include/asm-i386/stat.h b/include/asm-i386/stat.h
--- a/include/asm-i386/stat.h	Sun Nov 17 20:30:02 2002
+++ b/include/asm-i386/stat.h	Sun Nov 17 20:30:02 2002
@@ -29,11 +29,11 @@
 	unsigned long  st_blksize;
 	unsigned long  st_blocks;
 	unsigned long  st_atime;
-	unsigned long  __unused1;
+	unsigned long  st_atime_nsec;
 	unsigned long  st_mtime;
-	unsigned long  __unused2;
+	unsigned long  st_mtime_nsec;
 	unsigned long  st_ctime;
-	unsigned long  __unused3;
+	unsigned long  st_ctime_nsec;
 	unsigned long  __unused4;
 	unsigned long  __unused5;
 };
@@ -64,13 +64,13 @@
 	unsigned long	__pad4;		/* future possible st_blocks high bits */
 
 	unsigned long	st_atime;
-	unsigned long	__pad5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__pad6;
+	unsigned int	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec;
 
 	unsigned long long	st_ino;
 };
diff -Nru a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h
--- a/include/asm-i386/suspend.h	Sun Nov 17 20:30:12 2002
+++ b/include/asm-i386/suspend.h	Sun Nov 17 20:30:12 2002
@@ -15,8 +15,6 @@
 
 /* image of the saved processor state */
 struct saved_context {
-	unsigned long eax, ebx, ecx, edx;
-	unsigned long esp, ebp, esi, edi;
   	u16 es, fs, gs, ss;
 	unsigned long cr0, cr2, cr3, cr4;
 	u16 gdt_pad;
@@ -30,8 +28,13 @@
 	unsigned long tr;
 	unsigned long safety;
 	unsigned long return_address;
-	unsigned long eflags;
 } __attribute__((packed));
+
+/* We'll access these from assembly, so we'd better have them outside struct */
+extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
+extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
+extern unsigned long saved_context_eflags;
+
 
 #define loaddebug(thread,register) \
                __asm__("movl %0,%%db" #register  \
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-i386/unistd.h	Sun Nov 17 20:30:14 2002
@@ -262,6 +262,7 @@
 #define __NR_sys_epoll_ctl	255
 #define __NR_sys_epoll_wait	256
 #define __NR_remap_file_pages	257
+#define __NR_set_tid_address	258
 
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -Nru a/include/asm-ia64/stat.h b/include/asm-ia64/stat.h
--- a/include/asm-ia64/stat.h	Sun Nov 17 20:30:12 2002
+++ b/include/asm-ia64/stat.h	Sun Nov 17 20:30:12 2002
@@ -17,15 +17,17 @@
 	unsigned long	st_rdev;
 	unsigned long	st_size;
 	unsigned long	st_atime;
-	unsigned long	__reserved0;	/* reserved for atime.nanoseconds */
+	unsigned long	st_atime_nsec;
 	unsigned long	st_mtime;
-	unsigned long	__reserved1;	/* reserved for mtime.nanoseconds */
+	unsigned long	st_mtime_nsec;
 	unsigned long	st_ctime;
-	unsigned long	__reserved2;	/* reserved for ctime.nanoseconds */
+	unsigned long	st_ctime_nsec;
 	unsigned long	st_blksize;
 	long		st_blocks;
 	unsigned long	__unused[3];
 };
+
+#define STAT_HAVE_NSEC 1
 
 struct ia64_oldstat {
 	unsigned int	st_dev;
diff -Nru a/include/asm-m68k/stat.h b/include/asm-m68k/stat.h
--- a/include/asm-m68k/stat.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-m68k/stat.h	Sun Nov 17 20:30:14 2002
@@ -66,13 +66,13 @@
 	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
 
 	unsigned long	st_atime;
-	unsigned long	__pad5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__pad6;
+	unsigned long	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec;
 
 	unsigned long long	st_ino;
 };
diff -Nru a/include/asm-mips/stat.h b/include/asm-mips/stat.h
--- a/include/asm-mips/stat.h	Sun Nov 17 20:30:16 2002
+++ b/include/asm-mips/stat.h	Sun Nov 17 20:30:16 2002
@@ -37,11 +37,11 @@
 	 * but we don't have it under Linux.
 	 */
 	time_t		st_atime;
-	long		reserved0;
+	long		st_atime_nsec;
 	time_t		st_mtime;
-	long		reserved1;
+	long		st_mtime_nsec;
 	time_t		st_ctime;
-	long		reserved2;
+	long		st_ctime_nsec;
 	long		st_blksize;
 	long		st_blocks;
 	long		st_pad4[14];
diff -Nru a/include/asm-mips64/stat.h b/include/asm-mips64/stat.h
--- a/include/asm-mips64/stat.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-mips64/stat.h	Sun Nov 17 20:30:15 2002
@@ -74,18 +74,20 @@
 	 * but we don't have it under Linux.
 	 */
 	unsigned int	st_atime;
-	unsigned int	reserved0;	/* Reserved for st_atime expansion  */
+	unsigned int	st_atime_nsec;
 
 	unsigned int	st_mtime;
-	unsigned int	reserved1;	/* Reserved for st_mtime expansion  */
+	unsigned int	st_mtime_nsec;
 
 	unsigned int	st_ctime;
-	unsigned int	reserved2;	/* Reserved for st_ctime expansion  */
+	unsigned int	st_ctime_nsec;
 
 	unsigned int	st_blksize;
 	unsigned int	st_pad2;
 
 	unsigned long	st_blocks;
 };
+
+#define STAT_HAVE_NSEC 1
 
 #endif /* _ASM_STAT_H */
diff -Nru a/include/asm-parisc/stat.h b/include/asm-parisc/stat.h
--- a/include/asm-parisc/stat.h	Sun Nov 17 20:30:02 2002
+++ b/include/asm-parisc/stat.h	Sun Nov 17 20:30:02 2002
@@ -13,11 +13,11 @@
 	dev_t		st_rdev;
 	off_t		st_size;
 	time_t		st_atime;
-	unsigned int	st_spare1;
+	unsigned int	st_atime_nsec;
 	time_t		st_mtime;
-	unsigned int	st_spare2;
+	unsigned int	st_mtime_nsec;
 	time_t		st_ctime;
-	unsigned int	st_spare3;
+	unsigned int	st_ctime_nsec;
 	int		st_blksize;
 	int		st_blocks;
 	unsigned int	__unused1;	/* ACL stuff */
@@ -33,6 +33,8 @@
 	gid_t		st_gid;
 	unsigned int	st_spare4[3];
 };
+
+#define STAT_HAVE_NSEC
 
 typedef __kernel_off64_t	off64_t;
 
diff -Nru a/include/asm-ppc/stat.h b/include/asm-ppc/stat.h
--- a/include/asm-ppc/stat.h	Sun Nov 17 20:30:02 2002
+++ b/include/asm-ppc/stat.h	Sun Nov 17 20:30:02 2002
@@ -19,6 +19,8 @@
 	unsigned long  st_ctime;
 };
 
+#define STAT_HAVE_NSEC 1
+
 struct stat {
 	dev_t		st_dev;
 	ino_t		st_ino;
@@ -31,11 +33,11 @@
 	unsigned long  	st_blksize;
 	unsigned long  	st_blocks;
 	unsigned long  	st_atime;
-	unsigned long  	__unused1;
+	unsigned long  	st_atime_nsec;
 	unsigned long  	st_mtime;
-	unsigned long  	__unused2;
+	unsigned long  	st_mtime_nsec;
 	unsigned long  	st_ctime;
-	unsigned long  	__unused3;
+	unsigned long  	st_ctime_nsec;
 	unsigned long  	__unused4;
 	unsigned long  	__unused5;
 };
@@ -56,11 +58,11 @@
 
 	long long st_blocks;		/* Number 512-byte blocks allocated. */
 	long st_atime;			/* Time of last access.  */
-	unsigned long int __unused1;
+	unsigned long st_atime_nsec;
 	long st_mtime;			/* Time of last modification.  */
-	unsigned long int __unused2;
+	unsigned long int st_mtime_nsec;
 	long st_ctime;			/* Time of last status change.  */
-	unsigned long int __unused3;
+	unsigned long int st_ctime_nsec;
 	unsigned long int __unused4;
 	unsigned long int __unused5;
 };
diff -Nru a/include/asm-ppc64/stat.h b/include/asm-ppc64/stat.h
--- a/include/asm-ppc64/stat.h	Sun Nov 17 20:30:16 2002
+++ b/include/asm-ppc64/stat.h	Sun Nov 17 20:30:16 2002
@@ -36,16 +36,18 @@
 	unsigned long  	st_blksize;
 	unsigned long  	st_blocks;
 	unsigned long  	st_atime;
-	unsigned long  	__unused1;
+	unsigned long	st_atime_nsec;
 	unsigned long  	st_mtime;
-	unsigned long  	__unused2;
+	unsigned long  	st_mtime_nsec;
 	unsigned long  	st_ctime;
-	unsigned long  	__unused3;
+	unsigned long  	st_ctime_nsec;
 	unsigned long  	__unused4;
 	unsigned long  	__unused5;
 	unsigned long  	__unused6;
 };
 
+#define STAT_HAVE_NSEC 1
+
 /* This matches struct stat64 in glibc2.1. */
 struct stat64 {
 	unsigned long st_dev; 		/* Device.  */
@@ -61,11 +63,11 @@
 
 	long st_blocks;			/* Number 512-byte blocks allocated. */
 	int   st_atime;			/* Time of last access.  */
-	unsigned int  __unused1;
+	int   st_atime_nsec;
 	int   st_mtime;			/* Time of last modification.  */
-	unsigned int  __unused2;
+	int   st_mtime_nsec;
 	int   st_ctime;			/* Time of last status change.  */
-	unsigned int   __unused3;
+	int   st_ctime_nsec;
 	unsigned int   __unused4;
 	unsigned int   __unused5;
 };
diff -Nru a/include/asm-s390/stat.h b/include/asm-s390/stat.h
--- a/include/asm-s390/stat.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-s390/stat.h	Sun Nov 17 20:30:15 2002
@@ -37,15 +37,17 @@
         unsigned long  st_blksize;
         unsigned long  st_blocks;
         unsigned long  st_atime;
-        unsigned long  __unused1;
+        unsigned long  st_atime_nsec;
         unsigned long  st_mtime;
-        unsigned long  __unused2;
+        unsigned long  st_mtime_nsec;
         unsigned long  st_ctime;
-        unsigned long  __unused3;
+        unsigned long  st_ctime_nsec;
         unsigned long  __unused4;
         unsigned long  __unused5;
 };
 
+#define STAT_HAVE_NSEC 1
+
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
@@ -68,11 +70,11 @@
         unsigned long   __pad5;     /* future possible st_blocks high bits */
         unsigned long   st_blocks;  /* Number 512-byte blocks allocated. */
         unsigned long   st_atime;
-        unsigned long   __pad6;
+        unsigned long   st_atime_nsec;
         unsigned long   st_mtime;
-        unsigned long   __pad7;
+        unsigned long   st_mtime_nsec;
         unsigned long   st_ctime;
-        unsigned long   __pad8;     /* will be high 32 bits of ctime someday */
+        unsigned long   st_ctime_nsec;  /* will be high 32 bits of ctime someday */
         unsigned long long      st_ino;
 };
 
diff -Nru a/include/asm-s390x/stat.h b/include/asm-s390x/stat.h
--- a/include/asm-s390x/stat.h	Sun Nov 17 20:30:16 2002
+++ b/include/asm-s390x/stat.h	Sun Nov 17 20:30:16 2002
@@ -20,14 +20,16 @@
         unsigned long  st_rdev;
         unsigned long  st_size;
         unsigned long  st_atime;
-	unsigned long	__reserved0;	/* reserved for atime.nanoseconds */
+	unsigned long  st_atime_nsec;
         unsigned long  st_mtime;
-	unsigned long	__reserved1;	/* reserved for mtime.nanoseconds */
+	unsigned long  st_mtime_nsec;
         unsigned long  st_ctime;
-	unsigned long	__reserved2;	/* reserved for ctime.nanoseconds */
+	unsigned long  st_ctime_nsec;
         unsigned long  st_blksize;
         long           st_blocks;
         unsigned long  __unused[3];
 };
+
+#define STAT_HAVE_NSEC 1
 
 #endif
diff -Nru a/include/asm-sh/stat.h b/include/asm-sh/stat.h
--- a/include/asm-sh/stat.h	Sun Nov 17 20:30:02 2002
+++ b/include/asm-sh/stat.h	Sun Nov 17 20:30:02 2002
@@ -29,15 +29,17 @@
 	unsigned long  st_blksize;
 	unsigned long  st_blocks;
 	unsigned long  st_atime;
-	unsigned long  __unused1;
+	unsigned long  st_atime_nsec;
 	unsigned long  st_mtime;
-	unsigned long  __unused2;
+	unsigned long  st_mtime_nsec;
 	unsigned long  st_ctime;
-	unsigned long  __unused3;
+	unsigned long  st_ctime_nsec;
 	unsigned long  __unused4;
 	unsigned long  __unused5;
 };
 
+#define STAT_HAVE_NSEC 1
+
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
@@ -81,13 +83,13 @@
 #endif
 
 	unsigned long	st_atime;
-	unsigned long	__pad5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__pad6;
+	unsigned long	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec; 
 
 	unsigned long	__unused1;
 	unsigned long	__unused2;
diff -Nru a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
--- a/include/asm-sparc/elf.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-sparc/elf.h	Sun Nov 17 20:30:15 2002
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/mbus.h>
+#include <asm/uaccess.h>
 
 /* For the most part we present code dumps in the format
  * Solaris does.
diff -Nru a/include/asm-sparc/module.h b/include/asm-sparc/module.h
--- a/include/asm-sparc/module.h	Sun Nov 17 20:30:12 2002
+++ b/include/asm-sparc/module.h	Sun Nov 17 20:30:12 2002
@@ -1,12 +1,7 @@
 #ifndef _ASM_SPARC_MODULE_H
 #define _ASM_SPARC_MODULE_H
-/*
- * This file contains the sparc architecture specific module code.
- */
-
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
-
+struct mod_arch_specific { };
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
 #endif /* _ASM_SPARC_MODULE_H */
diff -Nru a/include/asm-sparc/stat.h b/include/asm-sparc/stat.h
--- a/include/asm-sparc/stat.h	Sun Nov 17 20:30:14 2002
+++ b/include/asm-sparc/stat.h	Sun Nov 17 20:30:14 2002
@@ -28,16 +28,18 @@
 	unsigned short	st_rdev;
 	long		st_size;
 	long		st_atime;
-	unsigned long	__unused1;
+	unsigned long	st_atime_nsec;
 	long		st_mtime;
-	unsigned long	__unused2;
+	unsigned long	st_mtime_nsec;
 	long		st_ctime;
-	unsigned long	__unused3;
+	unsigned long	st_ctime_nsec;
 	long		st_blksize;
 	long		st_blocks;
 	unsigned long	__unused4[2];
 };
 
+#define STAT_HAVE_NSEC 1
+
 struct stat64 {
 	unsigned char	__pad0[6];
 	unsigned short	st_dev;
@@ -62,13 +64,13 @@
 	unsigned int	st_blocks;
 
 	unsigned int	st_atime;
-	unsigned int	__unused1;
+	unsigned int	st_atime_nsec;
 
 	unsigned int	st_mtime;
-	unsigned int	__unused2;
+	unsigned int	st_mtime_nsec;
 
 	unsigned int	st_ctime;
-	unsigned int	__unused3;
+	unsigned int	st_ctime_nsec;
 
 	unsigned int	__unused4;
 	unsigned int	__unused5;
diff -Nru a/include/asm-sparc64/module.h b/include/asm-sparc64/module.h
--- a/include/asm-sparc64/module.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-sparc64/module.h	Sun Nov 17 20:30:15 2002
@@ -1,12 +1,7 @@
 #ifndef _ASM_SPARC64_MODULE_H
 #define _ASM_SPARC64_MODULE_H
-/*
- * This file contains the sparc64 architecture specific module code.
- */
-
-extern void * module_map (unsigned long size);
-extern void module_unmap (void *addr);
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
-
+struct mod_arch_specific { };
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
 #endif /* _ASM_SPARC64_MODULE_H */
diff -Nru a/include/asm-sparc64/stat.h b/include/asm-sparc64/stat.h
--- a/include/asm-sparc64/stat.h	Sun Nov 17 20:30:16 2002
+++ b/include/asm-sparc64/stat.h	Sun Nov 17 20:30:16 2002
@@ -69,13 +69,13 @@
 	unsigned int	st_blocks;
 
 	unsigned int	st_atime;
-	unsigned int	__unused1;
+	unsigned int	st_atime_nsec;
 
 	unsigned int	st_mtime;
-	unsigned int	__unused2;
+	unsigned int	st_mtime_nsec;
 
 	unsigned int	st_ctime;
-	unsigned int	__unused3;
+	unsigned int	st_ctime_nsec;
 
 	unsigned int	__unused4;
 	unsigned int	__unused5;
diff -Nru a/include/asm-um/irq.h b/include/asm-um/irq.h
--- a/include/asm-um/irq.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-um/irq.h	Sun Nov 17 20:30:15 2002
@@ -23,8 +23,9 @@
 #define WINCH_IRQ		10
 #define SIGIO_WRITE_IRQ 	11
 #define TELNETD_IRQ 		12
+#define XTERM_IRQ 		13
 
-#define LAST_IRQ TELNETD_IRQ
+#define LAST_IRQ XTERM_IRQ
 #define NR_IRQS (LAST_IRQ + 1)
 
 extern int um_request_irq(unsigned int irq, int fd, int type,
diff -Nru a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h
--- a/include/asm-um/system-generic.h	Sun Nov 17 20:30:16 2002
+++ b/include/asm-um/system-generic.h	Sun Nov 17 20:30:16 2002
@@ -18,9 +18,9 @@
 extern void *switch_to(void *prev, void *next, void *last);
 
 extern int set_signals(int enable);
+extern int get_signals(void);
 extern void block_signals(void);
 extern void unblock_signals(void);
-extern int get_signals(void);
 
 #define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
 #define local_irq_restore(flags) do { set_signals(flags); } while(0)
@@ -31,11 +31,11 @@
 #define local_irq_enable() unblock_signals()
 #define local_irq_disable() block_signals()
 
-#define irqs_disabled()			\
-({					\
-	unsigned long flags;		\
-	local_save_flags(flags);	\
-	(flags != 0);			\
+#define irqs_disabled()                 \
+({                                      \
+        unsigned long flags;            \
+        local_save_flags(flags);        \
+        (flags == 0);                   \
 })
 
 #endif
diff -Nru a/include/asm-um/unistd.h b/include/asm-um/unistd.h
--- a/include/asm-um/unistd.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-um/unistd.h	Sun Nov 17 20:30:15 2002
@@ -23,7 +23,7 @@
 		       struct timeval *tvp);
 extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence);
 extern long sys_read(unsigned int fildes, char *buf, int len);
-extern long sys_write(unsigned int fildes, char *buf, int len);
+extern long sys_write(int fildes, const char *buf, size_t len);
 
 #ifdef __KERNEL_SYSCALLS__
 
diff -Nru a/include/asm-x86_64/stat.h b/include/asm-x86_64/stat.h
--- a/include/asm-x86_64/stat.h	Sun Nov 17 20:30:15 2002
+++ b/include/asm-x86_64/stat.h	Sun Nov 17 20:30:15 2002
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_64_STAT_H
 #define _ASM_X86_64_STAT_H
 
+#define STAT_HAVE_NSEC 1
+
 struct stat {
 	unsigned long	st_dev;
 	unsigned long	st_ino;
@@ -16,11 +18,11 @@
 	long		st_blocks;	/* Number 512-byte blocks allocated. */
 
 	unsigned long	st_atime;
-	unsigned long	__reserved0;	/* reserved for atime.nanoseconds */
+	unsigned long 	st_atime_nsec; 
 	unsigned long	st_mtime;
-	unsigned long	__reserved1;	/* reserved for atime.nanoseconds */
+	unsigned long	st_mtime_nsec;
 	unsigned long	st_ctime;
-	unsigned long	__reserved2;	/* reserved for atime.nanoseconds */
+	unsigned long   st_ctime_nsec;
   	long		__unused[3];
 };
 
diff -Nru a/include/linux/amigaffs.h b/include/linux/amigaffs.h
--- a/include/linux/amigaffs.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/amigaffs.h	Sun Nov 17 20:30:04 2002
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 #include <asm/byteorder.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/atmdev.h	Sun Nov 17 20:30:15 2002
@@ -205,7 +205,7 @@
 #undef __AAL_STAT_ITEMS
 #else
 
-#include <linux/sched.h> /* wait_queue_head_t */
+#include <linux/wait.h> /* wait_queue_head_t */
 #include <linux/time.h> /* struct timeval */
 #include <linux/net.h>
 #include <linux/skbuff.h> /* struct sk_buff */
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/blkdev.h	Sun Nov 17 20:30:12 2002
@@ -2,7 +2,6 @@
 #define _LINUX_BLKDEV_H
 
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/genhd.h>
 #include <linux/list.h>
 #include <linux/pagemap.h>
diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h
--- a/include/linux/buffer_head.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/buffer_head.h	Sun Nov 17 20:30:02 2002
@@ -141,6 +141,7 @@
 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
 int inode_has_buffers(struct inode *);
 void invalidate_inode_buffers(struct inode *);
+int remove_inode_buffers(struct inode *inode);
 int fsync_buffers_list(spinlock_t *lock, struct list_head *);
 int sync_mapping_buffers(struct address_space *mapping);
 void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
diff -Nru a/include/linux/coda_linux.h b/include/linux/coda_linux.h
--- a/include/linux/coda_linux.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/coda_linux.h	Sun Nov 17 20:30:04 2002
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/param.h>
-#include <linux/sched.h> 
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
diff -Nru a/include/linux/cpu.h b/include/linux/cpu.h
--- a/include/linux/cpu.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/cpu.h	Sun Nov 17 20:30:04 2002
@@ -21,6 +21,7 @@
 
 #include <linux/device.h>
 #include <linux/node.h>
+#include <asm/semaphore.h>
 
 struct cpu {
 	int node_id;		/* The node which contains the CPU */
@@ -29,4 +30,6 @@
 
 extern int register_cpu(struct cpu *, int, struct node *);
 
+/* Stop CPUs going up and down. */
+extern struct semaphore cpucontrol;
 #endif /* _LINUX_CPU_H_ */
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	Sun Nov 17 20:30:16 2002
+++ b/include/linux/dcache.h	Sun Nov 17 20:30:16 2002
@@ -4,12 +4,13 @@
 #ifdef __KERNEL__
 
 #include <asm/atomic.h>
-#include <linux/mount.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <asm/page.h>			/* for BUG() */
 
+struct vfsmount;
+
 /*
  * linux/include/linux/dcache.h
  *
@@ -228,8 +229,7 @@
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
 
-extern char * __d_path(struct dentry *, struct vfsmount *, struct dentry *,
-	struct vfsmount *, char *, int);
+extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
   
 /* Allocation counts.. */
 
diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/devfs_fs_kernel.h	Sun Nov 17 20:30:15 2002
@@ -41,6 +41,8 @@
 
 #ifdef CONFIG_DEVFS_FS
 
+extern void devfs_remove(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
 struct unique_numspace
 {
     spinlock_t init_lock;
@@ -88,7 +90,8 @@
 extern devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master);
 extern const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen);
 extern int devfs_only (void);
-extern void devfs_register_tape (devfs_handle_t de);
+extern int devfs_register_tape (devfs_handle_t de);
+extern void devfs_unregister_tape(int num);
 extern void devfs_register_series (devfs_handle_t dir, const char *format,
 				   unsigned int num_entries,
 				   unsigned int flags, unsigned int major,
@@ -158,6 +161,9 @@
 					      char type, int traverse_symlinks)
 {
 }
+static inline void devfs_remove(const char *fmt, ...)
+{
+}
 static inline int devfs_get_flags (devfs_handle_t de, unsigned int *flags)
 {
     return 0;
@@ -230,11 +236,13 @@
 {
     return 0;
 }
-static inline void devfs_register_tape (devfs_handle_t de)
+static inline int devfs_register_tape (devfs_handle_t de)
+{
+    return -1;
+}
+static inline void devfs_unregister_tape(int num)
 {
-    return;
 }
-
 static inline void devfs_register_series (devfs_handle_t dir,
 					  const char *format,
 					  unsigned int num_entries,
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/device.h	Sun Nov 17 20:30:15 2002
@@ -23,14 +23,17 @@
 #ifndef _DEVICE_H_
 #define _DEVICE_H_
 
-#include <linux/types.h>
 #include <linux/config.h>
 #include <linux/ioport.h>
+#include <linux/kobject.h>
 #include <linux/list.h>
 #include <linux/sched.h>
-#include <linux/kobject.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/atomic.h>
 
-#define DEVICE_NAME_SIZE	80
+#define DEVICE_NAME_SIZE	50
+#define DEVICE_NAME_HALF	__stringify(20)	/* Less than half to accommodate slop */
 #define DEVICE_ID_SIZE		32
 #define BUS_ID_SIZE		16
 
@@ -443,19 +446,19 @@
 #ifdef DEBUG
 #define dev_dbg(dev, format, arg...)		\
 	printk (KERN_DEBUG "%s %s: " format ,	\
-		dev.driver->name , dev.bus_id , ## arg)
+		(dev).driver->name , (dev).bus_id , ## arg)
 #else
 #define dev_dbg(dev, format, arg...) do {} while (0)
 #endif
 
 #define dev_err(dev, format, arg...)		\
 	printk (KERN_ERR "%s %s: " format ,	\
-		dev.driver->name , dev.bus_id , ## arg)
+		(dev).driver->name , (dev).bus_id , ## arg)
 #define dev_info(dev, format, arg...)		\
 	printk (KERN_INFO "%s %s: " format ,	\
-		dev.driver->name , dev.bus_id , ## arg)
+		(dev).driver->name , (dev).bus_id , ## arg)
 #define dev_warn(dev, format, arg...)		\
-	printk (KERN_WARN "%s %s: " format ,	\
-		dev.driver->name , dev.bus_id , ## arg)
+	printk (KERN_WARNING "%s %s: " format ,	\
+		(dev).driver->name , (dev).bus_id , ## arg)
 
 #endif /* _DEVICE_H_ */
diff -Nru a/include/linux/elf.h b/include/linux/elf.h
--- a/include/linux/elf.h	Sun Nov 17 20:30:03 2002
+++ b/include/linux/elf.h	Sun Nov 17 20:30:03 2002
@@ -1,7 +1,6 @@
 #ifndef _LINUX_ELF_H
 #define _LINUX_ELF_H
 
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <asm/elf.h>
 
@@ -198,6 +197,9 @@
 #define ELF32_R_SYM(x) ((x) >> 8)
 #define ELF32_R_TYPE(x) ((x) & 0xff)
 
+#define ELF64_R_SYM(i)			((i) >> 32)
+#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
+
 #define R_386_NONE	0
 #define R_386_32	1
 #define R_386_PC32	2
@@ -295,6 +297,7 @@
 #define R_SPARC_PCPLT10		29
 #define R_SPARC_10		30
 #define R_SPARC_11		31
+#define R_SPARC_64		32
 #define R_SPARC_WDISP16		40
 #define R_SPARC_WDISP19		41
 #define R_SPARC_7		43
@@ -368,6 +371,47 @@
 #define R_ALPHA_GLOB_DAT        25      /* Create GOT entry */
 #define R_ALPHA_JMP_SLOT        26      /* Create PLT entry */
 #define R_ALPHA_RELATIVE        27      /* Adjust by program base */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE		0
+#define R_PPC_ADDR32		1	/* 32bit absolute address */
+#define R_PPC_ADDR24		2	/* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16		3	/* 16bit absolute address */
+#define R_PPC_ADDR16_LO		4	/* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI		5	/* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA		6	/* adjusted high 16bit */
+#define R_PPC_ADDR14		7	/* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN	8
+#define R_PPC_ADDR14_BRNTAKEN	9
+#define R_PPC_REL24		10	/* PC relative 26 bit */
+#define R_PPC_REL14		11	/* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN	12
+#define R_PPC_REL14_BRNTAKEN	13
+#define R_PPC_GOT16		14
+#define R_PPC_GOT16_LO		15
+#define R_PPC_GOT16_HI		16
+#define R_PPC_GOT16_HA		17
+#define R_PPC_PLTREL24		18
+#define R_PPC_COPY		19
+#define R_PPC_GLOB_DAT		20
+#define R_PPC_JMP_SLOT		21
+#define R_PPC_RELATIVE		22
+#define R_PPC_LOCAL24PC		23
+#define R_PPC_UADDR32		24
+#define R_PPC_UADDR16		25
+#define R_PPC_REL32		26
+#define R_PPC_PLT32		27
+#define R_PPC_PLTREL32		28
+#define R_PPC_PLT16_LO		29
+#define R_PPC_PLT16_HI		30
+#define R_PPC_PLT16_HA		31
+#define R_PPC_SDAREL16		32
+#define R_PPC_SECTOFF		33
+#define R_PPC_SECTOFF_LO	34
+#define R_PPC_SECTOFF_HI	35
+#define R_PPC_SECTOFF_HA	36
+/* Keep this the last entry.  */
+#define R_PPC_NUM		37
 
 /* Legal values for e_flags field of Elf64_Ehdr.  */
 
diff -Nru a/include/linux/eventpoll.h b/include/linux/eventpoll.h
--- a/include/linux/eventpoll.h	Sun Nov 17 20:30:13 2002
+++ b/include/linux/eventpoll.h	Sun Nov 17 20:30:13 2002
@@ -34,8 +34,11 @@
 asmlinkage int sys_epoll_wait(int epfd, struct pollfd *events, int maxevents,
 			      int timeout);
 
+/* Used to initialize the epoll bits inside the "struct file" */
+void eventpoll_init_file(struct file *file);
+
 /* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
-void ep_notify_file_close(struct file *file);
+void eventpoll_release(struct file *file);
 
 #endif /* #ifdef __KERNEL__ */
 
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/ext3_fs.h	Sun Nov 17 20:30:14 2002
@@ -17,6 +17,7 @@
 #define _LINUX_EXT3_FS_H
 
 #include <linux/types.h>
+#include <linux/ext3_fs_i.h>
 #include <linux/ext3_fs_sb.h>
 
 /*
diff -Nru a/include/linux/file.h b/include/linux/file.h
--- a/include/linux/file.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/file.h	Sun Nov 17 20:30:02 2002
@@ -41,6 +41,13 @@
 extern int get_unused_fd(void);
 extern void FASTCALL(put_unused_fd(unsigned int fd));
 
+extern struct file ** alloc_fd_array(int);
+extern int expand_fd_array(struct files_struct *, int nr);
+extern void free_fd_array(struct file **, int);
+
+extern fd_set *alloc_fdset(int);
+extern int expand_fdset(struct files_struct *, int nr);
+extern void free_fdset(fd_set *, int);
 
 static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
 {
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/fs.h	Sun Nov 17 20:30:12 2002
@@ -12,23 +12,21 @@
 #include <linux/wait.h>
 #include <linux/types.h>
 #include <linux/vfs.h>
-#include <linux/net.h>
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
 #include <linux/list.h>
 #include <linux/dcache.h>
 #include <linux/stat.h>
 #include <linux/cache.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
 #include <linux/radix-tree.h>
-#include <linux/bitops.h>
-
 #include <asm/atomic.h>
 
-struct poll_table_struct;
+struct iovec;
 struct nameidata;
-
+struct pipe_inode_info;
+struct poll_table_struct;
+struct vm_area_struct;
+struct vfsmount;
 
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
@@ -219,9 +217,6 @@
 			unsigned long max_blocks,
 			struct buffer_head *bh_result, int create);
 
-#include <linux/pipe_fs_i.h>
-/* #include <linux/umsdos_fs_i.h> */
-
 /*
  * Attribute flags.  These should be or-ed together to figure out what
  * has been changed!
@@ -255,9 +250,9 @@
 	uid_t		ia_uid;
 	gid_t		ia_gid;
 	loff_t		ia_size;
-	time_t		ia_atime;
-	time_t		ia_mtime;
-	time_t		ia_ctime;
+	struct timespec	ia_atime;
+	struct timespec	ia_mtime;
+	struct timespec	ia_ctime;
 	unsigned int	ia_attr_flags;
 };
 
@@ -271,10 +266,9 @@
 #define ATTR_FLAG_NODIRATIME	16 	/* Don't update atime for directory */
 
 /*
- * Includes for diskquotas and mount structures.
+ * Includes for diskquotas.
  */
 #include <linux/quota.h>
-#include <linux/mount.h>
 
 /*
  * oh the beauties of C type declarations.
@@ -375,9 +369,9 @@
 	gid_t			i_gid;
 	kdev_t			i_rdev;
 	loff_t			i_size;
-	time_t			i_atime;
-	time_t			i_mtime;
-	time_t			i_ctime;
+	struct timespec		i_atime;
+	struct timespec		i_mtime;
+	struct timespec		i_ctime;
 	unsigned int		i_blkbits;
 	unsigned long		i_blksize;
 	unsigned long		i_blocks;
@@ -413,25 +407,8 @@
 	} u;
 };
 
-struct socket_alloc {
-	struct socket socket;
-	struct inode vfs_inode;
-};
-
-static inline struct socket *SOCKET_I(struct inode *inode)
-{
-	return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
-}
-
-static inline struct inode *SOCK_INODE(struct socket *socket)
-{
-	return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
-}
-
 /* will die */
 #include <linux/coda_fs_i.h>
-#include <linux/ext3_fs_i.h>
-#include <linux/efs_fs_i.h>
 
 struct fown_struct {
 	rwlock_t lock;          /* protects pid, uid, euid fields */
@@ -506,6 +483,10 @@
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
+
+	/* Used by fs/eventpoll.c to link all the hooks to this file */
+	struct list_head	f_ep_links;
+	spinlock_t		f_ep_lock;
 };
 extern spinlock_t files_lock;
 #define file_list_lock() spin_lock(&files_lock);
@@ -598,7 +579,7 @@
 extern void posix_unblock_lock(struct file *, struct file_lock *);
 extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
 extern int __get_lease(struct inode *inode, unsigned int flags);
-extern time_t lease_get_mtime(struct inode *);
+extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
 
@@ -1121,10 +1102,10 @@
 extern int register_chrdev(unsigned int, const char *, struct file_operations *);
 extern int unregister_chrdev(unsigned int, const char *);
 extern int chrdev_open(struct inode *, struct file *);
-extern const char *__bdevname(kdev_t);
+extern const char *__bdevname(dev_t);
 extern inline const char *bdevname(struct block_device *bdev)
 {
-	return __bdevname(to_kdev_t(bdev->bd_dev));
+	return __bdevname(bdev->bd_dev);
 }
 extern const char * cdevname(kdev_t);
 extern const char * kdevname(kdev_t);
@@ -1337,13 +1318,10 @@
 extern unsigned int real_root_dev;
 #endif
 
-extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
-extern ssize_t block_read(struct file *, char *, size_t, loff_t *);
-extern ssize_t char_write(struct file *, const char *, size_t, loff_t *);
-extern ssize_t block_write(struct file *, const char *, size_t, loff_t *);
-
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int inode_setattr(struct inode *, struct iattr *);
+
+extern void inode_update_time(struct inode *inode, int ctime_too);
 
 static inline ino_t parent_ino(struct dentry *dentry)
 {
diff -Nru a/include/linux/fs_struct.h b/include/linux/fs_struct.h
--- a/include/linux/fs_struct.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/fs_struct.h	Sun Nov 17 20:30:15 2002
@@ -1,9 +1,8 @@
 #ifndef _LINUX_FS_STRUCT_H
 #define _LINUX_FS_STRUCT_H
-#ifdef __KERNEL__
 
-#include <linux/mount.h>
-#include <linux/dcache.h>
+struct dentry;
+struct vfsmount;
 
 struct fs_struct {
 	atomic_t count;
@@ -13,68 +12,17 @@
 	struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
 };
 
-#define INIT_FS { \
-	ATOMIC_INIT(1), \
-	RW_LOCK_UNLOCKED, \
-	0022, \
-	NULL, NULL, NULL, NULL, NULL, NULL \
+#define INIT_FS {				\
+	.count		= ATOMIC_INIT(1),	\
+	.lock		= RW_LOCK_UNLOCKED,	\
+	.umask		= 0022, \
 }
 
 extern void exit_fs(struct task_struct *);
 extern void set_fs_altroot(void);
+extern void set_fs_root(struct fs_struct *, struct vfsmount *, struct dentry *);
+extern void set_fs_pwd(struct fs_struct *, struct vfsmount *, struct dentry *);
+extern struct fs_struct *copy_fs_struct(struct fs_struct *);
+extern void put_fs_struct(struct fs_struct *);
 
-/*
- * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
- * It can block. Requires the big lock held.
- */
-
-static inline void set_fs_root(struct fs_struct *fs,
-	struct vfsmount *mnt,
-	struct dentry *dentry)
-{
-	struct dentry *old_root;
-	struct vfsmount *old_rootmnt;
-	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
-	old_root = fs->root;
-	old_rootmnt = fs->rootmnt;
-	fs->rootmnt = mntget(mnt);
-	fs->root = dget(dentry);
-	spin_unlock(&dcache_lock);
-	write_unlock(&fs->lock);
-	if (old_root) {
-		dput(old_root);
-		mntput(old_rootmnt);
-	}
-}
-
-/*
- * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
- * It can block. Requires the big lock held.
- */
-
-static inline void set_fs_pwd(struct fs_struct *fs,
-	struct vfsmount *mnt,
-	struct dentry *dentry)
-{
-	struct dentry *old_pwd;
-	struct vfsmount *old_pwdmnt;
-	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
-	old_pwd = fs->pwd;
-	old_pwdmnt = fs->pwdmnt;
-	fs->pwdmnt = mntget(mnt);
-	fs->pwd = dget(dentry);
-	spin_unlock(&dcache_lock);
-	write_unlock(&fs->lock);
-	if (old_pwd) {
-		dput(old_pwd);
-		mntput(old_pwdmnt);
-	}
-}
-
-struct fs_struct *copy_fs_struct(struct fs_struct *old);
-void put_fs_struct(struct fs_struct *fs);
-
-#endif
-#endif
+#endif /* _LINUX_FS_STRUCT_H */
diff -Nru a/include/linux/ftape.h b/include/linux/ftape.h
--- a/include/linux/ftape.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/ftape.h	Sun Nov 17 20:30:14 2002
@@ -34,7 +34,7 @@
 #define KERNEL_VER(major,minor,sublvl) (((major)<<16)+((minor)<<8)+(sublvl))
 
 #ifdef __KERNEL__
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/mm.h>
 #endif
 #include <linux/types.h>
diff -Nru a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h
--- a/include/linux/hfs_sysdep.h	Sun Nov 17 20:30:03 2002
+++ b/include/linux/hfs_sysdep.h	Sun Nov 17 20:30:03 2002
@@ -87,7 +87,7 @@
 }
 
 static inline hfs_u32 hfs_time(void) {
-	return htonl(hfs_from_utc(CURRENT_TIME)+2082844800U);
+	return htonl(hfs_from_utc(get_seconds())+2082844800U);
 }
 
 
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/hiddev.h	Sun Nov 17 20:30:12 2002
@@ -159,6 +159,7 @@
 #define HIDIOCSFLAG		_IOW('H', 0x0F, int)
 #define HIDIOCGCOLLECTIONINDEX	_IOW('H', 0x10, struct hiddev_usage_ref)
 #define HIDIOCGCOLLECTIONINFO	_IOWR('H', 0x11, struct hiddev_collection_info)
+#define HIDIOCGPHYS(len)	_IOC(_IOC_READ, 'H', 0x12, len)
 
 /* 
  * Flags to be used in HIDIOCSFLAG
diff -Nru a/include/linux/hugetlb.h b/include/linux/hugetlb.h
--- a/include/linux/hugetlb.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/hugetlb.h	Sun Nov 17 20:30:14 2002
@@ -4,6 +4,7 @@
 #ifdef CONFIG_HUGETLB_PAGE
 
 struct ctl_table;
+struct hugetlb_key;
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 {
@@ -17,6 +18,7 @@
 void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
 int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
 void huge_page_release(struct page *);
+void hugetlb_release_key(struct hugetlb_key *);
 int hugetlb_report_meminfo(char *);
 
 extern int htlbpage_max;
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/i2c.h	Sun Nov 17 20:30:04 2002
@@ -48,7 +48,6 @@
 #endif
 
 #include <asm/page.h>			/* for 2.2.xx 			*/
-#include <linux/sched.h>
 #include <asm/semaphore.h>
 #include <linux/config.h>
 
diff -Nru a/include/linux/if_pppox.h b/include/linux/if_pppox.h
--- a/include/linux/if_pppox.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/if_pppox.h	Sun Nov 17 20:30:04 2002
@@ -24,7 +24,6 @@
 #include <linux/if_ether.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
 #include <asm/semaphore.h>
 #include <linux/ppp_channel.h>
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/in.h b/include/linux/in.h
--- a/include/linux/in.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/in.h	Sun Nov 17 20:30:14 2002
@@ -70,6 +70,7 @@
 #define IP_MTU		14
 #define IP_FREEBIND	15
 #define IP_IPSEC_POLICY	16
+#define IP_XFRM_POLICY	17
 
 /* BSD compatibility */
 #define IP_RECVRETOPTS	IP_RETOPTS
diff -Nru a/include/linux/init.h b/include/linux/init.h
--- a/include/linux/init.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/init.h	Sun Nov 17 20:30:02 2002
@@ -38,17 +38,30 @@
  * Also note, that this data cannot be "const".
  */
 
-#ifndef MODULE
+/* These are for everybody (although not all archs will actually
+   discard it in modules) */
+#define __init		__attribute__ ((__section__ (".init.text")))
+#define __initdata	__attribute__ ((__section__ (".init.data")))
+#define __exit		__attribute__ ((__section__(".exit.text")))
+#define __exitdata	__attribute__ ((__section__(".exit.data")))
+#define __exit_call	__attribute__ ((unused,__section__ (".exitcall.exit")))
 
-#ifndef __ASSEMBLY__
+/* For assembly routines */
+#define __INIT		.section	".init.text","ax"
+#define __FINIT		.previous
+#define __INITDATA	.section	".init.data","aw"
 
+#ifndef __ASSEMBLY__
 /*
  * Used for initialization calls..
  */
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
+#endif
 
-extern initcall_t __initcall_start, __initcall_end;
+#ifndef MODULE
+
+#ifndef __ASSEMBLY__
 
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
@@ -70,7 +83,7 @@
 
 #define __initcall(fn) device_initcall(fn)
 
-#define __exitcall(fn)								\
+#define __exitcall(fn)							\
 	static exitcall_t __exitcall_##fn __exit_call = fn
 
 /*
@@ -83,39 +96,21 @@
 
 extern struct kernel_param __setup_start, __setup_end;
 
-#define __setup(str, fn)								\
-	static char __setup_str_##fn[] __initdata = str;				\
-	static struct kernel_param __setup_##fn __attribute__((unused)) __initsetup = { __setup_str_##fn, fn }
+#define __setup(str, fn)						\
+	static char __setup_str_##fn[] __initdata = str;		\
+	static struct kernel_param __setup_##fn				\
+		 __attribute__((unused,__section__ (".init.setup")))	\
+		= { __setup_str_##fn, fn }
 
 #endif /* __ASSEMBLY__ */
 
-/*
- * Mark functions and data as being only used at initialization
- * or exit time.
- */
-#define __init		__attribute__ ((__section__ (".init.text")))
-#define __exit		__attribute__ ((unused, __section__(".exit.text")))
-#define __initdata	__attribute__ ((__section__ (".init.data")))
-#define __exitdata	__attribute__ ((unused, __section__ (".exit.data")))
-#define __initsetup	__attribute__ ((unused,__section__ (".init.setup")))
-#define __init_call(level)  __attribute__ ((unused,__section__ (".initcall" level ".init")))
-#define __exit_call	__attribute__ ((unused,__section__ (".exitcall.exit")))
-
-/* For assembly routines */
-#define __INIT		.section	".init.text","ax"
-#define __FINIT		.previous
-#define __INITDATA	.section	".init.data","aw"
-
 /**
  * module_init() - driver initialization entry point
  * @x: function to be run at kernel boot time or module insertion
  * 
- * module_init() will add the driver initialization routine in
- * the "__initcall.int" code segment if the driver is checked as
- * "y" or static, or else it will wrap the driver initialization
- * routine with init_module() which is used by insmod and
- * modprobe when the driver is used as a module.
- */
+ * module_init() will either be called during do_initcalls (if
+ * builtin) or at module insertion time (if a module).  There can only
+ * be one per module. */
 #define module_init(x)	__initcall(x);
 
 /**
@@ -126,39 +121,21 @@
  * with cleanup_module() when used with rmmod when
  * the driver is a module.  If the driver is statically
  * compiled into the kernel, module_exit() has no effect.
+ * There can only be one per module.
  */
 #define module_exit(x)	__exitcall(x);
 
-#else
-
-#define __init
-#define __exit
-#define __initdata
-#define __exitdata
-#define __initcall(fn)
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-
-/* These macros create a dummy inline: gcc 2.9x does not count alias
- as usage, hence the `unused function' warning when __init functions
- are declared static. We use the dummy __*_module_inline functions
- both to kill the warning and check the type of the init/cleanup
- function. */
-typedef int (*__init_module_func_t)(void);
-typedef void (*__cleanup_module_func_t)(void);
-#define module_init(x) \
-	int init_module(void) __attribute__((alias(#x))); \
-	static inline __init_module_func_t __init_module_inline(void) \
-	{ return x; }
-#define module_exit(x) \
-	void cleanup_module(void) __attribute__((alias(#x))); \
-	static inline __cleanup_module_func_t __cleanup_module_inline(void) \
-	{ return x; }
+/**
+ * no_module_init - code needs no initialization.
+ *
+ * The equivalent of declaring an empty init function which returns 0.
+ * Every module must have exactly one module_init() or no_module_init
+ * invocation.  */
+#define no_module_init
 
-#define __setup(str,func) /* nothing */
+#else /* MODULE */
 
+/* Don't use these in modules, but some people do... */
 #define core_initcall(fn)		module_init(fn)
 #define postcore_initcall(fn)		module_init(fn)
 #define arch_initcall(fn)		module_init(fn)
@@ -167,6 +144,34 @@
 #define device_initcall(fn)		module_init(fn)
 #define late_initcall(fn)		module_init(fn)
 
+/* Each module knows its own name. */
+#define __DEFINE_MODULE_NAME						\
+	char __module_name[] __attribute__((section(".modulename"))) =	\
+	__stringify(KBUILD_MODNAME)
+
+/* These macros create a dummy inline: gcc 2.9x does not count alias
+ as usage, hence the `unused function' warning when __init functions
+ are declared static. We use the dummy __*_module_inline functions
+ both to kill the warning and check the type of the init/cleanup
+ function. */
+
+/* Each module must use one module_init(), or one no_module_init */
+#define module_init(initfn)					\
+	__DEFINE_MODULE_NAME;					\
+	static inline initcall_t __inittest(void)		\
+	{ return initfn; }					\
+	int __initfn(void) __attribute__((alias(#initfn)));
+
+#define no_module_init __DEFINE_MODULE_NAME
+
+/* This is only required if you want to be unloadable. */
+#define module_exit(exitfn)					\
+	static inline exitcall_t __exittest(void)		\
+	{ return exitfn; }					\
+	void __exitfn(void) __attribute__((alias(#exitfn)));
+
+
+#define __setup(str,func) /* nothing */
 #endif
 
 /* Data marked not to be saved by software_suspend() */
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	Sun Nov 17 20:30:13 2002
+++ b/include/linux/input.h	Sun Nov 17 20:30:13 2002
@@ -734,8 +734,9 @@
  * In-kernel definitions.
  */
 
-#include <linux/sched.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
 
 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
 #define BIT(x)	(1UL<<((x)%BITS_PER_LONG))
diff -Nru a/include/linux/intermezzo_fs.h b/include/linux/intermezzo_fs.h
--- a/include/linux/intermezzo_fs.h	Sun Nov 17 20:30:13 2002
+++ b/include/linux/intermezzo_fs.h	Sun Nov 17 20:30:13 2002
@@ -54,6 +54,7 @@
 #ifdef __KERNEL__
 # include <linux/smp.h>
 # include <linux/fsfilter.h>
+# include <linux/mount.h>
 # include <linux/slab.h>
 # include <linux/vmalloc.h>
 # include <linux/smp_lock.h>
diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h
--- a/include/linux/interrupt.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/interrupt.h	Sun Nov 17 20:30:14 2002
@@ -3,15 +3,11 @@
 #define _LINUX_INTERRUPT_H
 
 #include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/cache.h>
 #include <linux/bitops.h>
-
 #include <asm/atomic.h>
-#include <asm/system.h>
+#include <asm/hardirq.h>
 #include <asm/ptrace.h>
+#include <asm/softirq.h>
 
 struct irqaction {
 	void (*handler)(int, void *, struct pt_regs *);
@@ -22,8 +18,10 @@
 	struct irqaction *next;
 };
 
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
+extern int request_irq(unsigned int,
+		       void (*handler)(int, void *, struct pt_regs *),
+		       unsigned long, const char *, void *);
+extern void free_irq(unsigned int, void *);
 
 /*
  * Temporary defines for UP kernels, until all code gets fixed.
@@ -46,6 +44,7 @@
 enum
 {
 	HI_SOFTIRQ=0,
+	TIMER_SOFTIRQ,
 	NET_TX_SOFTIRQ,
 	NET_RX_SOFTIRQ,
 	SCSI_SOFTIRQ,
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/kernel.h	Sun Nov 17 20:30:02 2002
@@ -102,10 +102,11 @@
 #define TAINT_PROPRIETORY_MODULE	(1<<0)
 #define TAINT_FORCED_MODULE		(1<<1)
 #define TAINT_UNSAFE_SMP		(1<<2)
+#define TAINT_FORCED_RMMOD		(1<<3)
 
 extern void dump_stack(void);
 
-#if DEBUG
+#ifdef DEBUG
 #define pr_debug(fmt,arg...) \
 	printk(KERN_DEBUG fmt,##arg)
 #else
diff -Nru a/include/linux/kmod.h b/include/linux/kmod.h
--- a/include/linux/kmod.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/kmod.h	Sun Nov 17 20:30:04 2002
@@ -28,6 +28,7 @@
 static inline int request_module(const char * name) { return -ENOSYS; }
 #endif
 
+#define try_then_request_module(x, mod) ((x) ?: request_module(mod), (x))
 extern int exec_usermodehelper(char *program_path, char *argv[], char *envp[]);
 extern int call_usermodehelper(char *path, char *argv[], char *envp[]);
 
diff -Nru a/include/linux/lockd/debug.h b/include/linux/lockd/debug.h
--- a/include/linux/lockd/debug.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/lockd/debug.h	Sun Nov 17 20:30:15 2002
@@ -28,10 +28,6 @@
 # define ifdebug(flag)		if (0)
 #endif
 
-#ifdef LOCKD_DEBUG
-char *		  nlm_procname(u32);
-#endif
-
 #endif /* __KERNEL__ */
 
 /*
diff -Nru a/include/linux/logibusmouse.h b/include/linux/logibusmouse.h
--- a/include/linux/logibusmouse.h	Sun Nov 17 20:30:14 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,104 +0,0 @@
-#ifndef _LINUX_BUSMOUSE_H
-#define _LINUX_BUSMOUSE_H
-
-/*
- * linux/include/linux/busmouse.h: header file for Logitech Bus Mouse driver
- * by James Banks
- *
- * based on information gleamed from various mouse drivers on the net
- *
- * Heavily modified by David giller (rafetmad@oxy.edu)
- *
- * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
- * gt7080a@prism.gatech.edu (13JUL92)
- *
- * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
- *
- * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
- *    8/28/92
- *
- * Microsoft Bus Mouse support folded into 0.97pl4 code
- *    by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
- * Changes:  Logitech and Microsoft support in the same kernel.
- *           Defined new constants in busmouse.h for MS mice.
- *           Added int mse_busmouse_type to distinguish busmouse types
- *           Added a couple of new functions to handle differences in using
- *             MS vs. Logitech (where the int variable wasn't appropriate).
- *
- */
-
-#define MOUSE_IRQ		5
-#define LOGITECH_BUSMOUSE       0   /* Minor device # for Logitech  */
-#define MICROSOFT_BUSMOUSE      2   /* Minor device # for Microsoft */
-
-/*--------- LOGITECH BUSMOUSE ITEMS -------------*/
-
-#define	LOGIBM_BASE		0x23c
-#define	MSE_DATA_PORT		0x23c
-#define	MSE_SIGNATURE_PORT	0x23d
-#define	MSE_CONTROL_PORT	0x23e
-#define	MSE_INTERRUPT_PORT	0x23e
-#define	MSE_CONFIG_PORT		0x23f
-#define	LOGIBM_EXTENT		0x4
-
-#define	MSE_ENABLE_INTERRUPTS	0x00
-#define	MSE_DISABLE_INTERRUPTS	0x10
-
-#define	MSE_READ_X_LOW		0x80
-#define	MSE_READ_X_HIGH		0xa0
-#define	MSE_READ_Y_LOW		0xc0
-#define	MSE_READ_Y_HIGH		0xe0
-
-/* Magic number used to check if the mouse exists */
-#define MSE_CONFIG_BYTE		0x91
-#define MSE_DEFAULT_MODE	0x90
-#define MSE_SIGNATURE_BYTE	0xa5
-
-/* useful Logitech Mouse macros */
-
-#define MSE_INT_OFF()	outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
-#define MSE_INT_ON()	outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
-
-/*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
-
-#define	MSBM_BASE			0x23d
-#define	MS_MSE_DATA_PORT	        0x23d
-#define	MS_MSE_SIGNATURE_PORT	        0x23e
-#define	MS_MSE_CONTROL_PORT	        0x23c
-#define	MS_MSE_CONFIG_PORT		0x23f
-#define	MSBM_EXTENT			0x3
-
-#define	MS_MSE_ENABLE_INTERRUPTS	0x11
-#define	MS_MSE_DISABLE_INTERRUPTS	0x10
-
-#define	MS_MSE_READ_BUTTONS             0x00
-#define	MS_MSE_READ_X		        0x01
-#define	MS_MSE_READ_Y                   0x02
-
-#define MS_MSE_START                    0x80
-#define MS_MSE_COMMAND_MODE             0x07
-
-/* useful microsoft busmouse macros */
-
-#define MS_MSE_INT_OFF() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
-			    outb(MS_MSE_DISABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
-#define MS_MSE_INT_ON()  {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
-			    outb(MS_MSE_ENABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
-
- 
-struct mouse_status {
-	unsigned char	buttons;
-	unsigned char	latch_buttons;
-	int		dx;
-	int		dy;	
-	int 		present;
-	int		ready;
-	int		active;
-	wait_queue_head_t wait;
-	struct fasync_struct *fasyncptr;
-};
-
-/* Function Prototypes */
-
-#endif
-
diff -Nru a/include/linux/major.h b/include/linux/major.h
--- a/include/linux/major.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/major.h	Sun Nov 17 20:30:12 2002
@@ -33,6 +33,7 @@
 #define MD_MAJOR        9
 #define MISC_MAJOR	10
 #define SCSI_CDROM_MAJOR 11
+#define MUX_MAJOR	11	/* PA-RISC only */
 #define QIC02_TAPE_MAJOR 12
 #define XT_DISK_MAJOR	13
 #define SOUND_MAJOR	14
diff -Nru a/include/linux/mbcache.h b/include/linux/mbcache.h
--- a/include/linux/mbcache.h	Sun Nov 17 20:30:16 2002
+++ b/include/linux/mbcache.h	Sun Nov 17 20:30:16 2002
@@ -10,7 +10,7 @@
 struct mb_cache_entry;
 
 struct mb_cache_op {
-	void (*free)(struct mb_cache_entry *);
+	int (*free)(struct mb_cache_entry *, int);
 };
 
 struct mb_cache {
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/module.h	Sun Nov 17 20:30:15 2002
@@ -1,535 +1,290 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
 /*
  * Dynamic loading of modules into the kernel.
  *
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
+ * Rewritten again by Rusty Russell, 2002
  */
-
-#ifndef _LINUX_MODULE_H
-#define _LINUX_MODULE_H
-
 #include <linux/config.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
-#include <linux/errno.h>
-
-#include <asm/atomic.h>
-
-/* Don't need to bring in all of uaccess.h just for this decl.  */
-struct exception_table_entry;
-
-/* Used by get_kernel_syms, which is obsolete.  */
-struct kernel_sym
-{
-	unsigned long value;
-	char name[60];		/* should have been 64-sizeof(long); oh well */
-};
-
-struct module_symbol
-{
-	unsigned long value;
-	const char *name;
-};
-
-struct module_ref
-{
-	struct module *dep;	/* "parent" pointer */
-	struct module *ref;	/* "child" pointer */
-	struct module_ref *next_ref;
-};
-
-/* TBD */
-struct module_persist;
-
-struct module
-{
-	unsigned long size_of_struct;	/* == sizeof(module) */
-	struct module *next;
-	const char *name;
-	unsigned long size;
-
-	union
-	{
-		atomic_t usecount;
-		long pad;
-	} uc;				/* Needs to keep its size - so says rth */
-
-	unsigned long flags;		/* AUTOCLEAN et al */
-
-	unsigned nsyms;
-	unsigned ndeps;
-
-	struct module_symbol *syms;
-	struct module_ref *deps;
-	struct module_ref *refs;
-	int (*init)(void);
-	void (*cleanup)(void);
-	const struct exception_table_entry *ex_table_start;
-	const struct exception_table_entry *ex_table_end;
-#ifdef __alpha__
-	unsigned long gp;
-#endif
-	/* Members past this point are extensions to the basic
-	   module support and are optional.  Use mod_member_present()
-	   to examine them.  */
-	const struct module_persist *persist_start;
-	const struct module_persist *persist_end;
-	int (*can_unload)(void);
-	int runsize;			/* In modutils, not currently used */
-	const char *kallsyms_start;	/* All symbols for kernel debugging */
-	const char *kallsyms_end;
-	const char *archdata_start;	/* arch specific data for module */
-	const char *archdata_end;
-	const char *kernel_data;	/* Reserved for kernel internal use */
-};
-
-struct module_info
-{
-	unsigned long addr;
-	unsigned long size;
-	unsigned long flags;
-	long usecount;
-};
-
-/* Bits of module.flags.  */
-
-#define MOD_UNINITIALIZED	0
-#define MOD_RUNNING		1
-#define MOD_DELETED		2
-#define MOD_AUTOCLEAN		4
-#define MOD_VISITED  		8
-#define MOD_USED_ONCE		16
-#define MOD_JUST_FREED		32
-#define MOD_INITIALIZING	64
-
-/* Values for query_module's which.  */
-
-#define QM_MODULES	1
-#define QM_DEPS		2
-#define QM_REFS		3
-#define QM_SYMBOLS	4
-#define QM_INFO		5
-
-/* Can the module be queried? */
-#define MOD_CAN_QUERY(mod) (((mod)->flags & (MOD_RUNNING | MOD_INITIALIZING)) && !((mod)->flags & MOD_DELETED))
-
-/* When struct module is extended, we must test whether the new member
-   is present in the header received from insmod before we can use it.  
-   This function returns true if the member is present.  */
-
-#define mod_member_present(mod,member) 					\
-	((unsigned long)(&((struct module *)0L)->member + 1)		\
-	 <= (mod)->size_of_struct)
-
-/*
- * Ditto for archdata.  Assumes mod->archdata_start and mod->archdata_end
- * are validated elsewhere.
- */
-#define mod_archdata_member_present(mod, type, member)			\
-	(((unsigned long)(&((type *)0L)->member) +			\
-	  sizeof(((type *)0L)->member)) <=				\
-	 ((mod)->archdata_end - (mod)->archdata_start))
-	 
-
-/* Check if an address p with number of entries n is within the body of module m */
-#define mod_bound(p, n, m) ((unsigned long)(p) >= ((unsigned long)(m) + ((m)->size_of_struct)) && \
-	         (unsigned long)((p)+(n)) <= (unsigned long)(m) + (m)->size)
-
-/* Backwards compatibility definition.  */
-
-#define GET_USE_COUNT(module)	(atomic_read(&(module)->uc.usecount))
-
-/* Poke the use count of a module.  */
-
-#define __MOD_INC_USE_COUNT(mod)					\
-	(atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE)
-#define __MOD_DEC_USE_COUNT(mod)					\
-	(atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED)
-#define __MOD_IN_USE(mod)						\
-	(mod_member_present((mod), can_unload) && (mod)->can_unload	\
-	 ? (mod)->can_unload() : atomic_read(&(mod)->uc.usecount))
-
-/* Indirect stringification.  */
+#include <linux/stat.h>
+#include <linux/compiler.h>
+#include <linux/cache.h>
+#include <linux/kmod.h>
+#include <asm/module.h>
+#include <asm/uaccess.h> /* For struct exception_table_entry */
 
+/* Indirect stringification */
 #define __MODULE_STRING_1(x)	#x
 #define __MODULE_STRING(x)	__MODULE_STRING_1(x)
 
-/* Generic inter module communication.
- *
- * NOTE: This interface is intended for small amounts of data that are
- *       passed between two objects and either or both of the objects
- *       might be compiled as modules.  Do not over use this interface.
- *
- *       If more than two objects need to communicate then you probably
- *       need a specific interface instead of abusing this generic
- *       interface.  If both objects are *always* built into the kernel
- *       then a global extern variable is good enough, you do not need
- *       this interface.
- *
- * Keith Owens <kaos@ocs.com.au> 28 Oct 2000.
- */
-
-#ifdef __KERNEL__
-#define HAVE_INTER_MODULE
-extern void inter_module_register(const char *, struct module *, const void *);
-extern void inter_module_unregister(const char *);
-extern const void *inter_module_get(const char *);
-extern const void *inter_module_get_request(const char *, const char *);
-extern void inter_module_put(const char *);
-
-struct inter_module_entry {
-	struct list_head list;
-	const char *im_name;
-	struct module *owner;
-	const void *userdata;
-};
-
-extern int try_inc_mod_count(struct module *mod);
-#endif /* __KERNEL__ */
-
-#if defined(MODULE) && !defined(__GENKSYMS__)
-
-/* Embedded module documentation macros.  */
-
-/* For documentation purposes only.  */
-
-#define MODULE_AUTHOR(name)						   \
-const char __module_author[] __attribute__((section(".modinfo"))) = 	   \
-"author=" name
-
-#define MODULE_DESCRIPTION(desc)					   \
-const char __module_description[] __attribute__((section(".modinfo"))) =   \
-"description=" desc
-
-/* Could potentially be used by kmod...  */
-
-#define MODULE_SUPPORTED_DEVICE(dev)					   \
-const char __module_device[] __attribute__((section(".modinfo"))) = 	   \
-"device=" dev
-
-/* Used to verify parameters given to the module.  The TYPE arg should
-   be a string in the following format:
-   	[min[-max]]{b,h,i,l,s}
-   The MIN and MAX specifiers delimit the length of the array.  If MAX
-   is omitted, it defaults to MIN; if both are omitted, the default is 1.
-   The final character is a type specifier:
-	b	byte
-	h	short
-	i	int
-	l	long
-	s	string
-*/
-
-#define MODULE_PARM(var,type)			\
-const char __module_parm_##var[]		\
-__attribute__((section(".modinfo"))) =		\
-"parm_" __MODULE_STRING(var) "=" type
-
-#define MODULE_PARM_DESC(var,desc)		\
-const char __module_parm_desc_##var[]		\
-__attribute__((section(".modinfo"))) =		\
-"parm_desc_" __MODULE_STRING(var) "=" desc
-
-/*
- * MODULE_DEVICE_TABLE exports information about devices
- * currently supported by this module.  A device type, such as PCI,
- * is a C-like identifier passed as the first arg to this macro.
- * The second macro arg is the variable containing the device
- * information being made public.
- *
- * The following is a list of known device types (arg 1),
- * and the C types which are to be passed as arg 2.
- * pci - struct pci_device_id - List of PCI ids supported by this module
- * isapnp - struct isapnp_device_id - List of ISA PnP ids supported by this module
- * usb - struct usb_device_id - List of USB ids supported by this module
- */
-#define MODULE_GENERIC_TABLE(gtype,name)	\
-static const unsigned long __module_##gtype##_size \
-  __attribute__ ((unused)) = sizeof(struct gtype##_id); \
-static const struct gtype##_id * __module_##gtype##_table \
-  __attribute__ ((unused)) = name
-
-/*
- * The following license idents are currently accepted as indicating free
- * software modules
- *
- *	"GPL"				[GNU Public License v2 or later]
- *	"GPL v2"			[GNU Public License v2]
- *	"GPL and additional rights"	[GNU Public License v2 rights and more]
- *	"Dual BSD/GPL"			[GNU Public License v2 or BSD license choice]
- *	"Dual MPL/GPL"			[GNU Public License v2 or Mozilla license choice]
- *
- * The following other idents are available
- *
- *	"Proprietary"			[Non free products]
- *
- * There are dual licensed components, but when running with Linux it is the
- * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
- * is a GPL combined work.
- *
- * This exists for several reasons
- * 1.	So modinfo can show license info for users wanting to vet their setup 
- *	is free
- * 2.	So the community can ignore bug reports including proprietary modules
- * 3.	So vendors can do likewise based on their own policies
- */
- 
-#define MODULE_LICENSE(license) 	\
-static const char __module_license[]	\
-  __attribute__((section(".modinfo"), unused)) = "license=" license
-
-/* Define the module variable, and usage macros.  */
-extern struct module __this_module;
-
-#define THIS_MODULE		(&__this_module)
-#define MOD_INC_USE_COUNT	__MOD_INC_USE_COUNT(THIS_MODULE)
-#define MOD_DEC_USE_COUNT	__MOD_DEC_USE_COUNT(THIS_MODULE)
-#define MOD_IN_USE		__MOD_IN_USE(THIS_MODULE)
-
-#include <linux/version.h>
-static const char __module_kernel_version[]
-  __attribute__((section(".modinfo"), unused)) =
-  "kernel_version=" UTS_RELEASE;
-#ifdef CONFIG_MODVERSIONS
-static const char __module_using_checksums[]
-  __attribute__((section(".modinfo"), unused)) =
-  "using_checksums=1";
-#endif
-
-#else /* MODULE */
-
+/* Not Yet Implemented */
+#define MODULE_LICENSE(name)
 #define MODULE_AUTHOR(name)
-#define MODULE_LICENSE(license)
 #define MODULE_DESCRIPTION(desc)
 #define MODULE_SUPPORTED_DEVICE(name)
-#define MODULE_PARM(var,type)
+#define MODULE_GENERIC_TABLE(gtype,name)
+#define MODULE_DEVICE_TABLE(type,name)
 #define MODULE_PARM_DESC(var,desc)
+#define print_symbol(format, addr)
+#define print_modules()
 
-/* Create a dummy reference to the table to suppress gcc unused warnings.  Put
- * the reference in the .data.exit section which is discarded when code is built
- * in, so the reference does not bloat the running kernel.  Note: cannot be
- * const, other exit data may be writable.
- */
-#define MODULE_GENERIC_TABLE(gtype,name) \
-static const struct gtype##_id * __module_##gtype##_table \
-  __attribute__ ((unused, __section__(".exit.data"))) = name
-
-#ifndef __GENKSYMS__
-
-#define THIS_MODULE		NULL
-#define MOD_INC_USE_COUNT	do { } while (0)
-#define MOD_DEC_USE_COUNT	do { } while (0)
-#define MOD_IN_USE		1
-
-#endif /* !__GENKSYMS__ */
-
-#endif /* MODULE */
+#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
+struct kernel_symbol
+{
+	unsigned long value;
+	char name[MODULE_NAME_LEN];
+};
 
-#define MODULE_DEVICE_TABLE(type,name)		\
-  MODULE_GENERIC_TABLE(type##_device,name)
+#ifdef MODULE
+/* This is magically filled in by the linker, but THIS_MODULE must be
+   a constant so it works in initializers. */
+extern struct module __this_module;
+#define THIS_MODULE (&__this_module)
+#else
+#define THIS_MODULE ((struct module *)0)
+#endif
 
-/* Export a symbol either from the kernel or a module.
+#ifdef CONFIG_MODULES
+/* Get/put a kernel symbol (calls must be symmetric) */
+void *__symbol_get(const char *symbol);
+void *__symbol_get_gpl(const char *symbol);
+#define symbol_get(x) ((typeof(&x))(__symbol_get(#x)))
+
+/* For every exported symbol, place a struct in the __ksymtab section */
+#define EXPORT_SYMBOL(sym)				\
+	const struct kernel_symbol __ksymtab_##sym	\
+	__attribute__((section("__ksymtab")))		\
+	= { (unsigned long)&sym, #sym }
 
-   In the kernel, the symbol is added to the kernel's global symbol table.
+#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym) EXPORT_SYMBOL(sym)
 
-   In a module, it controls which variables are exported.  If no
-   variables are explicitly exported, the action is controled by the
-   insmod -[xX] flags.  Otherwise, only the variables listed are exported.
-   This obviates the need for the old register_symtab() function.  */
+struct kernel_symbol_group
+{
+	/* Links us into the global symbol list */
+	struct list_head list;
 
-/* So how does the CONFIG_MODVERSIONS magic work? 
- *
- * A module can only be loaded if it's undefined symbols can be resolved
- * using symbols the kernel exports for that purpose. The idea behind
- * CONFIG_MODVERSIONS is to mangle those symbols depending on their
- * definition (see man genksyms) - a change in the definition will thus
- * caused the mangled name to change, and the module will refuse to
- * load due to unresolved symbols.
- *
- * Let's start with taking a look how things work when we don't use
- * CONFIG_MODVERSIONS. In this case, the only thing which is worth
- * mentioning is the EXPORT_SYMBOL() macro. Using EXPORT_SYMBOL(foo)
- * will expand into __EXPORT_SYMBOL(foo, "foo"), which then uses
- * some ELF section magic to generate a list of pairs 
- * (address, symbol_name), which is used to resolve undefined 
- * symbols into addresses when loading a module.
- * 
- * That's easy. Let's get back to CONFIG_MODVERSIONS=y.
- *
- * The first step is to generate the checksums. This is done at
- * "make dep" time, code which exports symbols (using EXPORT_SYMTAB)
- * is preprocessed with the additional macro __GENKSYMS__ set and fed
- * into genksyms.
- * At this stage, for each file that exports symbols an corresponding
- * file in include/linux/module is generated, which for each exported
- * symbol contains
- *
- *         #define __ver_schedule_task     2d6c3d04
- *         #define schedule_task   _set_ver(schedule_task)
- *
- * In addition, include/linux/modversions.h is generated, which
- * looks like
- *
- *         #include <linux/modsetver.h>
- *         #include <linux/modules/kernel__context.ver>
- *        <<<lists all of the files just described>>>
- *
- * Let's see what happens for different cases during compilation.
- *
- * o compile a file into the kernel which does not export symbols:
- *
- *   Since the file is known to not export symbols (it's not listed
- *   in the export-objs variable in the corresponding Makefile), the
- *   kernel build system does compile it with no extra flags set.
- *   The macro EXPORT_SYMTAB is unset, and you can see below that
- *   files which still try to use EXPORT_SYMBOL() will be trapped.
- *   Other than that, just regular compilation.
- *
- * o compile a file into the kernel which does export symbols:
- *
- *   In this case, the file will compiled with the macro 
- *   EXPORT_SYMTAB defined.
- *   As MODULE is not set, we hit this case from below:
- *
- *         #define _set_ver(sym) sym
- *         #include <linux/modversions.h>
- *         
- *         #define EXPORT_SYMBOL(var) \
- *          __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
- *
- *   The first two lines will in essence include
- *
- *         #define __ver_schedule_task     2d6c3d04
- *         #define schedule_task   schedule_task
- *
- *   for each symbol. The second line really doesn't do much, but the
- *   first one gives us the checksums we generated before.
- *   
- *   So EXPORT_SYMBOL(schedule_task) will expand into
- *   __EXPORT_SYMBOL(schedule_task, "schedule_task_R2d6c3d04"),
- *   hence exporting the symbol for schedule_task under the name of
- *   schedule_task_R2d6c3d04.
- *
- * o compile a file into a module
- *   
- *   In this case, the kernel build system will add 
- *   "-include include/linux/modversions.h" to the command line. So
- *   modversions.h is prepended to the actual source, turning into
- *
- *         #define __ver_schedule_task     2d6c3d04
- *         #define schedule_task   schedule_task_R2d6c3d04
- *
- *   Though the source code says "schedule_task", the compiler will
- *   see the mangled symbol everywhere. So the module will end up with
- *   an undefined symbol "schedule_task_R2d6c3d04" - which is exactly
- *   the symbols which occurs in the kernel's list of symbols, with
- *   a value of &schedule_task - it all comes together nicely.
- *
- *   One question remains: What happens if a module itself exports
- *   a symbol - the answer is simple: It's actually handled as the
- *   CONFIG_MODVERSIONS=n case described first, only that the compiler
- *   sees the mangled symbol everywhere. So &foo_R12345678 is exported
- *   with the name "foo_R12345678". Think about it. It all makes sense.
- */
+	/* Module which owns it (if any) */
+	struct module *owner;
 
-#if defined(__GENKSYMS__)
+	unsigned int num_syms;
+	const struct kernel_symbol *syms;
+};
 
-/* We want the EXPORT_SYMBOL tag left intact for recognition.  */
+struct exception_table
+{
+	struct list_head list;
 
-#elif !defined(CONFIG_MODULES)
+	unsigned int num_entries;
+	const struct exception_table_entry *entry;
+};
 
-#define __EXPORT_SYMBOL(sym,str)
-#define EXPORT_SYMBOL(var)
-#define EXPORT_SYMBOL_NOVERS(var)
-#define EXPORT_SYMBOL_GPL(var)
+struct module_ref
+{
+	atomic_t count;
+} ____cacheline_aligned;
 
-#elif !defined(EXPORT_SYMTAB)
+struct module
+{
+	/* Am I live (yet)? */
+	int live;
 
-#define __EXPORT_SYMBOL(sym,str)   error this_object_must_be_defined_as_export_objs_in_the_Makefile
-#define EXPORT_SYMBOL(var)	   error this_object_must_be_defined_as_export_objs_in_the_Makefile
-#define EXPORT_SYMBOL_NOVERS(var)  error this_object_must_be_defined_as_export_objs_in_the_Makefile
-#define EXPORT_SYMBOL_GPL(var)  error this_object_must_be_defined_as_export_objs_in_the_Makefile
+	/* Member of list of modules */
+	struct list_head list;
 
-#else
+	/* Unique handle for this module */
+	char name[MODULE_NAME_LEN];
 
-#define __EXPORT_SYMBOL(sym, str)			\
-const char __kstrtab_##sym[]				\
-__attribute__((section(".kstrtab"))) = str;		\
-const struct module_symbol __ksymtab_##sym 		\
-__attribute__((section("__ksymtab"))) =			\
-{ (unsigned long)&sym, __kstrtab_##sym }
+	/* Exported symbols */
+	struct kernel_symbol_group symbols;
 
-#define __EXPORT_SYMBOL_GPL(sym, str)			\
-const char __kstrtab_##sym[]				\
-__attribute__((section(".kstrtab"))) = "GPLONLY_" str;	\
-const struct module_symbol __ksymtab_##sym		\
-__attribute__((section("__ksymtab"))) =			\
-{ (unsigned long)&sym, __kstrtab_##sym }
+	/* Exception tables */
+	struct exception_table extable;
 
-#if defined(CONFIG_MODVERSIONS) && !defined(MODULE)
+	/* Startup function. */
+	int (*init)(void);
 
-#define _set_ver(sym) sym
-#include <linux/modversions.h>
+	/* If this is non-NULL, vfree after init() returns */
+	void *module_init;
 
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
-#define EXPORT_SYMBOL_GPL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
+	/* Here is the actual code + data, vfree'd on unload. */
+	void *module_core;
 
-#else /* !defined (CONFIG_MODVERSIONS) || defined(MODULE) */
+	/* Here are the sizes of the init and core sections */
+	unsigned long init_size, core_size;
 
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-#define EXPORT_SYMBOL_GPL(var)  __EXPORT_SYMBOL_GPL(var, __MODULE_STRING(var))
+	/* Arch-specific module values */
+	struct mod_arch_specific arch;
 
-#endif /* defined(CONFIG_MODVERSIONS) && !defined(MODULE) */
+	/* Am I unsafe to unload? */
+	int unsafe;
 
-#define EXPORT_SYMBOL_NOVERS(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+#ifdef CONFIG_MODULE_UNLOAD
+	/* Reference counts */
+	struct module_ref ref[NR_CPUS];
 
-#endif /* __GENKSYMS__ */
+	/* What modules depend on me? */
+	struct list_head modules_which_use_me;
 
-/* 
- * Force a module to export no symbols.
- * EXPORT_NO_SYMBOLS is default now, leave the define around for sources
- * which still have it
- */
-#define EXPORT_NO_SYMBOLS
+	/* Who is waiting for us to be unloaded */
+	struct task_struct *waiter;
 
-#ifdef CONFIG_MODULES
-/* 
- * Always allocate a section "__ksymtab". If we encounter EXPORT_SYMBOL,
- * the exported symbol will be added to it.
- * If it remains empty, that tells modutils that we do not want to
- * export any symbols (as opposed to it not being present, which means
- * "export all symbols" to modutils)
- */
-__asm__(".section __ksymtab,\"a\"\n.previous");
+	/* Destruction function. */
+	void (*exit)(void);
 #endif
 
-#ifdef CONFIG_MODULES
-#define SET_MODULE_OWNER(some_struct) do { (some_struct)->owner = THIS_MODULE; } while (0)
-#else
-#define SET_MODULE_OWNER(some_struct) do { } while (0)
-#endif
+	/* The command line arguments (may be mangled).  People like
+	   keeping pointers to this stuff */
+	char args[0];
+};
 
-extern void print_modules(void);
+#ifdef CONFIG_MODULE_UNLOAD
 
-#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+void __symbol_put(const char *symbol);
+#define symbol_put(x) __symbol_put(#x)
+void symbol_put_addr(void *addr);
+
+/* We only need protection against local interrupts. */
+#ifndef __HAVE_ARCH_LOCAL_INC
+#define local_inc(x) atomic_inc(x)
+#define local_dec(x) atomic_dec(x)
+#endif
 
-extern struct module *module_list;
+static inline int try_module_get(struct module *module)
+{
+	int ret = 1;
 
-/*
- * print_symbols takes a format string containing one %s.
- * If support for resolving symbols is compiled in, the %s will
- * be replaced by the closest symbol to the address and the entire
- * string is printk()ed. Otherwise, nothing is printed.
- */
-extern void print_symbol(const char *fmt, unsigned long address);
+	if (module) {
+		unsigned int cpu = get_cpu();
+		if (likely(module->live))
+			local_inc(&module->ref[cpu].count);
+		else
+			ret = 0;
+		put_cpu();
+	}
+	return ret;
+}
 
-#else
+static inline void module_put(struct module *module)
+{
+	if (module) {
+		unsigned int cpu = get_cpu();
+		local_dec(&module->ref[cpu].count);
+		/* Maybe they're waiting for us to drop reference? */
+		if (unlikely(!module->live))
+			wake_up_process(module->waiter);
+		put_cpu();
+	}
+}
 
-static inline int
-print_symbol(const char *fmt, unsigned long address)
+#else /*!CONFIG_MODULE_UNLOAD*/
+static inline int try_module_get(struct module *module)
 {
-	return -ESRCH;
+	return !module || module->live;
 }
+static inline void module_put(struct module *module)
+{
+}
+#define symbol_put(x) do { } while(0)
+#define symbol_put_addr(p) do { } while(0)
 
+#endif /* CONFIG_MODULE_UNLOAD */
+
+/* This is a #define so the string doesn't get put in every .o file */
+#define module_name(mod)			\
+({						\
+	struct module *__mod = (mod);		\
+	__mod ? __mod->name : "kernel";		\
+})
+
+#define __unsafe(mod)							     \
+do {									     \
+	if (mod && !(mod)->unsafe) {					     \
+		printk(KERN_WARNING					     \
+		       "Module %s cannot be unloaded due to unsafe usage in" \
+		       " %s:%u\n", (mod)->name, __FILE__, __LINE__);	     \
+		(mod)->unsafe = 1;					     \
+	}								     \
+} while(0)
+
+#else /* !CONFIG_MODULES... */
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+#define EXPORT_SYMBOL_NOVERS(sym)
+
+/* Get/put a kernel symbol (calls should be symmetric) */
+#define symbol_get(x) (&(x))
+#define symbol_put(x) do { } while(0)
+#define symbol_put_addr(x) do { } while(0)
+
+#define try_module_get(module) 1
+#define module_put(module) do { } while(0)
+
+#define module_name(mod) "kernel"
+
+#define __unsafe(mod)
+#endif /* CONFIG_MODULES */
+
+/* For archs to search exception tables */
+extern struct list_head extables;
+extern spinlock_t modlist_lock;
+
+#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
+
+/* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
+#define __MOD_INC_USE_COUNT(mod) \
+	do { __unsafe(mod); (void)try_module_get(mod); } while(0)
+#define __MOD_DEC_USE_COUNT(mod) module_put(mod)
+#define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)
+
+/* People do this inside their init routines, when the module isn't
+   "live" yet.  They should no longer be doing that, but
+   meanwhile... */
+#if defined(CONFIG_MODULE_UNLOAD) && defined(MODULE)
+#define MOD_INC_USE_COUNT	\
+	do { __unsafe(THIS_MODULE); local_inc(&THIS_MODULE->ref[get_cpu()].count); put_cpu(); } while (0)
+#else
+#define MOD_INC_USE_COUNT \
+	do { __unsafe(THIS_MODULE); (void)try_module_get(THIS_MODULE); } while (0)
 #endif
+#define MOD_DEC_USE_COUNT module_put(THIS_MODULE)
+#define try_inc_mod_count(mod) try_module_get(mod)
+#define MODULE_PARM(parm,string)
+#define EXPORT_NO_SYMBOLS
+extern int module_dummy_usage;
+#define GET_USE_COUNT(module) (module_dummy_usage)
+#define MOD_IN_USE 0
+#define __mod_between(a_start, a_len, b_start, b_len)		\
+(((a_start) >= (b_start) && (a_start) <= (b_start)+(b_len))	\
+ || ((a_start)+(a_len) >= (b_start)				\
+     && (a_start)+(a_len) <= (b_start)+(b_len)))
+#define mod_bound(p, n, m)					\
+(((m)->module_init						\
+  && __mod_between((p),(n),(m)->module_init,(m)->init_size))	\
+ || __mod_between((p),(n),(m)->module_core,(m)->core_size))
+
+/* Old-style "I'll just call it init_module and it'll be run at
+   insert".  Use module_init(myroutine) instead. */
+#ifdef MODULE
+/* Used as "int init_module(void) { ... }".  Get funky to insert modname. */
+#define init_module(voidarg)						\
+	__initfn(void);							\
+	char __module_name[] __attribute__((section(".modulename"))) =	\
+	__stringify(KBUILD_MODNAME);					\
+	int __initfn(void)
+#define cleanup_module(voidarg) __exitfn(void)
+#endif
+
+/* Use symbol_get and symbol_put instead.  You'll thank me. */
+#define HAVE_INTER_MODULE
+extern void inter_module_register(const char *, struct module *, const void *);
+extern void inter_module_unregister(const char *);
+extern const void *inter_module_get(const char *);
+extern const void *inter_module_get_request(const char *, const char *);
+extern void inter_module_put(const char *);
 
 #endif /* _LINUX_MODULE_H */
diff -Nru a/include/linux/moduleloader.h b/include/linux/moduleloader.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/moduleloader.h	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,61 @@
+#ifndef _LINUX_MODULELOADER_H
+#define _LINUX_MODULELOADER_H
+/* The stuff needed for archs to support modules. */
+
+#include <linux/module.h>
+#include <linux/elf.h>
+
+/* Helper function for arch-specific module loaders */
+unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
+				   unsigned int symindex,
+				   const char *strtab,
+				   const char *name,
+				   struct module *mod,
+				   struct kernel_symbol_group **group);
+
+/* These must be implemented by the specific architecture */
+
+/* Total size to allocate for the non-releasable code; return len or
+   -error.  mod->core_size is the current generic tally. */
+long module_core_size(const Elf_Ehdr *hdr,
+		      const Elf_Shdr *sechdrs,
+		      const char *secstrings,
+		      struct module *mod);
+
+/* Total size of (if any) sections to be freed after init.  Return 0
+   for none, len, or -error. mod->init_size is the current generic
+   tally. */
+long module_init_size(const Elf_Ehdr *hdr,
+		      const Elf_Shdr *sechdrs,
+		      const char *secstrings,
+		      struct module *mod);
+
+/* Allocator used for allocating struct module, core sections and init
+   sections.  Returns NULL on failure. */
+void *module_alloc(unsigned long size);
+
+/* Free memory returned from module_alloc. */
+void module_free(struct module *mod, void *module_region);
+
+/* Apply the given relocation to the (simplified) ELF.  Return -error
+   or 0. */
+int apply_relocate(Elf_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *mod);
+
+/* Apply the given add relocation to the (simplified) ELF.  Return
+   -error or 0 */
+int apply_relocate_add(Elf_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *mod);
+
+/* Any final processing of module before access.  Return -error or 0. */
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *mod);
+
+#endif
diff -Nru a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/msdos_fs.h	Sun Nov 17 20:30:15 2002
@@ -5,6 +5,7 @@
  * The MS-DOS filesystem constants/structures
  */
 #include <linux/buffer_head.h>
+#include <linux/string.h>
 #include <asm/byteorder.h>
 
 #define SECTOR_SIZE	512		/* sector size (bytes) */
diff -Nru a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
--- a/include/linux/ncp_fs_sb.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/ncp_fs_sb.h	Sun Nov 17 20:30:02 2002
@@ -10,12 +10,15 @@
 
 #include <linux/types.h>
 #include <linux/ncp_mount.h>
+#include <linux/net.h>
 
 #ifdef __KERNEL__
 
 #include <linux/workqueue.h>
 
 #define NCP_DEFAULT_OPTIONS 0		/* 2 for packet signatures */
+
+struct sock;
 
 struct ncp_server {
 
diff -Nru a/include/linux/netlink.h b/include/linux/netlink.h
--- a/include/linux/netlink.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/netlink.h	Sun Nov 17 20:30:15 2002
@@ -7,6 +7,7 @@
 #define NETLINK_FIREWALL	3	/* Firewalling hook				*/
 #define NETLINK_TCPDIAG		4	/* TCP socket monitoring			*/
 #define NETLINK_NFLOG		5	/* netfilter/iptables ULOG */
+#define NETLINK_XFRM		6	/* ipsec */
 #define NETLINK_ARPD		8
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
 #define NETLINK_IP6_FW		13
@@ -85,6 +86,8 @@
 #define NET_MAJOR 36		/* Major 36 is reserved for networking 						*/
 
 #ifdef __KERNEL__
+
+#include <linux/capability.h>
 
 struct netlink_skb_parms
 {
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/nfs_fs.h	Sun Nov 17 20:30:12 2002
@@ -422,6 +422,14 @@
 	return (time_t)(time >> 32);
 }
 
+
+static inline u32
+nfs_time_to_nsecs(__u64 time)
+{
+	return time & 0xffffffff;
+}
+
+
 /* NFS root */
 
 extern void * nfs_root_data(void);
diff -Nru a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
--- a/include/linux/nfsd/cache.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/nfsd/cache.h	Sun Nov 17 20:30:02 2002
@@ -11,7 +11,8 @@
 #define NFSCACHE_H
 
 #ifdef __KERNEL__
-#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/uio.h>
 
 /*
  * Representation of a reply cache entry. The first two members *must*
diff -Nru a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
--- a/include/linux/nfsd/nfsfh.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/nfsd/nfsfh.h	Sun Nov 17 20:30:14 2002
@@ -263,8 +263,8 @@
 
 	inode = fhp->fh_dentry->d_inode;
 	if (!fhp->fh_pre_saved) {
-		fhp->fh_pre_mtime = inode->i_mtime;
-			fhp->fh_pre_ctime = inode->i_ctime;
+		fhp->fh_pre_mtime = inode->i_mtime.tv_sec;
+		fhp->fh_pre_ctime = inode->i_ctime.tv_sec;
 			fhp->fh_pre_size  = inode->i_size;
 			fhp->fh_pre_saved = 1;
 	}
@@ -296,9 +296,9 @@
 	}
 	fhp->fh_post_rdev[0]    = htonl((u32)major(inode->i_rdev));
 	fhp->fh_post_rdev[1]    = htonl((u32)minor(inode->i_rdev));
-	fhp->fh_post_atime      = inode->i_atime;
-	fhp->fh_post_mtime      = inode->i_mtime;
-	fhp->fh_post_ctime      = inode->i_ctime;
+	fhp->fh_post_atime      = inode->i_atime.tv_sec;
+	fhp->fh_post_mtime      = inode->i_mtime.tv_sec;
+	fhp->fh_post_ctime      = inode->i_ctime.tv_sec;
 	fhp->fh_post_saved      = 1;
 }
 #else
diff -Nru a/include/linux/parport.h b/include/linux/parport.h
--- a/include/linux/parport.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/parport.h	Sun Nov 17 20:30:15 2002
@@ -8,7 +8,6 @@
 
 #ifndef _PARPORT_H_
 #define _PARPORT_H_
-#include <linux/sched.h>
 
 /* Start off with user-visible constants */
 
@@ -97,13 +96,14 @@
 /* The rest is for the kernel only */
 #ifdef __KERNEL__
 
-#include <linux/wait.h>
+#include <linux/config.h>
+#include <linux/jiffies.h>
+#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/semaphore.h>
-#include <linux/proc_fs.h>
-#include <linux/config.h>
 
 #define PARPORT_NEED_GENERIC_OPS
 
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/pci.h	Sun Nov 17 20:30:14 2002
@@ -371,7 +371,6 @@
 	struct resource dma_resource[DEVICE_COUNT_DMA];
 	struct resource irq_resource[DEVICE_COUNT_IRQ];
 
-	char		name[90];	/* device name */
 	char		slot_name[8];	/* slot name */
 	int		active;		/* ISAPnP: device is active */
 	int		ro;		/* ISAPnP: read only */
diff -Nru a/include/linux/poll.h b/include/linux/poll.h
--- a/include/linux/poll.h	Sun Nov 17 20:30:15 2002
+++ b/include/linux/poll.h	Sun Nov 17 20:30:15 2002
@@ -10,43 +10,39 @@
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 
-struct poll_table_page;
+struct poll_table_struct;
+
+/* 
+ * structures and helpers for f_op->poll implementations
+ */
+typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
 
 typedef struct poll_table_struct {
-	int queue;
-	void *priv;
-	void (*qproc)(void *, wait_queue_head_t *);
-	int error;
-	struct poll_table_page * table;
+	poll_queue_proc qproc;
 } poll_table;
 
-extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p);
-
 static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
 {
 	if (p && wait_address)
-		__pollwait(filp, wait_address, p);
+		p->qproc(filp, wait_address, p);
 }
 
-static inline void poll_initwait_ex(poll_table* pt, int queue,
-				    void (*qproc)(void *, wait_queue_head_t *),
-				    void *priv)
+static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
 {
-	pt->queue = queue;
 	pt->qproc = qproc;
-	pt->priv = priv;
-	pt->error = 0;
-	pt->table = NULL;
-}
-
-static inline void poll_initwait(poll_table* pt)
-{
-
-	poll_initwait_ex(pt, 1, NULL, NULL);
 }
 
-extern void poll_freewait(poll_table* pt);
+/*
+ * Structures and helpers for sys_poll/sys_poll
+ */
+struct poll_wqueues {
+	poll_table pt;
+	struct poll_table_page * table;
+	int error;
+};
 
+extern void poll_initwait(struct poll_wqueues *pwq);
+extern void poll_freewait(struct poll_wqueues *pwq);
 
 /*
  * Scaleable version of the fd_set.
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Sun Nov 17 20:30:03 2002
+++ b/include/linux/sched.h	Sun Nov 17 20:30:03 2002
@@ -488,31 +488,10 @@
 extern unsigned long itimer_next;
 extern void do_timer(struct pt_regs *);
 
-extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr));
-extern void FASTCALL(__wake_up_locked(wait_queue_head_t *q, unsigned int mode));
-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));
-extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
-				      signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
-						    signed long timeout));
 extern int FASTCALL(wake_up_process(struct task_struct * tsk));
 extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk));
 extern void FASTCALL(sched_exit(task_t * p));
 
-#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
-#define wake_up_nr(x, nr)		__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
-#define wake_up_all(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0)
-#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE, 1)
-#define wake_up_interruptible_nr(x, nr)	__wake_up((x),TASK_INTERRUPTIBLE, nr)
-#define wake_up_interruptible_all(x)	__wake_up((x),TASK_INTERRUPTIBLE, 0)
-#define	wake_up_locked(x)		__wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
-#ifdef CONFIG_SMP
-#define wake_up_interruptible_sync(x)   __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
-#else
-#define wake_up_interruptible_sync(x)   __wake_up((x),TASK_INTERRUPTIBLE, 1)
-#endif
 asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
 
 extern int in_group_p(gid_t);
@@ -588,11 +567,6 @@
 		: on_sig_stack(sp) ? SS_ONSTACK : 0);
 }
 
-extern int request_irq(unsigned int,
-		       void (*handler)(int, void *, struct pt_regs *),
-		       unsigned long, const char *, void *);
-extern void free_irq(unsigned int, void *);
-
 /* capable prototype and code moved to security.[hc] */
 #include <linux/security.h>
 #if 0
@@ -627,17 +601,6 @@
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(void);
 
-/*
- * Routines for handling the fd arrays
- */
-extern struct file ** alloc_fd_array(int);
-extern int expand_fd_array(struct files_struct *, int nr);
-extern void free_fd_array(struct file **, int);
-
-extern fd_set *alloc_fdset(int);
-extern int expand_fdset(struct files_struct *, int nr);
-extern void free_fdset(fd_set *, int);
-
 extern int  copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
 extern void flush_thread(void);
 extern void exit_thread(void);
@@ -654,10 +617,6 @@
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int *);
 
-extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
-extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
-extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
-
 #ifdef CONFIG_SMP
 extern void wait_task_inactive(task_t * p);
 #else
@@ -665,108 +624,6 @@
 #endif
 extern void kick_if_running(task_t * p);
 
-#define __wait_event(wq, condition) 					\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_UNINTERRUPTIBLE);		\
-		if (condition)						\
-			break;						\
-		schedule();						\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-
-#define wait_event(wq, condition) 					\
-do {									\
-	if (condition)	 						\
-		break;							\
-	__wait_event(wq, condition);					\
-} while (0)
-
-#define __wait_event_interruptible(wq, condition, ret)			\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_INTERRUPTIBLE);			\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			schedule();					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-
-#define wait_event_interruptible(wq, condition)				\
-({									\
-	int __ret = 0;							\
-	if (!(condition))						\
-		__wait_event_interruptible(wq, condition, __ret);	\
-	__ret;								\
-})
-
-#define __wait_event_interruptible_timeout(wq, condition, ret)		\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_INTERRUPTIBLE);			\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			ret = schedule_timeout(ret);			\
-			if (!ret)					\
-				break;					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-
-#define wait_event_interruptible_timeout(wq, condition, timeout)	\
-({									\
-	long __ret = timeout;						\
-	if (!(condition))						\
-		__wait_event_interruptible_timeout(wq, condition, __ret); \
-	__ret;								\
-})
-	
-/*
- * Must be called with the spinlock in the wait_queue_head_t held.
- */
-static inline void add_wait_queue_exclusive_locked(wait_queue_head_t *q,
-						   wait_queue_t * wait)
-{
-	wait->flags |= WQ_FLAG_EXCLUSIVE;
-	__add_wait_queue_tail(q,  wait);
-}
-
-/*
- * Must be called with the spinlock in the wait_queue_head_t held.
- */
-static inline void remove_wait_queue_locked(wait_queue_head_t *q,
-					    wait_queue_t * wait)
-{
-	__remove_wait_queue(q,  wait);
-}
-
 #define remove_parent(p)	list_del_init(&(p)->sibling)
 #define add_parent(p, parent)	list_add_tail(&(p)->sibling,&(parent)->children)
 
@@ -848,26 +705,6 @@
 {
 	spin_unlock(&p->alloc_lock);
 }
-
-/* write full pathname into buffer and return start of pathname */
-static inline char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-				char *buf, int buflen)
-{
-	char *res;
-	struct vfsmount *rootmnt;
-	struct dentry *root;
-	read_lock(&current->fs->lock);
-	rootmnt = mntget(current->fs->rootmnt);
-	root = dget(current->fs->root);
-	read_unlock(&current->fs->lock);
-	spin_lock(&dcache_lock);
-	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
-	spin_unlock(&dcache_lock);
-	dput(root);
-	mntput(rootmnt);
-	return res;
-}
-
  
 /**
  * get_task_mm - acquire a reference to the task's mm
diff -Nru a/include/linux/smb.h b/include/linux/smb.h
--- a/include/linux/smb.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/smb.h	Sun Nov 17 20:30:14 2002
@@ -85,9 +85,9 @@
 	gid_t		f_gid;
 	dev_t		f_rdev;
 	loff_t		f_size;
-	time_t		f_atime;
-	time_t		f_mtime;
-	time_t		f_ctime;
+	struct timespec	f_atime;
+	struct timespec f_mtime;
+	struct timespec f_ctime;
 	unsigned long	f_blksize;
 	unsigned long	f_blocks;
 	int		f_unix;
diff -Nru a/include/linux/stat.h b/include/linux/stat.h
--- a/include/linux/stat.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/stat.h	Sun Nov 17 20:30:12 2002
@@ -54,6 +54,7 @@
 #define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)
 
 #include <linux/types.h>
+#include <linux/time.h>
 
 struct kstat {
 	unsigned long	ino;
@@ -64,9 +65,9 @@
 	gid_t		gid;
 	dev_t		rdev;
 	loff_t		size;
-	time_t		atime;
-	time_t		mtime;
-	time_t		ctime;
+	struct timespec  atime;
+	struct timespec	mtime;
+	struct timespec	ctime;
 	unsigned long	blksize;
 	unsigned long	blocks;
 };
diff -Nru a/include/linux/string.h b/include/linux/string.h
--- a/include/linux/string.h	Sun Nov 17 20:30:13 2002
+++ b/include/linux/string.h	Sun Nov 17 20:30:13 2002
@@ -15,7 +15,7 @@
 extern char * strpbrk(const char *,const char *);
 extern char * strsep(char **,const char *);
 extern __kernel_size_t strspn(const char *,const char *);
-
+extern __kernel_size_t strcspn(const char *,const char *);
 
 /*
  * Include machine specific inline routines
diff -Nru a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
--- a/include/linux/sunrpc/clnt.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/sunrpc/clnt.h	Sun Nov 17 20:30:14 2002
@@ -87,7 +87,7 @@
  * Procedure information
  */
 struct rpc_procinfo {
-	char *			p_procname;	/* procedure name */
+	u32			p_proc;		/* RPC procedure number */
 	kxdrproc_t		p_encode;	/* XDR encode function */
 	kxdrproc_t		p_decode;	/* XDR decode function */
 	unsigned int		p_bufsiz;	/* req. buffer size */
@@ -95,13 +95,6 @@
 	unsigned int		p_timer;	/* Which RTT timer to use */
 };
 
-#define rpcproc_bufsiz(clnt, proc)	((clnt)->cl_procinfo[proc].p_bufsiz)
-#define rpcproc_encode(clnt, proc)	((clnt)->cl_procinfo[proc].p_encode)
-#define rpcproc_decode(clnt, proc)	((clnt)->cl_procinfo[proc].p_decode)
-#define rpcproc_name(clnt, proc)	((clnt)->cl_procinfo[proc].p_procname)
-#define rpcproc_count(clnt, proc)	((clnt)->cl_procinfo[proc].p_count)
-#define rpcproc_timer(clnt, proc)	((clnt)->cl_procinfo[proc].p_timer)
-
 #define RPC_CONGESTED(clnt)	(RPCXPRT_CONGESTED((clnt)->cl_xprt))
 #define RPC_PEERADDR(clnt)	(&(clnt)->cl_xprt->addr)
 
@@ -131,7 +124,7 @@
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
 	struct rpc_message msg = {
-		.rpc_proc	= proc,
+		.rpc_proc	= &clnt->cl_procinfo[proc],
 		.rpc_argp	= argp,
 		.rpc_resp	= resp,
 		.rpc_cred	= NULL
diff -Nru a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
--- a/include/linux/sunrpc/sched.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/sunrpc/sched.h	Sun Nov 17 20:30:14 2002
@@ -16,8 +16,9 @@
 /*
  * This is the actual RPC procedure call info.
  */
+struct rpc_procinfo;
 struct rpc_message {
-	__u32			rpc_proc;	/* Procedure number */
+	struct rpc_procinfo *	rpc_proc;	/* Procedure information */
 	void *			rpc_argp;	/* Arguments */
 	void *			rpc_resp;	/* Result */
 	struct rpc_cred *	rpc_cred;	/* Credentials */
diff -Nru a/include/linux/suspend.h b/include/linux/suspend.h
--- a/include/linux/suspend.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/suspend.h	Sun Nov 17 20:30:12 2002
@@ -72,7 +72,9 @@
 extern void do_suspend_lowlevel(int resume);
 
 #else
-#define software_suspend()		do { } while(0)
+static inline void software_suspend(void)
+{
+}
 #define software_resume()		do { } while(0)
 #define register_suspend_notifier(a)	do { } while(0)
 #define unregister_suspend_notifier(a)	do { } while(0)
diff -Nru a/include/linux/time.h b/include/linux/time.h
--- a/include/linux/time.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/time.h	Sun Nov 17 20:30:14 2002
@@ -24,6 +24,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/spinlock.h>
+
 /*
  * Change timeval to jiffies, trying to avoid the
  * most obvious overflows..
@@ -79,6 +81,10 @@
 	value->tv_sec = jiffies / HZ;
 }
 
+static __inline__ int timespec_equal(struct timespec *a, struct timespec *b) 
+{ 
+	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
+} 
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
@@ -114,8 +120,16 @@
 }
 
 extern struct timespec xtime;
+extern rwlock_t xtime_lock;
+
+static inline unsigned long get_seconds(void)
+{ 
+	return xtime.tv_sec;
+}
+
+struct timespec current_kernel_time(void);
 
-#define CURRENT_TIME (xtime.tv_sec)
+#define CURRENT_TIME (current_kernel_time())
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/udf_fs.h b/include/linux/udf_fs.h
--- a/include/linux/udf_fs.h	Sun Nov 17 20:30:04 2002
+++ b/include/linux/udf_fs.h	Sun Nov 17 20:30:04 2002
@@ -34,23 +34,11 @@
 #ifndef _UDF_FS_H
 #define _UDF_FS_H 1
 
-#include <linux/config.h>
-
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS	8
 
-#define UDFFS_DATE			"2002/03/11"
-#define UDFFS_VERSION			"0.9.6"
-
-#if !defined(UDFFS_RW)
-
-#if defined(CONFIG_UDF_RW)
-#define UDFFS_RW			1
-#else /* !defined(CONFIG_UDF_RW) */
-#define UDFFS_RW			0
-#endif /* defined(CONFIG_UDF_RW) */
-
-#endif /* !defined(UDFFS_RW) */
+#define UDFFS_DATE			"2002/11/15"
+#define UDFFS_VERSION			"0.9.7"
 
 #define UDFFS_DEBUG
 
diff -Nru a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
--- a/include/linux/udf_fs_i.h	Sun Nov 17 20:30:02 2002
+++ b/include/linux/udf_fs_i.h	Sun Nov 17 20:30:02 2002
@@ -23,30 +23,49 @@
 #ifndef _ECMA_167_H
 typedef struct
 {
-	__u32 logicalBlockNum;
-	__u16 partitionReferenceNum;
+	__u32			logicalBlockNum;
+	__u16			partitionReferenceNum;
 } __attribute__ ((packed)) lb_addr;
+
+typedef struct
+{
+	__u32			extLength;
+	__u32			extPosition;
+} __attribute__ ((packed)) short_ad;
+
+typedef struct
+{
+	__u32			extLength;
+	lb_addr			extLocation;
+	__u8			impUse[6];
+} __attribute__ ((packed)) long_ad;
 #endif
 
 struct udf_inode_info
 {
-	long i_umtime;
-	long i_uctime;
-	long i_crtime;
-	long i_ucrtime;
+	long			i_umtime;
+	long			i_uctime;
+	long			i_crtime;
+	long			i_ucrtime;
 	/* Physical address of inode */
-	lb_addr i_location;
-	__u64 i_unique;
-	__u32 i_lenEAttr;
-	__u32 i_lenAlloc;
-	__u64 i_lenExtents;
-	__u32 i_next_alloc_block;
-	__u32 i_next_alloc_goal;
-	unsigned i_alloc_type : 3;
-	unsigned i_extended_fe : 1;
-	unsigned i_strat_4096 : 1;
-	unsigned i_new_inode : 1;
-	unsigned reserved : 26;
+	lb_addr			i_location;
+	__u64			i_unique;
+	__u32			i_lenEAttr;
+	__u32			i_lenAlloc;
+	__u64			i_lenExtents;
+	__u32			i_next_alloc_block;
+	__u32			i_next_alloc_goal;
+	unsigned		i_alloc_type : 3;
+	unsigned		i_efe : 1;
+	unsigned		i_use : 1;
+	unsigned		i_strat4096 : 1;
+	unsigned		reserved : 26;
+	union
+	{
+		short_ad	*i_sad;
+		long_ad		*i_lad;
+		__u8		*i_data;
+	} i_ext;
 	struct inode vfs_inode;
 };
 
diff -Nru a/include/linux/udp.h b/include/linux/udp.h
--- a/include/linux/udp.h	Sun Nov 17 20:30:12 2002
+++ b/include/linux/udp.h	Sun Nov 17 20:30:12 2002
@@ -57,7 +57,4 @@
 
 #define udp_sk(__sk) (&((struct udp_sock *)__sk)->udp)
 
-extern int udp_proc_init(void);
-extern void udp_proc_exit(void);
-
 #endif	/* _LINUX_UDP_H */
diff -Nru a/include/linux/wait.h b/include/linux/wait.h
--- a/include/linux/wait.h	Sun Nov 17 20:30:14 2002
+++ b/include/linux/wait.h	Sun Nov 17 20:30:14 2002
@@ -10,14 +10,11 @@
 
 #ifdef __KERNEL__
 
-#include <linux/kernel.h>
+#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
-#include <linux/config.h>
-
-#include <asm/page.h>
-#include <asm/processor.h>
+#include <asm/system.h>
 
 typedef struct __wait_queue wait_queue_t;
 typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync);
@@ -83,6 +80,10 @@
 	return !list_empty(&q->task_list);
 }
 
+extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
+extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
+extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
+
 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
 {
 	list_add(&new->task_list, &head->task_list);
@@ -103,6 +104,125 @@
 	list_del(&old->task_list);
 }
 
+extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr));
+extern void FASTCALL(__wake_up_locked(wait_queue_head_t *q, unsigned int mode));
+extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr));
+
+#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
+#define wake_up_nr(x, nr)		__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
+#define wake_up_all(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0)
+#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE, 1)
+#define wake_up_interruptible_nr(x, nr)	__wake_up((x),TASK_INTERRUPTIBLE, nr)
+#define wake_up_interruptible_all(x)	__wake_up((x),TASK_INTERRUPTIBLE, 0)
+#define	wake_up_locked(x)		__wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#ifdef CONFIG_SMP
+#define wake_up_interruptible_sync(x)   __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
+#else
+#define wake_up_interruptible_sync(x)   __wake_up((x),TASK_INTERRUPTIBLE, 1)
+#endif
+
+#define __wait_event(wq, condition) 					\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		set_current_state(TASK_UNINTERRUPTIBLE);		\
+		if (condition)						\
+			break;						\
+		schedule();						\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event(wq, condition) 					\
+do {									\
+	if (condition)	 						\
+		break;							\
+	__wait_event(wq, condition);					\
+} while (0)
+
+#define __wait_event_interruptible(wq, condition, ret)			\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		set_current_state(TASK_INTERRUPTIBLE);			\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			schedule();					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event_interruptible(wq, condition)				\
+({									\
+	int __ret = 0;							\
+	if (!(condition))						\
+		__wait_event_interruptible(wq, condition, __ret);	\
+	__ret;								\
+})
+
+#define __wait_event_interruptible_timeout(wq, condition, ret)		\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		set_current_state(TASK_INTERRUPTIBLE);			\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			ret = schedule_timeout(ret);			\
+			if (!ret)					\
+				break;					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout)	\
+({									\
+	long __ret = timeout;						\
+	if (!(condition))						\
+		__wait_event_interruptible_timeout(wq, condition, __ret); \
+	__ret;								\
+})
+	
+/*
+ * Must be called with the spinlock in the wait_queue_head_t held.
+ */
+static inline void add_wait_queue_exclusive_locked(wait_queue_head_t *q,
+						   wait_queue_t * wait)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	__add_wait_queue_tail(q,  wait);
+}
+
+/*
+ * Must be called with the spinlock in the wait_queue_head_t held.
+ */
+static inline void remove_wait_queue_locked(wait_queue_head_t *q,
+					    wait_queue_t * wait)
+{
+	__remove_wait_queue(q,  wait);
+}
+
 #define add_wait_queue_cond(q, wait, cond) \
 	({							\
 		unsigned long flags;				\
@@ -120,7 +240,19 @@
 	})
 
 /*
- * Waitqueue's which are removed from the waitqueue_head at wakeup time
+ * These are the old interfaces to sleep waiting for an event.
+ * They are racy.  DO NOT use them, use the wait_event* interfaces above.  
+ * We plan to remove these interfaces during 2.7.
+ */
+extern void FASTCALL(sleep_on(wait_queue_head_t *q));
+extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
+				      signed long timeout));
+extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
+extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
+						    signed long timeout));
+
+/*
+ * Waitqueues which are removed from the waitqueue_head at wakeup time
  */
 void FASTCALL(prepare_to_wait(wait_queue_head_t *q,
 				wait_queue_t *wait, int state));
diff -Nru a/include/linux/xfrm.h b/include/linux/xfrm.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/xfrm.h	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,215 @@
+#ifndef _LINUX_XFRM_H
+#define _LINUX_XFRM_H
+
+#include <linux/types.h>
+
+/* All of the structures in this file may not change size as they are
+ * passed into the kernel from userspace via netlink sockets.
+ */
+
+/* Structure to encapsulate addresses. I do not want to use
+ * "standard" structure. My apologies.
+ */
+typedef union
+{
+	struct {
+		__u32	addr;
+		__u32	mask;	/* Use unused bits to cache mask. */
+	} a4;
+#define xfrm4_addr a4.addr
+#define xfrm4_mask a4.mask
+	__u32		a6[4];
+} xfrm_address_t;
+
+/* Ident of a specific xfrm_state. It is used on input to lookup
+ * the state by (spi,daddr,ah/esp) or to store information about
+ * spi, protocol and tunnel address on output.
+ */
+struct xfrm_id
+{
+	xfrm_address_t	daddr;
+	__u32		spi;
+	__u8		proto;
+};
+
+/* Selector, used as selector both on policy rules (SPD) and SAs. */
+
+struct xfrm_selector
+{
+	xfrm_address_t	daddr;
+	xfrm_address_t	saddr;
+	__u16	dport;
+	__u16	dport_mask;
+	__u16	sport;
+	__u16	sport_mask;
+	__u8	prefixlen_d;
+	__u8	prefixlen_s;
+	__u8	proto;
+	int	ifindex;
+	uid_t	user;
+	void	*owner;
+};
+
+#define XFRM_INF (~(u64)0)
+
+struct xfrm_lifetime_cfg
+{
+	__u64	soft_byte_limit;
+	__u64	hard_byte_limit;
+	__u64	soft_packet_limit;
+	__u64	hard_packet_limit;
+	__u64	soft_add_expires_seconds;
+	__u64	hard_add_expires_seconds;
+	__u64	soft_use_expires_seconds;
+	__u64	hard_use_expires_seconds;
+};
+
+struct xfrm_lifetime_cur
+{
+	__u64	bytes;
+	__u64	packets;
+	__u64	add_time;
+	__u64	use_time;
+};
+
+struct xfrm_replay_state
+{
+	__u32	oseq;
+	__u32	seq;
+	__u32	bitmap;
+};
+
+struct xfrm_algo {
+	char	alg_name[64];
+	int	alg_key_len;    /* in bits */
+	char	alg_key[0];
+};
+
+struct xfrm_stats {
+	__u32	replay_window;
+	__u32	replay;
+	__u32	integrity_failed;
+};
+
+enum
+{
+	XFRM_POLICY_IN	= 0,
+	XFRM_POLICY_OUT	= 1,
+	XFRM_POLICY_FWD	= 2,
+	XFRM_POLICY_MAX	= 3
+};
+
+enum
+{
+	XFRM_SHARE_ANY,		/* No limitations */
+	XFRM_SHARE_SESSION,	/* For this session only */
+	XFRM_SHARE_USER,	/* For this user only */
+	XFRM_SHARE_UNIQUE	/* Use once */
+};
+
+/* Netlink configuration messages.  */
+#define XFRM_MSG_BASE		0x10
+
+#define XFRM_MSG_NEWSA		(RTM_BASE + 0)
+#define XFRM_MSG_DELSA		(RTM_BASE + 1)
+#define XFRM_MSG_GETSA		(RTM_BASE + 2)
+
+#define XFRM_MSG_NEWPOLICY	(RTM_BASE + 3)
+#define XFRM_MSG_DELPOLICY	(RTM_BASE + 4)
+#define XFRM_MSG_GETPOLICY	(RTM_BASE + 5)
+
+#define XFRM_MSG_ALLOCSPI	(RTM_BASE + 6)
+#define XFRM_MSG_ACQUIRE	(RTM_BASE + 7)
+#define XFRM_MSG_EXPIRE		(RTM_BASE + 8)
+
+#define XFRM_MSG_MAX		(XFRM_MSG_EXPIRE+1)
+
+struct xfrm_user_tmpl {
+	struct xfrm_id		id;
+	xfrm_address_t		saddr;
+	__u16			reqid;
+	__u8			mode;
+	__u8			share;
+	__u8			optional;
+	__u32			aalgos;
+	__u32			ealgos;
+	__u32			calgos;
+};
+
+/* Netlink message attributes.  */
+enum xfrm_attr_type_t {
+	XFRMA_UNSPEC,
+	XFRMA_ALG_AUTH,		/* struct xfrm_algo */
+	XFRMA_ALG_CRYPT,	/* struct xfrm_algo */
+	XFRMA_ALG_COMP,		/* struct xfrm_algo */
+	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
+
+#define XFRMA_MAX XFRMA_TMPL
+};
+
+struct xfrm_usersa_info {
+	struct xfrm_selector		sel;
+	struct xfrm_id			id;
+	struct xfrm_lifetime_cfg	lft;
+	struct xfrm_lifetime_cur	curlft;
+	struct xfrm_stats		stats;
+	__u32				seq;
+	__u16				family;
+	__u16				reqid;
+	__u8				mode; /* 0=transport,1=tunnel */
+	__u8				replay_window;
+};
+
+struct xfrm_usersa_id {
+	xfrm_address_t			saddr;
+	__u32				spi;
+	__u8				proto;
+};
+
+struct xfrm_userspi_info {
+	struct xfrm_usersa_info		info;
+	u32				min;
+	u32				max;
+};
+
+struct xfrm_userpolicy_info {
+	struct xfrm_selector		sel;
+	struct xfrm_lifetime_cfg	lft;
+	struct xfrm_lifetime_cur	curlft;
+	__u32				priority;
+	__u32				index;
+	__u16				family;
+	__u8				dir;
+	__u8				action;
+#define XFRM_POLICY_ALLOW	0
+#define XFRM_POLICY_BLOCK	1
+	__u8				flags;
+#define XFRM_POLICY_LOCALOK	1	/* Allow user to override global policy */
+	__u8				share;
+};
+
+struct xfrm_userpolicy_id {
+	struct xfrm_selector		sel;
+	__u32				index;
+	__u8				dir;
+};
+
+struct xfrm_user_acquire {
+	struct xfrm_id			id;
+	xfrm_address_t			saddr;
+	struct xfrm_userpolicy_info	policy;
+	__u32				aalgos;
+	__u32				ealgos;
+	__u32				calgos;
+	__u32				seq;
+};
+
+struct xfrm_user_expire {
+	struct xfrm_usersa_info		state;
+	__u8				hard;
+};
+
+#define XFRMGRP_ACQUIRE		1
+#define XFRMGRP_EXPIRE		2
+
+#endif /* _LINUX_XFRM_H */
diff -Nru a/include/net/ip_fib.h b/include/net/ip_fib.h
--- a/include/net/ip_fib.h	Sun Nov 17 20:30:15 2002
+++ b/include/net/ip_fib.h	Sun Nov 17 20:30:15 2002
@@ -276,7 +276,4 @@
 #endif
 }
 
-extern int fib_proc_init(void);
-extern void fib_proc_exit(void);
-
 #endif  /* _NET_FIB_H */
diff -Nru a/include/net/route.h b/include/net/route.h
--- a/include/net/route.h	Sun Nov 17 20:30:02 2002
+++ b/include/net/route.h	Sun Nov 17 20:30:02 2002
@@ -140,7 +140,9 @@
 	return ip_tos2prio[IPTOS_TOS(tos)>>1];
 }
 
-static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif, u8 protocol, u16 sport, u16 dport)
+static inline int ip_route_connect(struct rtable **rp, u32 dst,
+				   u32 src, u32 tos, int oif, u8 protocol,
+				   u16 sport, u16 dport, struct sock *sk)
 {
 	struct flowi fl = { .oif = oif,
 			    .nl_u = { .ip4_u = { .daddr = dst,
@@ -161,10 +163,11 @@
 		ip_rt_put(*rp);
 		*rp = NULL;
 	}
-	return ip_route_output_key(rp, &fl);
+	return ip_route_output_flow(rp, &fl, sk, 0);
 }
 
-static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport)
+static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
+				    struct sock *sk)
 {
 	if (sport != (*rp)->fl.uli_u.ports.sport ||
 	    dport != (*rp)->fl.uli_u.ports.dport) {
@@ -175,7 +178,7 @@
 		fl.uli_u.ports.dport = dport;
 		ip_rt_put(*rp);
 		*rp = NULL;
-		return ip_route_output_key(rp, &fl);
+		return ip_route_output_flow(rp, &fl, sk, 0);
 	}
 	return 0;
 }
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Sun Nov 17 20:30:15 2002
+++ b/include/net/sock.h	Sun Nov 17 20:30:15 2002
@@ -321,6 +321,21 @@
 	return container_of((void *)si, struct kiocb, private);
 }
 
+struct socket_alloc {
+	struct socket socket;
+	struct inode vfs_inode;
+};
+
+static inline struct socket *SOCKET_I(struct inode *inode)
+{
+	return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
+}
+
+static inline struct inode *SOCK_INODE(struct socket *socket)
+{
+	return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
+}
+
 /* Used by processes to "lock" a socket state, so that
  * interrupts and bottom half handlers won't change it
  * from under us. It essentially blocks any incoming
diff -Nru a/include/net/udp.h b/include/net/udp.h
--- a/include/net/udp.h	Sun Nov 17 20:30:15 2002
+++ b/include/net/udp.h	Sun Nov 17 20:30:15 2002
@@ -76,6 +76,4 @@
 #define UDP_INC_STATS_BH(field)		SNMP_INC_STATS_BH(udp_statistics, field)
 #define UDP_INC_STATS_USER(field) 	SNMP_INC_STATS_USER(udp_statistics, field)
 
-extern int udp_proc_init(void);
-
 #endif	/* _UDP_H */
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	Sun Nov 17 20:30:12 2002
+++ b/include/net/xfrm.h	Sun Nov 17 20:30:12 2002
@@ -1,4 +1,4 @@
-#include <linux/types.h>
+#include <linux/xfrm.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/skbuff.h>
@@ -8,6 +8,8 @@
 #include <net/dst.h>
 #include <net/route.h>
 
+extern struct semaphore xfrm_cfg_sem;
+
 /* Organization of SPD aka "XFRM rules"
    ------------------------------------
 
@@ -69,84 +71,6 @@
       metrics. Plus, it will be made via sk->dst_cache. Solved.
  */
 
-/* Structure to encapsulate addresses. I do not want to use
- * "standard" structure. My apologies. */
-
-typedef union
-{
-	struct {
-		u32	addr;
-		u32	mask;	/* Use unused bits to cache mask. */
-	} a4;
-#define xfrm4_addr a4.addr
-#define xfrm4_mask a4.mask
-	u32		a6[4];
-} xfrm_address_t;
-
-/* Ident of a specific xfrm_state. It is used on input to lookup
- * the state by (spi,daddr,ah/esp) or to store information about
- * spi, protocol and tunnel address on output. */
-
-struct xfrm_id
-{
-	xfrm_address_t	daddr;
-	__u32		spi;
-	__u8		proto;
-};
-
-/* Selector, used as selector both on policy rules (SPD) and SAs. */
-
-struct xfrm_selector
-{
-	xfrm_address_t	daddr;
-	xfrm_address_t	saddr;
-	__u16	dport;
-	__u16	dport_mask;
-	__u16	sport;
-	__u16	sport_mask;
-	__u8	prefixlen_d;
-	__u8	prefixlen_s;
-	__u8	proto;
-	int	ifindex;
-	uid_t	user;
-	void	*owner;
-};
-
-#define XFRM_INF (~(u64)0)
-
-struct xfrm_lifetime_cfg
-{
-	u64	soft_byte_limit;
-	u64	hard_byte_limit;
-	u64	soft_packet_limit;
-	u64	hard_packet_limit;
-	u64	soft_add_expires_seconds;
-	u64	hard_add_expires_seconds;
-	u64	soft_use_expires_seconds;
-	u64	hard_use_expires_seconds;
-};
-
-struct xfrm_lifetime_cur
-{
-	u64	bytes;
-	u64	packets;
-	u64	add_time;
-	u64	use_time;
-};
-
-struct xfrm_replay_state
-{
-	u32	oseq;
-	u32	seq;
-	u32	bitmap;
-};
-
-struct xfrm_algo {
-	char	alg_name[CRYPTO_MAX_ALG_NAME];
-	int	alg_key_len;    /* in bits */
-	char	alg_key[0];
-};
-
 /* Full description of state of transformer. */
 struct xfrm_state
 {
@@ -172,6 +96,7 @@
 		u8		replay_window;
 		u8		aalgo, ealgo, calgo;
 		u16		reqid;
+		u16		family;
 		xfrm_address_t	saddr;
 		int		header_len;
 		int		trailer_len;
@@ -188,11 +113,7 @@
 	struct xfrm_replay_state replay;
 
 	/* Statistics */
-	struct {
-		u32		replay_window;
-		u32		replay;
-		u32		integrity_failed;
-	} stats;
+	struct xfrm_stats	stats;
 
 	struct xfrm_lifetime_cur curlft;
 	struct timer_list	timer;
@@ -267,22 +188,6 @@
 
 #define XFRM_MAX_DEPTH		3
 
-enum
-{
-	XFRM_SHARE_ANY,		/* No limitations */
-	XFRM_SHARE_SESSION,	/* For this session only */
-	XFRM_SHARE_USER,	/* For this user only */
-	XFRM_SHARE_UNIQUE	/* Use once */
-};
-
-enum
-{
-	XFRM_POLICY_IN	= 0,
-	XFRM_POLICY_OUT	= 1,
-	XFRM_POLICY_FWD	= 2,
-	XFRM_POLICY_MAX	= 3
-};
-
 struct xfrm_policy
 {
 	struct xfrm_policy	*next;
@@ -297,11 +202,9 @@
 	struct xfrm_lifetime_cfg lft;
 	struct xfrm_lifetime_cur curlft;
 	struct dst_entry       *bundles;
+	__u16			family;
 	__u8			action;
-#define XFRM_POLICY_ALLOW	0
-#define XFRM_POLICY_BLOCK	1
 	__u8			flags;
-#define XFRM_POLICY_LOCALOK	1	/* Allow user to override global policy */
 	__u8			dead;
 	__u8			xfrm_nr;
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
@@ -320,7 +223,7 @@
 extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 
-extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX];
+extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
 {
@@ -429,16 +332,16 @@
 	return 0;
 }
 
-extern void __xfrm_sk_free_policy(struct xfrm_policy *);
+extern void __xfrm_sk_free_policy(struct xfrm_policy *, int dir);
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
 	if (unlikely(sk->policy[0] != NULL)) {
-		__xfrm_sk_free_policy(sk->policy[0]);
+		__xfrm_sk_free_policy(sk->policy[0], 0);
 		sk->policy[0] = NULL;
 	}
 	if (unlikely(sk->policy[1] != NULL)) {
-		__xfrm_sk_free_policy(sk->policy[1]);
+		__xfrm_sk_free_policy(sk->policy[1], 1);
 		sk->policy[1] = NULL;
 	}
 }
@@ -470,14 +373,14 @@
 struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
 void xfrm_policy_flush(void);
 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr);
+struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
 extern void xfrm_policy_flush(void);
 extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
 extern int xfrm_flush_bundles(struct xfrm_state *x);
 
-extern wait_queue_head_t *km_waitq;
+extern wait_queue_head_t km_waitq;
 extern void km_warn_expired(struct xfrm_state *x);
 extern void km_expired(struct xfrm_state *x);
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
diff -Nru a/include/scsi/sg.h b/include/scsi/sg.h
--- a/include/scsi/sg.h	Sun Nov 17 20:30:13 2002
+++ b/include/scsi/sg.h	Sun Nov 17 20:30:13 2002
@@ -69,7 +69,7 @@
 	http://www.torque.net/sg/p/scsi-generic_long.txt
  A version of this document (potentially out of date) may also be found in
  the kernel source tree, probably at:
-        /usr/src/linux/Documentation/scsi-generic.txt .
+        /usr/src/linux/Documentation/scsi/scsi-generic.txt .
 
  Utility and test programs are available at the sg web site. They are 
  bundled as sg_utils (for the lk 2.2 series) and sg3_utils (for the
diff -Nru a/include/sound/initval.h b/include/sound/initval.h
--- a/include/sound/initval.h	Sun Nov 17 20:30:02 2002
+++ b/include/sound/initval.h	Sun Nov 17 20:30:02 2002
@@ -110,6 +110,8 @@
 #endif
 
 #ifdef SNDRV_LEGACY_FIND_FREE_IRQ
+#include <linux/interrupt.h>
+
 static void snd_legacy_empty_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 }
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/init/Kconfig	Sun Nov 17 20:30:15 2002
@@ -116,21 +116,24 @@
 	  may want to make use of modules with this kernel in the future, then
 	  say Y here.  If unsure, say Y.
 
-config MODVERSIONS
-	bool "Set version information on all module symbols"
+config MODULE_UNLOAD
+	bool "Module unloading"
 	depends on MODULES
-	---help---
-	  Usually, modules have to be recompiled whenever you switch to a new
-	  kernel.  Saying Y here makes it possible, and safe, to use the
-	  same modules even after compiling a new kernel; this requires the
-	  program modprobe. All the software needed for module support is in
-	  the modutils package (check the file <file:Documentation/Changes>
-	  for location and latest version).  NOTE: if you say Y here but don't
-	  have the program genksyms (which is also contained in the above
-	  mentioned modutils package), then the building of your kernel will
-	  fail.  If you are going to use modules that are generated from
-	  non-kernel sources, you would benefit from this option.  Otherwise
-	  it's not that important.  So, N ought to be a safe bet.
+	help
+	  Without this option you will not be able to unload any
+	  modules (note that some modules may not be unloadable
+	  anyway), which makes your kernel slightly smaller and
+	  simpler.  If unsure, say Y.
+
+config MODULE_FORCE_UNLOAD
+	bool "Forced module unloading"
+	depends on MODULES && EXPERIMENTAL
+	help
+	  This option allows you to force a module to unload, even if the
+	  kernel believes it is unsafe: the kernel will remove the module
+	  without waiting for anyone to stop using it (using the -f option to
+	  rmmod).  This is mainly for kernel developers and desparate users.
+	  If unsure, say N.
 
 config KMOD
 	bool "Kernel module loader"
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Sun Nov 17 20:30:13 2002
+++ b/init/do_mounts.c	Sun Nov 17 20:30:13 2002
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/root_dev.h>
+#include <linux/mount.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -20,6 +21,8 @@
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
 
+#include <linux/raid/md.h>
+
 #define BUILD_CRAMDISK
 
 extern int get_filesystem_list(char * buf);
@@ -36,6 +39,10 @@
 extern asmlinkage long sys_mknod(const char *name, int mode, dev_t dev);
 extern asmlinkage long sys_umount(char *name, int flags);
 extern asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg);
+extern asmlinkage long sys_access(const char * filename, int mode);
+extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_getdents64(unsigned int fd, void * dirent,
+	unsigned int count);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
@@ -315,25 +322,125 @@
 }
 #endif
 
+#ifdef CONFIG_DEVFS_FS
+static int __init do_read_dir(int fd, void *buf, int len)
+{
+	long bytes, n;
+	char *p = buf;
+	lseek(fd, 0, 0);
+
+	for (bytes = 0, p = buf; bytes < len; bytes += n, p+=n) {
+		n = sys_getdents64(fd, p, len - bytes);
+		if (n < 0)
+			return -1;
+		if (n == 0)
+			return bytes;
+	}
+	return 0;
+}
+
+static void * __init read_dir(char *path, int *len)
+{
+	int size;
+	int fd = open(path, 0, 0);
+
+	*len = 0;
+	if (fd < 0)
+		return NULL;
+
+	for (size = 1<<9; size < (1<<18); size <<= 1) {
+		void *p = kmalloc(size, GFP_KERNEL);
+		int n;
+		if (!p)
+			break;
+		n = do_read_dir(fd, p, size);
+		if (n > 0) {
+			close(fd);
+			*len = n;
+			return p;
+		}
+		kfree(p);
+		if (n < 0)
+			break;
+	}
+	close(fd);
+	return NULL;
+}
+#endif
+
+struct linux_dirent64 {
+	u64		d_ino;
+	s64		d_off;
+	unsigned short	d_reclen;
+	unsigned char	d_type;
+	char		d_name[0];
+};
+
+static int __init find_in_devfs(char *path, dev_t dev)
+{
+#ifdef CONFIG_DEVFS_FS
+	struct stat buf;
+	char *end = path + strlen(path);
+	int rest = path + 64 - end;
+	int size;
+	char *p = read_dir(path, &size);
+	char *s;
+
+	if (!p)
+		return -1;
+	for (s = p; s < p + size; s += ((struct linux_dirent64 *)s)->d_reclen) {
+		struct linux_dirent64 *d = (struct linux_dirent64 *)s;
+		if (strlen(d->d_name) + 2 > rest)
+			continue;
+		switch (d->d_type) {
+			case DT_BLK:
+				sprintf(end, "/%s", d->d_name);
+				if (sys_newstat(path, &buf) < 0)
+					break;
+				if (!S_ISBLK(buf.st_mode))
+					break;
+				if (buf.st_rdev != dev)
+					break;
+				kfree(p);
+				return 0;
+			case DT_DIR:
+				if (strcmp(d->d_name, ".") == 0)
+					break;
+				if (strcmp(d->d_name, "..") == 0)
+					break;
+				sprintf(end, "/%s", d->d_name);
+				if (find_in_devfs(path, dev) < 0)
+					break;
+				kfree(p);
+				return 0;
+		}
+	}
+	kfree(p);
+#endif
+	return -1;
+}
+
 static int __init create_dev(char *name, dev_t dev, char *devfs_name)
 {
-	void *handle;
 	char path[64];
-	int n;
 
 	sys_unlink(name);
 	if (!do_devfs)
 		return sys_mknod(name, S_IFBLK|0600, dev);
 
-	handle = devfs_get_handle(NULL, !dev ? devfs_name : NULL,
-				  MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1);
-	if (!handle)
+	if (devfs_name && devfs_name[0]) {
+		if (strncmp(devfs_name, "/dev/", 5) == 0)
+			devfs_name += 5;
+		sprintf(path, "/dev/%s", devfs_name);
+		if (sys_access(path, 0) == 0)
+			return sys_symlink(devfs_name, name);
+	}
+	if (!dev)
 		return -1;
-	n = devfs_generate_path(handle, path + 5, sizeof (path) - 5);
-	devfs_put(handle);
-	if (n < 0)
+	strcpy(path, "/dev");
+	if (find_in_devfs(path, dev) < 0)
 		return -1;
-	return sys_symlink(path + n + 5, name);
+	return sys_symlink(path + 5, name);
 }
 
 #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
@@ -730,12 +837,22 @@
 	return rd_load_image("/dev/initrd");
 }
 
+static void __init md_run_setup(void);
+
 /*
  * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
  */
 void prepare_namespace(void)
 {
-	int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+	int is_floppy;
+
+#ifdef CONFIG_DEVFS_FS
+	sys_mount("devfs", "/dev", "devfs", 0, NULL);
+	do_devfs = 1;
+#endif
+
+	md_run_setup();
+
 	if (saved_root_name[0]) {
 		char *p = saved_root_name;
 		ROOT_DEV = name_to_dev_t(p);
@@ -743,17 +860,15 @@
 			p += 5;
 		strcpy(root_device_name, p);
 	}
+
+	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (!initrd_start)
 		mount_initrd = 0;
 	real_root_dev = ROOT_DEV;
 #endif
 
-#ifdef CONFIG_DEVFS_FS
-	sys_mount("devfs", "/dev", "devfs", 0, NULL);
-	do_devfs = 1;
-#endif
-
 	create_dev("/dev/root", ROOT_DEV, NULL);
 
 	/* This has to be before mounting root, because even readonly mount of reiserfs would replay
@@ -922,3 +1037,260 @@
 }
 
 #endif  /* BUILD_CRAMDISK && CONFIG_BLK_DEV_RAM */
+
+#ifdef CONFIG_BLK_DEV_MD
+
+/*
+ * When md (and any require personalities) are compiled into the kernel
+ * (not a module), arrays can be assembles are boot time using with AUTODETECT
+ * where specially marked partitions are registered with md_autodetect_dev(),
+ * and with MD_BOOT where devices to be collected are given on the boot line
+ * with md=.....
+ * The code for that is here.
+ */
+
+struct {
+	int set;
+	int noautodetect;
+} raid_setup_args __initdata;
+
+static struct {
+	char device_set [MAX_MD_DEVS];
+	int pers[MAX_MD_DEVS];
+	int chunk[MAX_MD_DEVS];
+	char *device_names[MAX_MD_DEVS];
+} md_setup_args __initdata;
+
+/*
+ * Parse the command-line parameters given our kernel, but do not
+ * actually try to invoke the MD device now; that is handled by
+ * md_setup_drive after the low-level disk drivers have initialised.
+ *
+ * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which
+ *             assigns the task of parsing integer arguments to the
+ *             invoked program now).  Added ability to initialise all
+ *             the MD devices (by specifying multiple "md=" lines)
+ *             instead of just one.  -- KTK
+ * 18May2000: Added support for persistent-superblock arrays:
+ *             md=n,0,factor,fault,device-list   uses RAID0 for device n
+ *             md=n,-1,factor,fault,device-list  uses LINEAR for device n
+ *             md=n,device-list      reads a RAID superblock from the devices
+ *             elements in device-list are read by name_to_kdev_t so can be
+ *             a hex number or something like /dev/hda1 /dev/sdb
+ * 2001-06-03: Dave Cinege <dcinege@psychosis.com>
+ *		Shifted name_to_kdev_t() and related operations to md_set_drive()
+ *		for later execution. Rewrote section to make devfs compatible.
+ */
+static int __init md_setup(char *str)
+{
+	int minor, level, factor, fault, pers;
+	char *pername = "";
+	char *str1 = str;
+
+	if (get_option(&str, &minor) != 2) {	/* MD Number */
+		printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
+		return 0;
+	}
+	if (minor >= MAX_MD_DEVS) {
+		printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor);
+		return 0;
+	} else if (md_setup_args.device_names[minor]) {
+		printk(KERN_WARNING "md: md=%d, Specified more than once. "
+		       "Replacing previous definition.\n", minor);
+	}
+	switch (get_option(&str, &level)) {	/* RAID Personality */
+	case 2: /* could be 0 or -1.. */
+		if (level == 0 || level == LEVEL_LINEAR) {
+			if (get_option(&str, &factor) != 2 ||	/* Chunk Size */
+					get_option(&str, &fault) != 2) {
+				printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
+				return 0;
+			}
+			md_setup_args.pers[minor] = level;
+			md_setup_args.chunk[minor] = 1 << (factor+12);
+			switch(level) {
+			case LEVEL_LINEAR:
+				pers = LINEAR;
+				pername = "linear";
+				break;
+			case 0:
+				pers = RAID0;
+				pername = "raid0";
+				break;
+			default:
+				printk(KERN_WARNING
+				       "md: The kernel has not been configured for raid%d support!\n",
+				       level);
+				return 0;
+			}
+			md_setup_args.pers[minor] = pers;
+			break;
+		}
+		/* FALL THROUGH */
+	case 1: /* the first device is numeric */
+		str = str1;
+		/* FALL THROUGH */
+	case 0:
+		md_setup_args.pers[minor] = 0;
+		pername="super-block";
+	}
+
+	printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
+		minor, pername, str);
+	md_setup_args.device_names[minor] = str;
+
+	return 1;
+}
+static void __init md_setup_drive(void)
+{
+	int minor, i;
+	dev_t dev;
+	dev_t devices[MD_SB_DISKS+1];
+
+	for (minor = 0; minor < MAX_MD_DEVS; minor++) {
+		int fd;
+		int err = 0;
+		char *devname;
+		mdu_disk_info_t dinfo;
+		char name[16], devfs_name[16];
+
+		if (!(devname = md_setup_args.device_names[minor]))
+			continue;
+		
+		sprintf(name, "/dev/md%d", minor);
+		sprintf(devfs_name, "/dev/md/%d", minor);
+		create_dev(name, MKDEV(MD_MAJOR, minor), devfs_name);
+		for (i = 0; i < MD_SB_DISKS && devname != 0; i++) {
+			char *p;
+			char comp_name[64];
+			struct stat buf;
+
+			p = strchr(devname, ',');
+			if (p)
+				*p++ = 0;
+
+			dev = name_to_dev_t(devname);
+			if (strncmp(devname, "/dev/", 5))
+				devname += 5;
+			snprintf(comp_name, 63, "/dev/%s", devname);
+			if (sys_newstat(comp_name, &buf) == 0 &&
+							S_ISBLK(buf.st_mode))
+				dev = buf.st_rdev;
+			if (!dev) {
+				printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
+				break;
+			}
+
+			devices[i] = dev;
+			md_setup_args.device_set[minor] = 1;
+
+			devname = p;
+		}
+		devices[i] = 0;
+
+		if (!md_setup_args.device_set[minor])
+			continue;
+
+		printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
+
+		fd = open(name, 0, 0);
+		if (fd < 0) {
+			printk(KERN_ERR "md: open failed - cannot start array %d\n", minor);
+			continue;
+		}
+		if (sys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) {
+			printk(KERN_WARNING
+			       "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
+			       minor);
+			close(fd);
+			continue;
+		}
+
+		if (md_setup_args.pers[minor]) {
+			/* non-persistent */
+			mdu_array_info_t ainfo;
+			ainfo.level = pers_to_level(md_setup_args.pers[minor]);
+			ainfo.size = 0;
+			ainfo.nr_disks =0;
+			ainfo.raid_disks =0;
+			while (devices[ainfo.raid_disks])
+				ainfo.raid_disks++;
+			ainfo.md_minor =minor;
+			ainfo.not_persistent = 1;
+
+			ainfo.state = (1 << MD_SB_CLEAN);
+			ainfo.layout = 0;
+			ainfo.chunk_size = md_setup_args.chunk[minor];
+			err = sys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo);
+			for (i = 0; !err && i <= MD_SB_DISKS; i++) {
+				dev = devices[i];
+				if (!dev)
+					break;
+				dinfo.number = i;
+				dinfo.raid_disk = i;
+				dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
+				dinfo.major = MAJOR(dev);
+				dinfo.minor = MINOR(dev);
+				err = sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo);
+			}
+		} else {
+			/* persistent */
+			for (i = 0; i <= MD_SB_DISKS; i++) {
+				dev = devices[i];
+				if (!dev)
+					break;
+				dinfo.major = MAJOR(dev);
+				dinfo.minor = MINOR(dev);
+				sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo);
+			}
+		}
+		if (!err)
+			err = sys_ioctl(fd, RUN_ARRAY, 0);
+		if (err)
+			printk(KERN_WARNING "md: starting md%d failed\n", minor);
+		close(fd);
+	}
+}
+
+static int __init raid_setup(char *str)
+{
+	int len, pos;
+
+	len = strlen(str) + 1;
+	pos = 0;
+
+	while (pos < len) {
+		char *comma = strchr(str+pos, ',');
+		int wlen;
+		if (comma)
+			wlen = (comma-str)-pos;
+		else	wlen = (len-1)-pos;
+
+		if (!strncmp(str, "noautodetect", wlen))
+			raid_setup_args.noautodetect = 1;
+		pos += wlen+1;
+	}
+	raid_setup_args.set = 1;
+	return 1;
+}
+
+__setup("raid=", raid_setup);
+__setup("md=", md_setup);
+#endif
+
+static void __init md_run_setup(void)
+{
+#ifdef CONFIG_BLK_DEV_MD
+	create_dev("/dev/md0", MKDEV(MD_MAJOR, 0), "md/0");
+	if (raid_setup_args.noautodetect)
+		printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
+	else {
+		int fd = open("/dev/md0", 0, 0);
+		if (fd >= 0) {
+			sys_ioctl(fd, RAID_AUTORUN, 0);
+			close(fd);
+		}
+	}
+	md_setup_drive();
+#endif
+}
diff -Nru a/init/initramfs.c b/init/initramfs.c
--- a/init/initramfs.c	Sun Nov 17 20:30:02 2002
+++ b/init/initramfs.c	Sun Nov 17 20:30:02 2002
@@ -6,6 +6,7 @@
 #include <linux/fcntl.h>
 #include <linux/unistd.h>
 #include <linux/delay.h>
+#include <linux/string.h>
 
 static void __init error(char *x)
 {
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Sun Nov 17 20:30:04 2002
+++ b/init/main.c	Sun Nov 17 20:30:04 2002
@@ -63,6 +63,7 @@
 extern void init_modules(void);
 extern void sock_init(void);
 extern void fork_init(unsigned long);
+extern void extable_init(void);
 extern void mca_init(void);
 extern void sbus_init(void);
 extern void sysctl_init(void);
@@ -394,6 +395,7 @@
 	printk("Kernel command line: %s\n", saved_command_line);
 	parse_options(command_line);
 	trap_init();
+	extable_init();
 	rcu_init();
 	init_IRQ();
 	sched_init();
@@ -406,9 +408,6 @@
 	 * this. But we do want output early, in case something goes wrong.
 	 */
 	console_init();
-#ifdef CONFIG_MODULES
-	init_modules();
-#endif
 	profile_init();
 	kmem_cache_init();
 	local_irq_enable();
@@ -456,6 +455,8 @@
 }
 
 struct task_struct *child_reaper = &init_task;
+
+extern initcall_t __initcall_start, __initcall_end;
 
 static void __init do_initcalls(void)
 {
diff -Nru a/ipc/msg.c b/ipc/msg.c
--- a/ipc/msg.c	Sun Nov 17 20:30:02 2002
+++ b/ipc/msg.c	Sun Nov 17 20:30:02 2002
@@ -115,7 +115,7 @@
 	}
 
 	msq->q_stime = msq->q_rtime = 0;
-	msq->q_ctime = CURRENT_TIME;
+	msq->q_ctime = get_seconds();
 	msq->q_cbytes = msq->q_qnum = 0;
 	msq->q_qbytes = msg_ctlmnb;
 	msq->q_lspid = msq->q_lrpid = 0;
@@ -532,7 +532,7 @@
 		ipcp->gid = setbuf.gid;
 		ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | 
 			(S_IRWXUGO & setbuf.mode);
-		msq->q_ctime = CURRENT_TIME;
+		msq->q_ctime = get_seconds();
 		/* sleeping receivers might be excluded by
 		 * stricter permissions.
 		 */
@@ -599,7 +599,7 @@
 			} else {
 				msr->r_msg = msg;
 				msq->q_lrpid = msr->r_tsk->pid;
-				msq->q_rtime = CURRENT_TIME;
+				msq->q_rtime = get_seconds();
 				wake_up_process(msr->r_tsk);
 				return 1;
 			}
@@ -669,7 +669,7 @@
 	}
 
 	msq->q_lspid = current->pid;
-	msq->q_stime = CURRENT_TIME;
+	msq->q_stime = get_seconds();
 
 	if(!pipelined_send(msq,msg)) {
 		/* noone is waiting for this message, enqueue it */
@@ -760,7 +760,7 @@
 		}
 		list_del(&msg->m_list);
 		msq->q_qnum--;
-		msq->q_rtime = CURRENT_TIME;
+		msq->q_rtime = get_seconds();
 		msq->q_lrpid = current->pid;
 		msq->q_cbytes -= msg->m_ts;
 		atomic_sub(msg->m_ts,&msg_bytes);
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	Sun Nov 17 20:30:12 2002
+++ b/ipc/sem.c	Sun Nov 17 20:30:12 2002
@@ -155,7 +155,7 @@
 	sma->sem_pending_last = &sma->sem_pending;
 	/* sma->undo = NULL; */
 	sma->sem_nsems = nsems;
-	sma->sem_ctime = CURRENT_TIME;
+	sma->sem_ctime = get_seconds();
 	sem_unlock(sma);
 
 	return sem_buildid(id, sma->sem_perm.seq);
@@ -296,7 +296,7 @@
 		goto undo;
 	}
 
-	sma->sem_otime = CURRENT_TIME;
+	sma->sem_otime = get_seconds();
 	return 0;
 
 out_of_range:
@@ -605,7 +605,7 @@
 		for (un = sma->undo; un; un = un->id_next)
 			for (i = 0; i < nsems; i++)
 				un->semadj[i] = 0;
-		sma->sem_ctime = CURRENT_TIME;
+		sma->sem_ctime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
 		err = 0;
@@ -657,7 +657,7 @@
 			un->semadj[semnum] = 0;
 		curr->semval = val;
 		curr->sempid = current->pid;
-		sma->sem_ctime = CURRENT_TIME;
+		sma->sem_ctime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
 		err = 0;
@@ -749,7 +749,7 @@
 		ipcp->gid = setbuf.gid;
 		ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
 				| (setbuf.mode & S_IRWXUGO);
-		sma->sem_ctime = CURRENT_TIME;
+		sma->sem_ctime = get_seconds();
 		sem_unlock(sma);
 		err = 0;
 		break;
@@ -1228,7 +1228,7 @@
 				sem->semval = 0; /* shouldn't happen */
 			sem->sempid = current->pid;
 		}
-		sma->sem_otime = CURRENT_TIME;
+		sma->sem_otime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
 next_entry:
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Sun Nov 17 20:30:14 2002
+++ b/ipc/shm.c	Sun Nov 17 20:30:14 2002
@@ -88,7 +88,7 @@
 
 	if(!(shp = shm_lock(id)))
 		BUG();
-	shp->shm_atim = CURRENT_TIME;
+	shp->shm_atim = get_seconds();
 	shp->shm_lprid = current->pid;
 	shp->shm_nattch++;
 	shm_unlock(shp);
@@ -137,7 +137,7 @@
 	if(!(shp = shm_lock(id)))
 		BUG();
 	shp->shm_lprid = current->pid;
-	shp->shm_dtim = CURRENT_TIME;
+	shp->shm_dtim = get_seconds();
 	shp->shm_nattch--;
 	if(shp->shm_nattch == 0 &&
 	   shp->shm_flags & SHM_DEST)
@@ -212,7 +212,7 @@
 	shp->shm_cprid = current->pid;
 	shp->shm_lprid = 0;
 	shp->shm_atim = shp->shm_dtim = 0;
-	shp->shm_ctim = CURRENT_TIME;
+	shp->shm_ctim = get_seconds();
 	shp->shm_segsz = size;
 	shp->shm_nattch = 0;
 	shp->id = shm_buildid(id,shp->shm_perm.seq);
@@ -566,7 +566,7 @@
 		shp->shm_perm.gid = setbuf.gid;
 		shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)
 			| (setbuf.mode & S_IRWXUGO);
-		shp->shm_ctim = CURRENT_TIME;
+		shp->shm_ctim = get_seconds();
 		break;
 	}
 
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	Sun Nov 17 20:30:04 2002
+++ b/kernel/Makefile	Sun Nov 17 20:30:04 2002
@@ -4,18 +4,18 @@
 
 export-objs = signal.o sys.o kmod.o workqueue.o ksyms.o pm.o exec_domain.o \
 		printk.o platform.o suspend.o dma.o module.o cpufreq.o \
-		profile.o rcupdate.o
+		profile.o rcupdate.o intermodule.o
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
-	    module.o exit.o itimer.o time.o softirq.o resource.o \
+	    exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \
-	    rcupdate.o
+	    rcupdate.o intermodule.o
 
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o
 obj-$(CONFIG_UID16) += uid16.o
-obj-$(CONFIG_MODULES) += ksyms.o
+obj-$(CONFIG_MODULES) += ksyms.o module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += pm.o
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c
--- a/kernel/exec_domain.c	Sun Nov 17 20:30:14 2002
+++ b/kernel/exec_domain.c	Sun Nov 17 20:30:14 2002
@@ -210,8 +210,8 @@
 	read_lock(&exec_domains_lock);
 	for (ep = exec_domains; ep && len < PAGE_SIZE - 80; ep = ep->next)
 		len += sprintf(page + len, "%d-%d\t%-16s\t[%s]\n",
-			ep->pers_low, ep->pers_high, ep->name,
-			ep->module ? ep->module->name : "kernel");
+			       ep->pers_low, ep->pers_high, ep->name,
+			       module_name(ep->module));
 	read_unlock(&exec_domains_lock);
 	return (len);
 }
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Sun Nov 17 20:30:15 2002
+++ b/kernel/exit.c	Sun Nov 17 20:30:15 2002
@@ -20,6 +20,7 @@
 #include <linux/binfmts.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Sun Nov 17 20:30:03 2002
+++ b/kernel/fork.c	Sun Nov 17 20:30:03 2002
@@ -28,6 +28,7 @@
 #include <linux/security.h>
 #include <linux/futex.h>
 #include <linux/ptrace.h>
+#include <linux/mount.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -205,12 +206,14 @@
 	return tsk;
 }
 
-static inline int dup_mmap(struct mm_struct * mm)
+#ifdef CONFIG_MMU
+static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 {
 	struct vm_area_struct * mpnt, *tmp, **pprev;
 	int retval;
 	unsigned long charge = 0;
 
+	down_write(&oldmm->mmap_sem);
 	flush_cache_mm(current->mm);
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
@@ -287,11 +290,29 @@
 
 out:
 	flush_tlb_mm(current->mm);
+	up_write(&oldmm->mmap_sem);
 	return retval;
 fail_nomem:
 	vm_unacct_memory(charge);
 	goto out;
 }
+static inline int mm_alloc_pgd(struct mm_struct * mm)
+{
+	mm->pgd = pgd_alloc(mm);
+	if (unlikely(!mm->pgd))
+		return -ENOMEM;
+	return 0;
+}
+
+static inline void mm_free_pgd(struct mm_struct * mm)
+{
+	pgd_free(mm->pgd);
+}
+#else
+#define dup_mmap(mm, oldmm)	(0)
+#define mm_alloc_pgd(mm)	(0)
+#define mm_free_pgd(mm)
+#endif /* CONFIG_MMU */
 
 spinlock_t mmlist_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 int mmlist_nr;
@@ -314,8 +335,7 @@
 	mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
 
-	mm->pgd = pgd_alloc(mm);
-	if (mm->pgd)
+	if (likely(!mm_alloc_pgd(mm)))
 		return mm;
 	free_mm(mm);
 	return NULL;
@@ -344,8 +364,8 @@
  */
 inline void __mmdrop(struct mm_struct *mm)
 {
-	if (mm == &init_mm) BUG();
-	pgd_free(mm->pgd);
+	BUG_ON(mm == &init_mm);
+	mm_free_pgd(mm);
 	destroy_context(mm);
 	free_mm(mm);
 }
@@ -388,12 +408,15 @@
 		complete(vfork_done);
 	}
 	if (tsk->user_tid) {
+		int * user_tid = tsk->user_tid;
+		tsk->user_tid = NULL;
+
 		/*
 		 * We dont check the error code - if userspace has
 		 * not set up a proper pointer then tough luck.
 		 */
-		put_user(0, tsk->user_tid);
-		sys_futex((unsigned long)tsk->user_tid, FUTEX_WAKE, 1, NULL);
+		put_user(0, user_tid);
+		sys_futex((unsigned long)user_tid, FUTEX_WAKE, 1, NULL);
 	}
 }
 
@@ -444,10 +467,7 @@
 	if (init_new_context(tsk,mm))
 		goto free_pt;
 
-	down_write(&oldmm->mmap_sem);
-	retval = dup_mmap(mm);
-	up_write(&oldmm->mmap_sem);
-
+	retval = dup_mmap(mm, oldmm);
 	if (retval)
 		goto free_pt;
 
@@ -657,6 +677,13 @@
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
 	p->flags = new_flags;
+}
+
+asmlinkage int sys_set_tid_address(int *user_tid)
+{
+	current->user_tid = user_tid;
+
+	return current->pid;
 }
 
 /*
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	Sun Nov 17 20:30:12 2002
+++ b/kernel/futex.c	Sun Nov 17 20:30:12 2002
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/futex.h>
 #include <linux/vcache.h>
+#include <linux/mount.h>
 
 #define FUTEX_HASHBITS 8
 
diff -Nru a/kernel/intermodule.c b/kernel/intermodule.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/kernel/intermodule.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,183 @@
+/* Deprecated, do not use.  Moved from module.c to here. --RR */
+
+/* Written by Keith Owens <kaos@ocs.com.au> Oct 2000 */
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+/* inter_module functions are always available, even when the kernel is
+ * compiled without modules.  Consumers of inter_module_xxx routines
+ * will always work, even when both are built into the kernel, this
+ * approach removes lots of #ifdefs in mainline code.
+ */
+
+static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
+static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
+static int kmalloc_failed;
+
+struct inter_module_entry {
+	struct list_head list;
+	const char *im_name;
+	struct module *owner;
+	const void *userdata;
+};
+
+/**
+ * inter_module_register - register a new set of inter module data.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ * @owner: module that is registering the data, always use THIS_MODULE
+ * @userdata: pointer to arbitrary userdata to be registered
+ *
+ * Description: Check that the im_name has not already been registered,
+ * complain if it has.  For new data, add it to the inter_module_entry
+ * list.
+ */
+void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime, *ime_new;
+
+	if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
+		/* Overloaded kernel, not fatal */
+		printk(KERN_ERR
+			"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
+			im_name);
+		kmalloc_failed = 1;
+		return;
+	}
+	memset(ime_new, 0, sizeof(*ime_new));
+	ime_new->im_name = im_name;
+	ime_new->owner = owner;
+	ime_new->userdata = userdata;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			spin_unlock(&ime_lock);
+			kfree(ime_new);
+			/* Program logic error, fatal */
+			printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
+			BUG();
+		}
+	}
+	list_add(&(ime_new->list), &ime_list);
+	spin_unlock(&ime_lock);
+}
+
+/**
+ * inter_module_unregister - unregister a set of inter module data.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: Check that the im_name has been registered, complain if
+ * it has not.  For existing data, remove it from the
+ * inter_module_entry list.
+ */
+void inter_module_unregister(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			list_del(&(ime->list));
+			spin_unlock(&ime_lock);
+			kfree(ime);
+			return;
+		}
+	}
+	spin_unlock(&ime_lock);
+	if (kmalloc_failed) {
+		printk(KERN_ERR
+			"inter_module_unregister: no entry for '%s', "
+			"probably caused by previous kmalloc failure\n",
+			im_name);
+		return;
+	}
+	else {
+		/* Program logic error, fatal */
+		printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
+		BUG();
+	}
+}
+
+/**
+ * inter_module_get - return arbitrary userdata from another module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: If the im_name has not been registered, return NULL.
+ * Try to increment the use count on the owning module, if that fails
+ * then return NULL.  Otherwise return the userdata.
+ */
+const void *inter_module_get(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+	const void *result = NULL;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			if (try_inc_mod_count(ime->owner))
+				result = ime->userdata;
+			break;
+		}
+	}
+	spin_unlock(&ime_lock);
+	return(result);
+}
+
+/**
+ * inter_module_get_request - im get with automatic request_module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ * @modname: module that is expected to register im_name
+ *
+ * Description: If inter_module_get fails, do request_module then retry.
+ */
+const void *inter_module_get_request(const char *im_name, const char *modname)
+{
+	const void *result = inter_module_get(im_name);
+	if (!result) {
+		request_module(modname);
+		result = inter_module_get(im_name);
+	}
+	return(result);
+}
+
+/**
+ * inter_module_put - release use of data from another module.
+ * @im_name: an arbitrary string to identify the data, must be unique
+ *
+ * Description: If the im_name has not been registered, complain,
+ * otherwise decrement the use count on the owning module.
+ */
+void inter_module_put(const char *im_name)
+{
+	struct list_head *tmp;
+	struct inter_module_entry *ime;
+
+	spin_lock(&ime_lock);
+	list_for_each(tmp, &ime_list) {
+		ime = list_entry(tmp, struct inter_module_entry, list);
+		if (strcmp(ime->im_name, im_name) == 0) {
+			if (ime->owner)
+				__MOD_DEC_USE_COUNT(ime->owner);
+			spin_unlock(&ime_lock);
+			return;
+		}
+	}
+	spin_unlock(&ime_lock);
+	printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
+	BUG();
+}
+
+EXPORT_SYMBOL(inter_module_register);
+EXPORT_SYMBOL(inter_module_unregister);
+EXPORT_SYMBOL(inter_module_get);
+EXPORT_SYMBOL(inter_module_get_request);
+EXPORT_SYMBOL(inter_module_put);
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Sun Nov 17 20:30:12 2002
+++ b/kernel/kmod.c	Sun Nov 17 20:30:12 2002
@@ -29,7 +29,7 @@
 #include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/workqueue.h>
-
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 extern int max_threads, system_running;
@@ -155,7 +155,7 @@
 static int exec_modprobe(void * module_name)
 {
 	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-	char *argv[] = { modprobe_path, "-s", "-k", "--", (char*)module_name, NULL };
+	char *argv[] = { modprobe_path, "--", (char*)module_name, NULL };
 	int ret;
 
 	if (!system_running)
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sun Nov 17 20:30:02 2002
+++ b/kernel/ksyms.c	Sun Nov 17 20:30:02 2002
@@ -53,6 +53,7 @@
 #include <linux/percpu.h>
 #include <linux/smp_lock.h>
 #include <linux/dnotify.h>
+#include <linux/mount.h>
 #include <asm/checksum.h>
 
 #if defined(CONFIG_PROC_FS)
@@ -71,14 +72,6 @@
 };
 #endif
 
-
-EXPORT_SYMBOL(inter_module_register);
-EXPORT_SYMBOL(inter_module_unregister);
-EXPORT_SYMBOL(inter_module_get);
-EXPORT_SYMBOL(inter_module_get_request);
-EXPORT_SYMBOL(inter_module_put);
-EXPORT_SYMBOL(try_inc_mod_count);
-
 /* process memory management */
 EXPORT_SYMBOL(do_mmap_pgoff);
 EXPORT_SYMBOL(do_munmap);
@@ -174,7 +167,7 @@
 EXPORT_SYMBOL(d_alloc_anon);
 EXPORT_SYMBOL(d_splice_alias);
 EXPORT_SYMBOL(d_lookup);
-EXPORT_SYMBOL(__d_path);
+EXPORT_SYMBOL(d_path);
 EXPORT_SYMBOL(mark_buffer_dirty);
 EXPORT_SYMBOL(end_buffer_io_sync);
 EXPORT_SYMBOL(__mark_inode_dirty);
@@ -276,7 +269,7 @@
 EXPORT_SYMBOL(generic_file_llseek);
 EXPORT_SYMBOL(remote_llseek);
 EXPORT_SYMBOL(no_llseek);
-EXPORT_SYMBOL(__pollwait);
+EXPORT_SYMBOL(poll_initwait);
 EXPORT_SYMBOL(poll_freewait);
 EXPORT_SYMBOL(ROOT_DEV);
 EXPORT_SYMBOL(find_get_page);
@@ -601,3 +594,5 @@
 
 /* debug */
 EXPORT_SYMBOL(dump_stack);
+
+EXPORT_SYMBOL(current_kernel_time); 
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Sun Nov 17 20:30:15 2002
+++ b/kernel/module.c	Sun Nov 17 20:30:15 2002
@@ -1,1376 +1,1206 @@
+/* Rewritten by Rusty Russell, on the backs of many others...
+   Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
+
+    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
+*/
 #include <linux/config.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <asm/module.h>
-#include <asm/uaccess.h>
-#include <linux/kallsyms.h>
-#include <linux/vmalloc.h>
-#include <linux/smp_lock.h>
-#include <asm/pgalloc.h>
+#include <linux/moduleloader.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
 #include <linux/seq_file.h>
-#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/rcupdate.h>
+#include <linux/cpu.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 
-/*
- * Originally by Anonymous (as far as I know...)
- * Linux version by Bas Laarhoven <bas@vimec.nl>
- * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
- * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
- * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
- * Add MOD_INITIALIZING Keith Owens <kaos@ocs.com.au> Nov 1999
- * Add kallsyms support, Keith Owens <kaos@ocs.com.au> Apr 2000
- * Add asm/module support, IA64 has special requirements.  Keith Owens <kaos@ocs.com.au> Sep 2000
- * Fix assorted bugs in module verification.  Keith Owens <kaos@ocs.com.au> Sep 2000
- * Fix sys_init_module race, Andrew Morton <andrewm@uow.edu.au> Oct 2000
- *     http://www.uwsg.iu.edu/hypermail/linux/kernel/0008.3/0379.html
- * Replace xxx_module_symbol with inter_module_xxx.  Keith Owens <kaos@ocs.com.au> Oct 2000
- * Add a module list lock for kernel fault race fixing. Alan Cox <alan@redhat.com>
- *
- * This source is covered by the GNU GPL, the same as all kernel sources.
- */
-
-#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
-
-extern struct module_symbol __start___ksymtab[];
-extern struct module_symbol __stop___ksymtab[];
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , a...)
+#endif
 
 extern const struct exception_table_entry __start___ex_table[];
 extern const struct exception_table_entry __stop___ex_table[];
+extern const struct kernel_symbol __start___ksymtab[];
+extern const struct kernel_symbol __stop___ksymtab[];
 
-extern const char __start___kallsyms[] __attribute__((weak));
-extern const char __stop___kallsyms[] __attribute__((weak));
-
-/* modutils uses these exported symbols to figure out if
-   kallsyms support is present */
+/* Protects extables and symbol tables */
+spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
 
-EXPORT_SYMBOL(__start___kallsyms);
-EXPORT_SYMBOL(__stop___kallsyms);
+/* The exception and symbol tables: start with kernel only. */
+LIST_HEAD(extables);
+static LIST_HEAD(symbols);
+
+static struct exception_table kernel_extable;
+static struct kernel_symbol_group kernel_symbols;
+
+/* List of modules, protected by module_mutex */
+static DECLARE_MUTEX(module_mutex);
+LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */
 
-struct module kernel_module =
-{
-	.size_of_struct		= sizeof(struct module),
-	.name 			= "",
-	.uc	 		= {ATOMIC_INIT(1)},
-	.flags			= MOD_RUNNING,
-	.syms			= __start___ksymtab,
-	.ex_table_start		= __start___ex_table,
-	.ex_table_end		= __stop___ex_table,
-	.kallsyms_start		= __start___kallsyms,
-	.kallsyms_end		= __stop___kallsyms,
+/* Convenient structure for holding init and core sizes */
+struct sizes
+{
+	unsigned long init_size;
+	unsigned long core_size;
 };
 
-struct module *module_list = &kernel_module;
-
-#endif	/* defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) */
-
-/* inter_module functions are always available, even when the kernel is
- * compiled without modules.  Consumers of inter_module_xxx routines
- * will always work, even when both are built into the kernel, this
- * approach removes lots of #ifdefs in mainline code.
- */
-
-static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
-static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
-static int kmalloc_failed;
-
-/*
- *	This lock prevents modifications that might race the kernel fault
- *	fixups. It does not prevent reader walks that the modules code
- *	does. The kernel lock does that.
- *
- *	Since vmalloc fault fixups occur in any context this lock is taken
- *	irqsave at all times.
- */
+/* Find a symbol, return value and the symbol group */
+static unsigned long __find_symbol(const char *name,
+				   struct kernel_symbol_group **group)
+{
+	struct kernel_symbol_group *ks;
  
-spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
+	list_for_each_entry(ks, &symbols, list) {
+ 		unsigned int i;
 
-/**
- * inter_module_register - register a new set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @owner: module that is registering the data, always use THIS_MODULE
- * @userdata: pointer to arbitrary userdata to be registered
- *
- * Description: Check that the im_name has not already been registered,
- * complain if it has.  For new data, add it to the inter_module_entry
- * list.
- */
-void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime, *ime_new;
-
-	if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
-		/* Overloaded kernel, not fatal */
-		printk(KERN_ERR
-			"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
-			im_name);
-		kmalloc_failed = 1;
-		return;
-	}
-	memset(ime_new, 0, sizeof(*ime_new));
-	ime_new->im_name = im_name;
-	ime_new->owner = owner;
-	ime_new->userdata = userdata;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			spin_unlock(&ime_lock);
-			kfree(ime_new);
-			/* Program logic error, fatal */
-			printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
-			BUG();
-		}
-	}
-	list_add(&(ime_new->list), &ime_list);
-	spin_unlock(&ime_lock);
-}
-
-/**
- * inter_module_unregister - unregister a set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: Check that the im_name has been registered, complain if
- * it has not.  For existing data, remove it from the
- * inter_module_entry list.
- */
-void inter_module_unregister(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			list_del(&(ime->list));
-			spin_unlock(&ime_lock);
-			kfree(ime);
-			return;
-		}
-	}
-	spin_unlock(&ime_lock);
-	if (kmalloc_failed) {
-		printk(KERN_ERR
-			"inter_module_unregister: no entry for '%s', "
-			"probably caused by previous kmalloc failure\n",
-			im_name);
-		return;
-	}
-	else {
-		/* Program logic error, fatal */
-		printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
-		BUG();
-	}
-}
-
-/**
- * inter_module_get - return arbitrary userdata from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, return NULL.
- * Try to increment the use count on the owning module, if that fails
- * then return NULL.  Otherwise return the userdata.
- */
-const void *inter_module_get(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-	const void *result = NULL;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			if (try_inc_mod_count(ime->owner))
-				result = ime->userdata;
-			break;
+		for (i = 0; i < ks->num_syms; i++) {
+			if (strcmp(ks->syms[i].name, name) == 0) {
+				*group = ks;
+				return ks->syms[i].value;
+			}
 		}
 	}
-	spin_unlock(&ime_lock);
-	return(result);
+	DEBUGP("Failed to find symbol %s\n", name);
+ 	return 0;
 }
 
-/**
- * inter_module_get_request - im get with automatic request_module.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @modname: module that is expected to register im_name
- *
- * Description: If inter_module_get fails, do request_module then retry.
- */
-const void *inter_module_get_request(const char *im_name, const char *modname)
-{
-	const void *result = inter_module_get(im_name);
-	if (!result) {
-		request_module(modname);
-		result = inter_module_get(im_name);
-	}
-	return(result);
-}
-
-/**
- * inter_module_put - release use of data from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, complain,
- * otherwise decrement the use count on the owning module.
- */
-void inter_module_put(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			if (ime->owner)
-				__MOD_DEC_USE_COUNT(ime->owner);
-			spin_unlock(&ime_lock);
-			return;
-		}
+/* Find a symbol in this elf symbol table */
+static unsigned long find_local_symbol(Elf_Shdr *sechdrs,
+				       unsigned int symindex,
+				       const char *strtab,
+				       const char *name)
+{
+	unsigned int i;
+	Elf_Sym *sym = (void *)sechdrs[symindex].sh_offset;
+
+	/* Search (defined) internal symbols first. */
+	for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) {
+		if (sym[i].st_shndx != SHN_UNDEF
+		    && strcmp(name, strtab + sym[i].st_name) == 0)
+			return sym[i].st_value;
 	}
-	spin_unlock(&ime_lock);
-	printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
-	BUG();
+	return 0;
 }
 
-
-#if defined(CONFIG_MODULES)	/* The rest of the source */
-
-static long get_mod_name(const char *user_name, char **buf);
-static void put_mod_name(char *buf);
-struct module *find_module(const char *name);
-void free_module(struct module *, int tag_freed);
-
-
-/*
- * Called at boot time
- */
-
-void __init init_modules(void)
+/* Search for module by name: must hold module_mutex. */
+static struct module *find_module(const char *name)
 {
-	kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;
+	struct module *mod;
 
-	arch_init_modules(&kernel_module);
+	list_for_each_entry(mod, &modules, list) {
+		if (strcmp(mod->name, name) == 0)
+			return mod;
+	}
+	return NULL;
 }
 
-/*
- * Copy the name of a module from user space.
- */
-
-static inline long
-get_mod_name(const char *user_name, char **buf)
+#ifdef CONFIG_MODULE_UNLOAD
+/* Init the unload section of the module. */
+static void module_unload_init(struct module *mod)
 {
-	unsigned long page;
-	long retval;
-
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
-	if (retval > 0) {
-		if (retval < PAGE_SIZE) {
-			*buf = (char *)page;
-			return retval;
-		}
-		retval = -ENAMETOOLONG;
-	} else if (!retval)
-		retval = -EINVAL;
+	unsigned int i;
 
-	free_page(page);
-	return retval;
+	INIT_LIST_HEAD(&mod->modules_which_use_me);
+	for (i = 0; i < NR_CPUS; i++)
+		atomic_set(&mod->ref[i].count, 0);
+	/* Backwards compatibility macros put refcount during init. */
+	mod->waiter = current;
 }
 
-static inline void
-put_mod_name(char *buf)
+/* modules using other modules */
+struct module_use
 {
-	free_page((unsigned long)buf);
-}
-
-/*
- * Allocate space for a module.
- */
+	struct list_head list;
+	struct module *module_which_uses;
+};
 
-asmlinkage unsigned long
-sys_create_module(const char *name_user, size_t size)
+/* Does a already use b? */
+static int already_uses(struct module *a, struct module *b)
 {
-	char *name;
-	long namelen, error;
-	struct module *mod;
-	unsigned long flags;
-
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
-	lock_kernel();
-	if ((namelen = get_mod_name(name_user, &name)) < 0) {
-		error = namelen;
-		goto err0;
-	}
-	if (size < sizeof(struct module)+namelen) {
-		error = -EINVAL;
-		goto err1;
-	}
-	if (find_module(name) != NULL) {
-		error = -EEXIST;
-		goto err1;
-	}
-	if ((mod = (struct module *)module_map(size)) == NULL) {
-		error = -ENOMEM;
-		goto err1;
-	}
-
-	memset(mod, 0, sizeof(*mod));
-	mod->size_of_struct = sizeof(*mod);
-	mod->name = (char *)(mod + 1);
-	mod->size = size;
-	memcpy((char*)(mod+1), name, namelen+1);
-
-	put_mod_name(name);
-
-	spin_lock_irqsave(&modlist_lock, flags);
-	mod->next = module_list;
-	module_list = mod;	/* link it in */
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	struct module_use *use;
 
-	error = (long) mod;
-	goto err0;
-err1:
-	put_mod_name(name);
-err0:
-	unlock_kernel();
-	return error;
+	list_for_each_entry(use, &b->modules_which_use_me, list) {
+		if (use->module_which_uses == a) {
+			DEBUGP("%s uses %s!\n", a->name, b->name);
+			return 1;
+		}
+	}
+	DEBUGP("%s does not use %s!\n", a->name, b->name);
+	return 0;
 }
 
-/*
- * Initialize a module.
- */
-
-asmlinkage long
-sys_init_module(const char *name_user, struct module *mod_user)
+/* Module a uses b */
+static int use_module(struct module *a, struct module *b)
 {
-	struct module mod_tmp, *mod;
-	char *name, *n_name, *name_tmp = NULL;
-	long namelen, n_namelen, i, error;
-	unsigned long mod_user_size;
-	struct module_ref *dep;
+	struct module_use *use;
+	if (b == NULL || already_uses(a, b)) return 1;
 
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
-	lock_kernel();
-	if ((namelen = get_mod_name(name_user, &name)) < 0) {
-		error = namelen;
-		goto err0;
-	}
-	if ((mod = find_module(name)) == NULL) {
-		error = -ENOENT;
-		goto err1;
-	}
-
-	/* Check module header size.  We allow a bit of slop over the
-	   size we are familiar with to cope with a version of insmod
-	   for a newer kernel.  But don't over do it. */
-	if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
-		goto err1;
-	if (mod_user_size < (unsigned long)&((struct module *)0L)->persist_start
-	    || mod_user_size > sizeof(struct module) + 16*sizeof(void*)) {
-		printk(KERN_ERR "init_module: Invalid module header size.\n"
-		       KERN_ERR "A new version of the modutils is likely "
-				"needed.\n");
-		error = -EINVAL;
-		goto err1;
-	}
-
-	/* Hold the current contents while we play with the user's idea
-	   of righteousness.  */
-	mod_tmp = *mod;
-	name_tmp = kmalloc(strlen(mod->name) + 1, GFP_KERNEL);	/* Where's kstrdup()? */
-	if (name_tmp == NULL) {
-		error = -ENOMEM;
-		goto err1;
-	}
-	strcpy(name_tmp, mod->name);
-
-	error = copy_from_user(mod, mod_user, mod_user_size);
-	if (error) {
-		error = -EFAULT;
-		goto err2;
-	}
-
-	/* Sanity check the size of the module.  */
-	error = -EINVAL;
-
-	if (mod->size > mod_tmp.size) {
-		printk(KERN_ERR "init_module: Size of initialized module "
-				"exceeds size of created module.\n");
-		goto err2;
-	}
-
-	/* Make sure all interesting pointers are sane.  */
-
-	if (!mod_bound(mod->name, namelen, mod)) {
-		printk(KERN_ERR "init_module: mod->name out of bounds.\n");
-		goto err2;
-	}
-	if (mod->nsyms && !mod_bound(mod->syms, mod->nsyms, mod)) {
-		printk(KERN_ERR "init_module: mod->syms out of bounds.\n");
-		goto err2;
-	}
-	if (mod->ndeps && !mod_bound(mod->deps, mod->ndeps, mod)) {
-		printk(KERN_ERR "init_module: mod->deps out of bounds.\n");
-		goto err2;
-	}
-	if (mod->init && !mod_bound((unsigned long)mod->init, 0, mod)) {
-		printk(KERN_ERR "init_module: mod->init out of bounds.\n");
-		goto err2;
-	}
-	if (mod->cleanup && !mod_bound((unsigned long)mod->cleanup, 0, mod)) {
-		printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n");
-		goto err2;
-	}
-	if (mod->ex_table_start > mod->ex_table_end
-	    || (mod->ex_table_start &&
-		!((unsigned long)mod->ex_table_start >= ((unsigned long)mod + mod->size_of_struct)
-		  && ((unsigned long)mod->ex_table_end
-		      < (unsigned long)mod + mod->size)))
-	    || (((unsigned long)mod->ex_table_start
-		 - (unsigned long)mod->ex_table_end)
-		% sizeof(struct exception_table_entry))) {
-		printk(KERN_ERR "init_module: mod->ex_table_* invalid.\n");
-		goto err2;
-	}
-	if (mod->flags & ~MOD_AUTOCLEAN) {
-		printk(KERN_ERR "init_module: mod->flags invalid.\n");
-		goto err2;
-	}
-	if (mod_member_present(mod, can_unload)
-	    && mod->can_unload && !mod_bound((unsigned long)mod->can_unload, 0, mod)) {
-		printk(KERN_ERR "init_module: mod->can_unload out of bounds.\n");
-		goto err2;
-	}
-	if (mod_member_present(mod, kallsyms_end)) {
-	    if (mod->kallsyms_end &&
-		(!mod_bound(mod->kallsyms_start, 0, mod) ||
-		 !mod_bound(mod->kallsyms_end, 0, mod))) {
-		printk(KERN_ERR "init_module: mod->kallsyms out of bounds.\n");
-		goto err2;
-	    }
-	    if (mod->kallsyms_start > mod->kallsyms_end) {
-		printk(KERN_ERR "init_module: mod->kallsyms invalid.\n");
-		goto err2;
-	    }
-	}
-	if (mod_member_present(mod, archdata_end)) {
-	    if (mod->archdata_end &&
-		(!mod_bound(mod->archdata_start, 0, mod) ||
-		 !mod_bound(mod->archdata_end, 0, mod))) {
-		printk(KERN_ERR "init_module: mod->archdata out of bounds.\n");
-		goto err2;
-	    }
-	    if (mod->archdata_start > mod->archdata_end) {
-		printk(KERN_ERR "init_module: mod->archdata invalid.\n");
-		goto err2;
-	    }
-	}
-	if (mod_member_present(mod, kernel_data) && mod->kernel_data) {
-	    printk(KERN_ERR "init_module: mod->kernel_data must be zero.\n");
-	    goto err2;
-	}
-
-	/* Check that the user isn't doing something silly with the name.  */
-
-	if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod
-				      + (unsigned long)mod_user,
-				      &n_name)) < 0) {
-		printk(KERN_ERR "init_module: get_mod_name failure.\n");
-		error = n_namelen;
-		goto err2;
-	}
-	if (namelen != n_namelen || strcmp(n_name, mod_tmp.name) != 0) {
-		printk(KERN_ERR "init_module: changed module name to "
-				"`%s' from `%s'\n",
-		       n_name, mod_tmp.name);
-		goto err3;
-	}
-
-	/* Ok, that's about all the sanity we can stomach; copy the rest.  */
-
-	if (copy_from_user((char *)mod+mod_user_size,
-			   (char *)mod_user+mod_user_size,
-			   mod->size-mod_user_size)) {
-		error = -EFAULT;
-		goto err3;
-	}
-
-	if (module_arch_init(mod))
-		goto err3;
-
-	/* On some machines it is necessary to do something here
-	   to make the I and D caches consistent.  */
-	flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);
-
-	mod->next = mod_tmp.next;
-	mod->refs = NULL;
-
-	/* Sanity check the module's dependents */
-	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
-		struct module *o, *d = dep->dep;
-
-		/* Make sure the indicated dependencies are really modules.  */
-		if (d == mod) {
-			printk(KERN_ERR "init_module: self-referential "
-					"dependency in mod->deps.\n");
-			goto err3;
-		}
-
-		/* Scan the current modules for this dependency */
-		for (o = module_list; o != &kernel_module && o != d; o = o->next)
-			;
-
-		if (o != d) {
-			printk(KERN_ERR "init_module: found dependency that is "
-				"(no longer?) a module.\n");
-			goto err3;
-		}
+	DEBUGP("Allocating new usage for %s.\n", a->name);
+	use = kmalloc(sizeof(*use), GFP_ATOMIC);
+	if (!use) {
+		printk("%s: out of memory loading\n", a->name);
+		return 0;
 	}
 
-	/* Update module references.  */
-	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
-		struct module *d = dep->dep;
-
-		dep->ref = mod;
-		dep->next_ref = d->refs;
-		d->refs = dep;
-		/* Being referenced by a dependent module counts as a
-		   use as far as kmod is concerned.  */
-		d->flags |= MOD_USED_ONCE;
-	}
-
-	/* Free our temporary memory.  */
-	put_mod_name(n_name);
-	put_mod_name(name);
-
-	/* Initialize the module.  */
-	atomic_set(&mod->uc.usecount,1);
-	mod->flags |= MOD_INITIALIZING;
-	if (mod->init && (error = mod->init()) != 0) {
-		atomic_set(&mod->uc.usecount,0);
-		mod->flags &= ~MOD_INITIALIZING;
-		if (error > 0)	/* Buggy module */
-			error = -EBUSY;
-		goto err0;
-	}
-	atomic_dec(&mod->uc.usecount);
-
-	/* And set it running.  */
-	mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;
-	error = 0;
-	goto err0;
-
-err3:
-	put_mod_name(n_name);
-err2:
-	*mod = mod_tmp;
-	strcpy((char *)mod->name, name_tmp);	/* We know there is room for this */
-err1:
-	put_mod_name(name);
-err0:
-	unlock_kernel();
-	kfree(name_tmp);
-	return error;
-}
-
-static spinlock_t unload_lock = SPIN_LOCK_UNLOCKED;
-int try_inc_mod_count(struct module *mod)
-{
-	int res = 1;
-	if (mod) {
-		spin_lock(&unload_lock);
-		if (mod->flags & MOD_DELETED)
-			res = 0;
-		else
-			__MOD_INC_USE_COUNT(mod);
-		spin_unlock(&unload_lock);
-	}
-	return res;
+	use->module_which_uses = a;
+	list_add(&use->list, &b->modules_which_use_me);
+	try_module_get(b); /* Can't fail */
+	return 1;
 }
 
-asmlinkage long
-sys_delete_module(const char *name_user)
+/* Clear the unload stuff of the module. */
+static void module_unload_free(struct module *mod)
 {
-	struct module *mod, *next;
-	char *name;
-	long error;
-	int something_changed;
-
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
-
-	lock_kernel();
-	if (name_user) {
-		if ((error = get_mod_name(name_user, &name)) < 0)
-			goto out;
-		error = -ENOENT;
-		if ((mod = find_module(name)) == NULL) {
-			put_mod_name(name);
-			goto out;
-		}
-		put_mod_name(name);
-		error = -EBUSY;
-		if (mod->refs != NULL)
-			goto out;
+	struct module *i;
 
-		spin_lock(&unload_lock);
-		if (!__MOD_IN_USE(mod)) {
-			mod->flags |= MOD_DELETED;
-			spin_unlock(&unload_lock);
-			free_module(mod, 0);
-			error = 0;
-		} else {
-			spin_unlock(&unload_lock);
-		}
-		goto out;
-	}
+	list_for_each_entry(i, &modules, list) {
+		struct module_use *use;
 
-	/* Do automatic reaping */
-restart:
-	something_changed = 0;
-	
-	for (mod = module_list; mod != &kernel_module; mod = next) {
-		next = mod->next;
-		spin_lock(&unload_lock);
-		if (mod->refs == NULL
-		    && (mod->flags & MOD_AUTOCLEAN)
-		    && (mod->flags & MOD_RUNNING)
-		    && !(mod->flags & MOD_DELETED)
-		    && (mod->flags & MOD_USED_ONCE)
-		    && !__MOD_IN_USE(mod)) {
-			if ((mod->flags & MOD_VISITED)
-			    && !(mod->flags & MOD_JUST_FREED)) {
-				spin_unlock(&unload_lock);
-				mod->flags &= ~MOD_VISITED;
-			} else {
-				mod->flags |= MOD_DELETED;
-				spin_unlock(&unload_lock);
-				free_module(mod, 1);
-				something_changed = 1;
+		list_for_each_entry(use, &i->modules_which_use_me, list) {
+			if (use->module_which_uses == mod) {
+				DEBUGP("%s unusing %s\n", mod->name, i->name);
+				module_put(i);
+				list_del(&use->list);
+				kfree(use);
+				/* There can be at most one match. */
+				break;
 			}
-		} else {
-			spin_unlock(&unload_lock);
 		}
 	}
-	
-	if (something_changed)
-		goto restart;
-		
-	for (mod = module_list; mod != &kernel_module; mod = mod->next)
-		mod->flags &= ~MOD_JUST_FREED;
-	
-	error = 0;
-out:
-	unlock_kernel();
-	return error;
 }
 
-/* Query various bits about modules.  */
-
-static int
-qm_modules(char *buf, size_t bufsize, size_t *ret)
-{
-	struct module *mod;
-	size_t nmod, space, len;
-
-	nmod = space = 0;
+#ifdef CONFIG_SMP
+/* Thread to stop each CPU in user context. */
+enum stopref_state {
+	STOPREF_WAIT,
+	STOPREF_PREPARE,
+	STOPREF_DISABLE_IRQ,
+	STOPREF_EXIT,
+};
 
-	for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
-		len = strlen(mod->name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, mod->name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
-	}
+static enum stopref_state stopref_state;
+static unsigned int stopref_num_threads;
+static atomic_t stopref_thread_ack;
 
-	if (put_user(nmod, ret))
-		return -EFAULT;
-	else
-		return 0;
+static int stopref(void *cpu)
+{
+	int irqs_disabled = 0;
+	int prepared = 0;
 
-calc_space_needed:
-	space += len;
-	while ((mod = mod->next) != &kernel_module)
-		space += strlen(mod->name)+1;
+	sprintf(current->comm, "kmodule%lu\n", (unsigned long)cpu);
 
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
-}
+	/* Highest priority we can manage, and move to right CPU. */
+#if 0 /* FIXME */
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+	setscheduler(current->pid, SCHED_FIFO, &param);
+#endif
+	set_cpus_allowed(current, 1 << (unsigned long)cpu);
 
-static int
-qm_deps(struct module *mod, char *buf, size_t bufsize, size_t *ret)
-{
-	size_t i, space, len;
+	/* Ack: we are alive */
+	atomic_inc(&stopref_thread_ack);
 
-	if (mod == &kernel_module)
-		return -EINVAL;
-	if (!MOD_CAN_QUERY(mod))
-		if (put_user(0, ret))
-			return -EFAULT;
+	/* Simple state machine */
+	while (stopref_state != STOPREF_EXIT) {
+		if (stopref_state == STOPREF_DISABLE_IRQ && !irqs_disabled) {
+			local_irq_disable();
+			irqs_disabled = 1;
+			/* Ack: irqs disabled. */
+			atomic_inc(&stopref_thread_ack);
+		} else if (stopref_state == STOPREF_PREPARE && !prepared) {
+			/* Everyone is in place, hold CPU. */
+			preempt_disable();
+			prepared = 1;
+			atomic_inc(&stopref_thread_ack);
+		}
+		if (irqs_disabled || prepared)
+			cpu_relax();
 		else
-			return 0;
-
-	space = 0;
-	for (i = 0; i < mod->ndeps; ++i) {
-		const char *dep_name = mod->deps[i].dep->name;
-
-		len = strlen(dep_name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, dep_name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
+			yield();
 	}
 
-	if (put_user(i, ret))
-		return -EFAULT;
-	else
-		return 0;
+	/* Ack: we are exiting. */
+	atomic_inc(&stopref_thread_ack);
 
-calc_space_needed:
-	space += len;
-	while (++i < mod->ndeps)
-		space += strlen(mod->deps[i].dep->name)+1;
+	if (irqs_disabled)
+		local_irq_enable();
+	if (prepared)
+		preempt_enable();
 
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
+	return 0;
 }
 
-static int
-qm_refs(struct module *mod, char *buf, size_t bufsize, size_t *ret)
+/* Change the thread state */
+static void stopref_set_state(enum stopref_state state, int sleep)
 {
-	size_t nrefs, space, len;
-	struct module_ref *ref;
-
-	if (mod == &kernel_module)
-		return -EINVAL;
-	if (!MOD_CAN_QUERY(mod))
-		if (put_user(0, ret))
-			return -EFAULT;
+	atomic_set(&stopref_thread_ack, 0);
+	wmb();
+	stopref_state = state;
+	while (atomic_read(&stopref_thread_ack) != stopref_num_threads) {
+		if (sleep)
+			yield();
 		else
-			return 0;
-
-	space = 0;
-	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
-		const char *ref_name = ref->ref->name;
-
-		len = strlen(ref_name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-		if (copy_to_user(buf, ref_name, len))
-			return -EFAULT;
-		buf += len;
-		bufsize -= len;
-		space += len;
+			cpu_relax();
 	}
-
-	if (put_user(nrefs, ret))
-		return -EFAULT;
-	else
-		return 0;
-
-calc_space_needed:
-	space += len;
-	while ((ref = ref->next_ref) != NULL)
-		space += strlen(ref->ref->name)+1;
-
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
 }
 
-static int
-qm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret)
+/* Stop the machine.  Disables irqs. */
+static int stop_refcounts(void)
 {
-	size_t i, space, len;
-	struct module_symbol *s;
-	char *strings;
-	unsigned long *vals;
+	unsigned int i, cpu;
+	unsigned long old_allowed;
+	int ret = 0;
 
-	if (!MOD_CAN_QUERY(mod))
-		if (put_user(0, ret))
-			return -EFAULT;
-		else
-			return 0;
+	/* One thread per cpu.  We'll do our own. */
+	cpu = smp_processor_id();
 
-	space = mod->nsyms * 2*sizeof(void *);
+	/* FIXME: racy with set_cpus_allowed. */
+	old_allowed = current->cpus_allowed;
+	set_cpus_allowed(current, 1 << (unsigned long)cpu);
 
-	i = len = 0;
-	s = mod->syms;
+	atomic_set(&stopref_thread_ack, 0);
+	stopref_num_threads = 0;
+	stopref_state = STOPREF_WAIT;
 
-	if (space > bufsize)
-		goto calc_space_needed;
+	/* No CPUs can come up or down during this. */
+	down(&cpucontrol);
 
-	if (!access_ok(VERIFY_WRITE, buf, space))
-		return -EFAULT;
+	for (i = 0; i < NR_CPUS; i++) {
+		if (i == cpu || !cpu_online(i))
+			continue;
+		ret = kernel_thread(stopref, (void *)(long)i, CLONE_KERNEL);
+		if (ret < 0)
+			break;
+		stopref_num_threads++;
+	}
+
+	/* Wait for them all to come to life. */
+	while (atomic_read(&stopref_thread_ack) != stopref_num_threads)
+		yield();
 
-	bufsize -= space;
-	vals = (unsigned long *)buf;
-	strings = buf+space;
-
-	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
-		len = strlen(s->name)+1;
-		if (len > bufsize)
-			goto calc_space_needed;
-
-		if (copy_to_user(strings, s->name, len)
-		    || __put_user(s->value, vals+0)
-		    || __put_user(space, vals+1))
-			return -EFAULT;
-
-		strings += len;
-		bufsize -= len;
-		space += len;
+	/* If some failed, kill them all. */
+	if (ret < 0) {
+		stopref_set_state(STOPREF_EXIT, 1);
+		up(&cpucontrol);
+		return ret;
 	}
-	if (put_user(i, ret))
-		return -EFAULT;
-	else
-		return 0;
 
-calc_space_needed:
-	for (; i < mod->nsyms; ++i, ++s)
-		space += strlen(s->name)+1;
+	/* Don't schedule us away at this point, please. */
+	preempt_disable();
 
-	if (put_user(space, ret))
-		return -EFAULT;
-	else
-		return -ENOSPC;
+	/* Now they are all scheduled, make them hold the CPUs, ready. */
+	stopref_set_state(STOPREF_PREPARE, 0);
+
+	/* Make them disable irqs. */
+	stopref_set_state(STOPREF_DISABLE_IRQ, 0);
+
+	local_irq_disable();
+	return 0;
+}
+
+/* Restart the machine.  Re-enables irqs. */
+static void restart_refcounts(void)
+{
+	stopref_set_state(STOPREF_EXIT, 0);
+	local_irq_enable();
+	preempt_enable();
+	up(&cpucontrol);
+}
+#else /* ...!SMP */
+static inline int stop_refcounts(void)
+{
+	local_irq_disable();
+	return 0;
+}
+static inline void restart_refcounts(void)
+{
+	local_irq_enable();
 }
+#endif
 
-static int
-qm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret)
+static unsigned int module_refcount(struct module *mod)
 {
-	int error = 0;
+	unsigned int i, total = 0;
 
-	if (mod == &kernel_module)
-		return -EINVAL;
-
-	if (sizeof(struct module_info) <= bufsize) {
-		struct module_info info;
-		info.addr = (unsigned long)mod;
-		info.size = mod->size;
-		info.flags = mod->flags;
-		
-		/* usecount is one too high here - report appropriately to
-		   compensate for locking */
-		info.usecount = (mod_member_present(mod, can_unload)
-				 && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount)-1);
-
-		if (copy_to_user(buf, &info, sizeof(struct module_info)))
-			return -EFAULT;
-	} else
-		error = -ENOSPC;
+	for (i = 0; i < NR_CPUS; i++)
+		total += atomic_read(&mod->ref[i].count);
+	return total;
+}
 
-	if (put_user(sizeof(struct module_info), ret))
-		return -EFAULT;
+/* This exists whether we can unload or not */
+static void free_module(struct module *mod);
 
-	return error;
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+static inline int try_force(unsigned int flags)
+{
+	return (flags & O_TRUNC);
+}
+#else
+static inline int try_force(unsigned int flags)
+{
+	return 0;
 }
+#endif /* CONFIG_MODULE_FORCE_UNLOAD */
 
 asmlinkage long
-sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
-		 size_t *ret)
+sys_delete_module(const char *name_user, unsigned int flags)
 {
 	struct module *mod;
-	int err;
+	char name[MODULE_NAME_LEN];
+	int ret, forced = 0;
 
-	lock_kernel();
-	if (name_user == NULL)
-		mod = &kernel_module;
-	else {
-		long namelen;
-		char *name;
+	if (!capable(CAP_SYS_MODULE))
+		return -EPERM;
 
-		if ((namelen = get_mod_name(name_user, &name)) < 0) {
-			err = namelen;
-			goto out;
-		}
-		err = -ENOENT;
-		if ((mod = find_module(name)) == NULL) {
-			put_mod_name(name);
-			goto out;
-		}
-		put_mod_name(name);
+	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+		return -EFAULT;
+	name[MODULE_NAME_LEN-1] = '\0';
+
+	if (down_interruptible(&module_mutex) != 0)
+		return -EINTR;
+
+	mod = find_module(name);
+	if (!mod) {
+		ret = -ENOENT;
+		goto out;
 	}
 
-	/* __MOD_ touches the flags. We must avoid that */
-	
-	atomic_inc(&mod->uc.usecount);
-		
-	switch (which)
-	{
-	case 0:
-		err = 0;
-		break;
-	case QM_MODULES:
-		err = qm_modules(buf, bufsize, ret);
-		break;
-	case QM_DEPS:
-		err = qm_deps(mod, buf, bufsize, ret);
-		break;
-	case QM_REFS:
-		err = qm_refs(mod, buf, bufsize, ret);
-		break;
-	case QM_SYMBOLS:
-		err = qm_symbols(mod, buf, bufsize, ret);
-		break;
-	case QM_INFO:
-		err = qm_info(mod, buf, bufsize, ret);
-		break;
-	default:
-		err = -EINVAL;
-		break;
+	if (!list_empty(&mod->modules_which_use_me)) {
+		/* Other modules depend on us: get rid of them first. */
+		ret = -EWOULDBLOCK;
+		goto out;
 	}
-	atomic_dec(&mod->uc.usecount);
-	
-out:
-	unlock_kernel();
-	return err;
-}
 
-/*
- * Copy the kernel symbol table to user space.  If the argument is
- * NULL, just return the size of the table.
- *
- * This call is obsolete.  New programs should use query_module+QM_SYMBOLS
- * which does not arbitrarily limit the length of symbols.
- */
+	/* Already dying? */
+	if (!mod->live) {
+		/* FIXME: if (force), slam module count and wake up
+                   waiter --RR */
+		DEBUGP("%s already dying\n", mod->name);
+		ret = -EBUSY;
+		goto out;
+	}
 
-asmlinkage long
-sys_get_kernel_syms(struct kernel_sym *table)
-{
-	struct module *mod;
-	int i;
-	struct kernel_sym ksym;
+	if (!mod->exit || mod->unsafe) {
+		forced = try_force(flags);
+		if (!forced) {
+			/* This module can't be removed */
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+	/* Stop the machine so refcounts can't move: irqs disabled. */
+	DEBUGP("Stopping refcounts...\n");
+	ret = stop_refcounts();
+	if (ret != 0)
+		goto out;
 
-	lock_kernel();
-	for (mod = module_list, i = 0; mod; mod = mod->next) {
-		/* include the count for the module name! */
-		i += mod->nsyms + 1;
+	/* If it's not unused, quit unless we are told to block. */
+	if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
+		forced = try_force(flags);
+		if (!forced)
+			ret = -EWOULDBLOCK;
+	} else {
+		mod->waiter = current;
+		mod->live = 0;
 	}
+	restart_refcounts();
 
-	if (table == NULL)
+	if (ret != 0)
 		goto out;
 
-	/* So that we don't give the user our stack content */
-	memset (&ksym, 0, sizeof (ksym));
+	if (forced)
+		goto destroy;
 
-	for (mod = module_list, i = 0; mod; mod = mod->next) {
-		struct module_symbol *msym;
-		unsigned int j;
+	/* Since we might sleep for some time, drop the semaphore first */
+	up(&module_mutex);
+	for (;;) {
+		DEBUGP("Looking at refcount...\n");
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (module_refcount(mod) == 0)
+			break;
+		schedule();
+	}
+	current->state = TASK_RUNNING;
 
-		if (!MOD_CAN_QUERY(mod))
-			continue;
+	DEBUGP("Regrabbing mutex...\n");
+	down(&module_mutex);
 
-		/* magic: write module info as a pseudo symbol */
-		ksym.value = (unsigned long)mod;
-		ksym.name[0] = '#';
-		strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);
-		ksym.name[sizeof(ksym.name)-1] = '\0';
+ destroy:
+	/* Final destruction now noone is using it. */
+	if (mod->exit)
+		mod->exit();
+	free_module(mod);
 
-		if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
-			goto out;
-		++i, ++table;
+ out:
+	up(&module_mutex);
+	return ret;
+}
 
-		if (mod->nsyms == 0)
-			continue;
+static void print_unload_info(struct seq_file *m, struct module *mod)
+{
+	struct module_use *use;
 
-		for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {
-			ksym.value = msym->value;
-			strncpy(ksym.name, msym->name, sizeof(ksym.name));
-			ksym.name[sizeof(ksym.name)-1] = '\0';
-
-			if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
-				goto out;
-			++i, ++table;
-		}
-	}
-out:
-	unlock_kernel();
-	return i;
-}
+	seq_printf(m, " %u", module_refcount(mod));
 
-/*
- * Look for a module by name, ignoring modules marked for deletion.
- */
+	list_for_each_entry(use, &mod->modules_which_use_me, list)
+		seq_printf(m, " %s", use->module_which_uses->name);
 
-struct module *
-find_module(const char *name)
-{
-	struct module *mod;
+	if (mod->unsafe)
+		seq_printf(m, " [unsafe]");
 
-	for (mod = module_list; mod ; mod = mod->next) {
-		if (mod->flags & MOD_DELETED)
-			continue;
-		if (!strcmp(mod->name, name))
-			break;
-	}
+	if (!mod->exit)
+		seq_printf(m, " [permanent]");
 
-	return mod;
+	seq_printf(m, "\n");
 }
 
-/*
- * Free the given module.
- */
-
-void
-free_module(struct module *mod, int tag_freed)
+void __symbol_put(const char *symbol)
 {
-	struct module_ref *dep;
-	unsigned i;
+	struct kernel_symbol_group *ksg;
 	unsigned long flags;
 
-	/* Let the module clean up.  */
-
-	if (mod->flags & MOD_RUNNING)
-	{
-		if(mod->cleanup)
-			mod->cleanup();
-		mod->flags &= ~MOD_RUNNING;
-	}
-
-	/* Remove the module from the dependency lists.  */
-
-	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
-		struct module_ref **pp;
-		for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
-			continue;
-		*pp = dep->next_ref;
-		if (tag_freed && dep->dep->refs == NULL)
-			dep->dep->flags |= MOD_JUST_FREED;
-	}
+	spin_lock_irqsave(&modlist_lock, flags);
+	if (!__find_symbol(symbol, &ksg))
+		BUG();
+	module_put(ksg->owner);
+	spin_unlock_irqrestore(&modlist_lock, flags);
+}
+EXPORT_SYMBOL(__symbol_put);
 
-	/* And from the main module list.  */
+void symbol_put_addr(void *addr)
+{
+	struct kernel_symbol_group *ks;
+	unsigned long flags;
 
 	spin_lock_irqsave(&modlist_lock, flags);
-	if (mod == module_list) {
-		module_list = mod->next;
-	} else {
-		struct module *p;
-		for (p = module_list; p->next != mod; p = p->next)
-			continue;
-		p->next = mod->next;
+	list_for_each_entry(ks, &symbols, list) {
+ 		unsigned int i;
+
+		for (i = 0; i < ks->num_syms; i++) {
+			if (ks->syms[i].value == (unsigned long)addr) {
+				module_put(ks->owner);
+				spin_unlock_irqrestore(&modlist_lock, flags);
+				return;
+			}
+		}
 	}
 	spin_unlock_irqrestore(&modlist_lock, flags);
+	BUG();
+}
+EXPORT_SYMBOL_GPL(symbol_put_addr);
 
-	/* And free the memory.  */
-
-	module_unmap(mod);
+#else /* !CONFIG_MODULE_UNLOAD */
+static void print_unload_info(struct seq_file *m, struct module *mod)
+{
+	seq_printf(m, "\n");
 }
 
-/*
- * Called by the /proc file system to return a current list of modules.
- */
-static void *m_start(struct seq_file *m, loff_t *pos)
+static inline void module_unload_free(struct module *mod)
 {
-	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)
+
+static inline int use_module(struct module *a, struct module *b)
 {
-	struct module *v = p;
-	(*pos)++;
-	return v->next;
+	return try_module_get(b);
 }
-static void m_stop(struct seq_file *m, void *p)
+
+static inline void module_unload_init(struct module *mod)
 {
-	unlock_kernel();
 }
-static int m_show(struct seq_file *m, void *p)
+
+asmlinkage long
+sys_delete_module(const char *name_user, unsigned int flags)
 {
-	struct module *mod = p;
-	struct module_ref *ref = mod->refs;
+	return -ENOSYS;
+}
 
-	if (mod == &kernel_module)
-		return 0;
+#endif /* CONFIG_MODULE_UNLOAD */
+
+/* Find an symbol for this module (ie. resolve internals first).
+   It we find one, record usage.  Must be holding module_mutex. */
+unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
+				   unsigned int symindex,
+				   const char *strtab,
+				   const char *name,
+				   struct module *mod,
+				   struct kernel_symbol_group **ksg)
+{
+	unsigned long ret;
 
-	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, ']');
+	ret = find_local_symbol(sechdrs, symindex, strtab, name);
+	if (ret) {
+		*ksg = NULL;
+		return ret;
 	}
-	seq_putc(m, '\n');
-	return 0;
+	/* Look in other modules... */
+	spin_lock_irq(&modlist_lock);
+	ret = __find_symbol(name, ksg);
+	if (ret) {
+		/* This can fail due to OOM, or module unloading */
+		if (!use_module(mod, (*ksg)->owner))
+			ret = 0;
+	}
+	spin_unlock_irq(&modlist_lock);
+	return ret;
 }
-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.
- */
+/* Free a module, remove from lists, etc (must hold module mutex). */
+static void free_module(struct module *mod)
+{
+	/* Delete from various lists */
+	list_del(&mod->list);
+	spin_lock_irq(&modlist_lock);
+	list_del(&mod->symbols.list);
+	list_del(&mod->extable.list);
+	spin_unlock_irq(&modlist_lock);
 
-struct mod_sym {
-	struct module *mod;
-	int index;
-};
+	/* These may be NULL, but that's OK */
+	module_free(mod, mod->module_init);
+	module_free(mod, mod->module_core);
+
+	/* Module unload stuff */
+	module_unload_free(mod);
 
-/* iterator */
+	/* Finally, free the module structure */
+	module_free(mod, mod);
+}
 
-static void *s_start(struct seq_file *m, loff_t *pos)
+void *__symbol_get(const char *symbol)
 {
-	struct mod_sym *p = kmalloc(sizeof(*p), GFP_KERNEL);
-	struct module *v;
-	loff_t n = *pos;
+	struct kernel_symbol_group *ksg;
+	unsigned long value, flags;
 
-	if (!p)
-		return ERR_PTR(-ENOMEM);
-	lock_kernel();
-	for (v = module_list; v; n -= v->nsyms, v = v->next) {
-		if (n < v->nsyms) {
-			p->mod = v;
-			p->index = n;
-			return p;
-		}
+	spin_lock_irqsave(&modlist_lock, flags);
+	value = __find_symbol(symbol, &ksg);
+	if (value && !try_module_get(ksg->owner))
+		value = 0;
+	spin_unlock_irqrestore(&modlist_lock, flags);
+
+	return (void *)value;
+}
+EXPORT_SYMBOL_GPL(__symbol_get);
+
+/* Transfer one ELF section to the correct (init or core) area. */
+static void *copy_section(const char *name,
+			  void *base,
+			  Elf_Shdr *sechdr,
+			  struct module *mod,
+			  struct sizes *used)
+{
+	void *dest;
+	unsigned long *use;
+
+	/* Only copy to init section if there is one */
+	if (strstr(name, ".init") && mod->module_init) {
+		dest = mod->module_init;
+		use = &used->init_size;
+	} else {
+		dest = mod->module_core;
+		use = &used->core_size;
 	}
-	unlock_kernel();
-	kfree(p);
-	return NULL;
+
+	/* Align up */
+	*use = ALIGN(*use, sechdr->sh_addralign);
+	dest += *use;
+	*use += sechdr->sh_size;
+
+	/* May not actually be in the file (eg. bss). */
+	if (sechdr->sh_type != SHT_NOBITS)
+		memcpy(dest, base + sechdr->sh_offset, sechdr->sh_size);
+
+	return dest;
 }
 
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+/* Look for the special symbols */
+static int grab_private_symbols(Elf_Shdr *sechdrs,
+				unsigned int symbolsec,
+				const char *strtab,
+				struct module *mod)
 {
-	struct mod_sym *v = p;
-	(*pos)++;
-	if (++v->index >= v->mod->nsyms) {
-		do {
-			v->mod = v->mod->next;
-			if (!v->mod) {
-				unlock_kernel();
-				kfree(p);
-				return NULL;
-			}
-		} while (!v->mod->nsyms);
-		v->index = 0;
+	Elf_Sym *sym = (void *)sechdrs[symbolsec].sh_offset;
+	unsigned int i;
+
+	for (i = 1; i < sechdrs[symbolsec].sh_size/sizeof(*sym); i++) {
+		if (strcmp("__initfn", strtab + sym[i].st_name) == 0)
+			mod->init = (void *)sym[i].st_value;
+#ifdef CONFIG_MODULE_UNLOAD
+		if (strcmp("__exitfn", strtab + sym[i].st_name) == 0)
+			mod->exit = (void *)sym[i].st_value;
+#endif
 	}
-	return p;
+
+	return 0;
 }
 
-static void s_stop(struct seq_file *m, void *p)
-{
-	if (p && !IS_ERR(p)) {
-		unlock_kernel();
-		kfree(p);
+/* Deal with the given section */
+static int handle_section(const char *name,
+			  Elf_Shdr *sechdrs,
+			  unsigned int strindex,
+			  unsigned int symindex,
+			  unsigned int i,
+			  struct module *mod)
+{
+	int ret;
+	const char *strtab = (char *)sechdrs[strindex].sh_offset;
+
+	switch (sechdrs[i].sh_type) {
+	case SHT_REL:
+		ret = apply_relocate(sechdrs, strtab, symindex, i, mod);
+		break;
+	case SHT_RELA:
+		ret = apply_relocate_add(sechdrs, strtab, symindex, i, mod);
+		break;
+	case SHT_SYMTAB:
+		ret = grab_private_symbols(sechdrs, i, strtab, mod);
+		break;
+	default:
+		DEBUGP("Ignoring section %u: %s\n", i,
+		       sechdrs[i].sh_type==SHT_NULL ? "NULL":
+		       sechdrs[i].sh_type==SHT_PROGBITS ? "PROGBITS":
+		       sechdrs[i].sh_type==SHT_SYMTAB ? "SYMTAB":
+		       sechdrs[i].sh_type==SHT_STRTAB ? "STRTAB":
+		       sechdrs[i].sh_type==SHT_RELA ? "RELA":
+		       sechdrs[i].sh_type==SHT_HASH ? "HASH":
+		       sechdrs[i].sh_type==SHT_DYNAMIC ? "DYNAMIC":
+		       sechdrs[i].sh_type==SHT_NOTE ? "NOTE":
+		       sechdrs[i].sh_type==SHT_NOBITS ? "NOBITS":
+		       sechdrs[i].sh_type==SHT_REL ? "REL":
+		       sechdrs[i].sh_type==SHT_SHLIB ? "SHLIB":
+		       sechdrs[i].sh_type==SHT_DYNSYM ? "DYNSYM":
+		       sechdrs[i].sh_type==SHT_NUM ? "NUM":
+		       "UNKNOWN");
+		ret = 0;
 	}
+	return ret;
 }
 
-static int s_show(struct seq_file *m, void *p)
+/* Figure out total size desired for the common vars */
+static unsigned long read_commons(void *start, Elf_Shdr *sechdr)
 {
-	struct mod_sym *v = p;
-	struct module_symbol *sym;
+	unsigned long size, i, max_align;
+	Elf_Sym *sym;
+	
+	size = max_align = 0;
 
-	if (!MOD_CAN_QUERY(v->mod))
-		return 0;
-	sym = &v->mod->syms[v->index];
-	if (*v->mod->name)
-		seq_printf(m, "%0*lx %s\t[%s]\n", (int)(2*sizeof(void*)),
-			       sym->value, sym->name, v->mod->name);
-	else
-		seq_printf(m, "%0*lx %s\n", (int)(2*sizeof(void*)),
-			       sym->value, sym->name);
-	return 0;
-}
+	for (sym = start + sechdr->sh_offset, i = 0;
+	     i < sechdr->sh_size / sizeof(Elf_Sym);
+	     i++) {
+		if (sym[i].st_shndx == SHN_COMMON) {
+			/* Value encodes alignment. */
+			if (sym[i].st_value > max_align)
+				max_align = sym[i].st_value;
+			/* Pad to required alignment */
+			size = ALIGN(size, sym[i].st_value) + sym[i].st_size;
+		}
+	}
 
-struct seq_operations ksyms_op = {
-	.start	= s_start,
-	.next	= s_next,
-	.stop	= s_stop,
-	.show	= s_show
-};
+	/* Now, add in max alignment requirement (with align
+	   attribute, this could be large), so we know we have space
+	   whatever the start alignment is */
+	return size + max_align;
+}
+
+/* Change all symbols so that sh_value encodes the pointer directly. */
+static void simplify_symbols(Elf_Shdr *sechdrs,
+			     unsigned int symindex,
+			     unsigned int strindex,
+			     void *common,
+			     struct module *mod)
+{
+	unsigned int i;
+	Elf_Sym *sym;
+
+	/* First simplify defined symbols, so if they become the
+           "answer" to undefined symbols, copying their st_value us
+           correct. */
+	for (sym = (void *)sechdrs[symindex].sh_offset, i = 0;
+	     i < sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+	     i++) {
+		switch (sym[i].st_shndx) {
+		case SHN_COMMON:
+			/* Value encodes alignment. */
+			common = (void *)ALIGN((unsigned long)common,
+					       sym[i].st_value);
+			/* Change it to encode pointer */
+			sym[i].st_value = (unsigned long)common;
+			common += sym[i].st_size;
+			break;
+
+		case SHN_ABS:
+			/* Don't need to do anything */
+			DEBUGP("Absolute symbol: 0x%08lx\n",
+			       (long)sym[i].st_value);
+			break;
 
-#define MODLIST_SIZE 4096
+		case SHN_UNDEF:
+			break;
 
-/*
- * this function isn't smp safe but that's not really a problem; it's
- * called from oops context only and any locking could actually prevent
- * the oops from going out; the line that is generated is informational
- * only and should NEVER prevent the real oops from going out. 
- */
-void print_modules(void)
-{
-	static char modlist[MODLIST_SIZE];
-	struct module *this_mod;
-	int pos = 0;
+		default:
+			sym[i].st_value 
+				= (unsigned long)
+				(sechdrs[sym[i].st_shndx].sh_offset
+				 + sym[i].st_value);
+		}
+	}
 
-	this_mod = module_list;
-	while (this_mod) {
-		if (this_mod->name)
-			pos += snprintf(modlist+pos, MODLIST_SIZE-pos-1, 
-					"%s ", this_mod->name);
-		this_mod = this_mod->next;
+	/* Now try to resolve undefined symbols */
+	for (sym = (void *)sechdrs[symindex].sh_offset, i = 0;
+	     i < sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+	     i++) {
+		if (sym[i].st_shndx == SHN_UNDEF) {
+			/* Look for symbol */
+			struct kernel_symbol_group *ksg = NULL;
+			const char *strtab 
+				= (char *)sechdrs[strindex].sh_offset;
+
+			sym[i].st_value
+				= find_symbol_internal(sechdrs,
+						       symindex,
+						       strtab,
+						       strtab + sym[i].st_name,
+						       mod,
+						       &ksg);
+			/* We fake up "__this_module" */
+			if (strcmp(strtab+sym[i].st_name, "__this_module")==0)
+				sym[i].st_value = (unsigned long)mod;
+		}
 	}
-	printk("%s\n",modlist);
 }
 
-#else		/* CONFIG_MODULES */
+/* Get the total allocation size of the init and non-init sections */
+static struct sizes get_sizes(const Elf_Ehdr *hdr,
+			      const Elf_Shdr *sechdrs,
+			      const char *secstrings)
+{
+	struct sizes ret = { 0, 0 };
+	unsigned i;
 
-/* Dummy syscalls for people who don't want modules */
+	/* Everything marked ALLOC (this includes the exported
+           symbols) */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		unsigned long *add;
+
+		/* If it's called *.init*, and we're init, we're interested */
+		if (strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+			add = &ret.init_size;
+		else
+			add = &ret.core_size;
 
-asmlinkage unsigned long
-sys_create_module(const char *name_user, size_t size)
-{
-	return -ENOSYS;
-}
+		if (sechdrs[i].sh_flags & SHF_ALLOC) {
+			/* Pad up to required alignment */
+			*add = ALIGN(*add, sechdrs[i].sh_addralign ?: 1);
+			*add += sechdrs[i].sh_size;
+		}
+	}
 
-asmlinkage long
-sys_init_module(const char *name_user, struct module *mod_user)
-{
-	return -ENOSYS;
+	return ret;
 }
 
-asmlinkage long
-sys_delete_module(const char *name_user)
-{
-	return -ENOSYS;
-}
+/* Allocate and load the module */
+static struct module *load_module(void *umod,
+				  unsigned long len,
+				  const char *uargs)
+{
+	Elf_Ehdr *hdr;
+	Elf_Shdr *sechdrs;
+	char *secstrings;
+	unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
+		modnameindex;
+	long arglen;
+	unsigned long common_length;
+	struct sizes sizes, used;
+	struct module *mod;
+	long err = 0;
+	void *ptr = NULL; /* Stops spurious gcc uninitialized warning */
 
-asmlinkage long
-sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
-		 size_t *ret)
-{
-	/* Let the program know about the new interface.  Not that
-	   it'll do them much good.  */
-	if (which == 0)
-		return 0;
+	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
+	       umod, len, uargs);
+	if (len < sizeof(*hdr))
+		return ERR_PTR(-ENOEXEC);
+
+	/* Suck in entire file: we'll want most of it. */
+	/* vmalloc barfs on "unusual" numbers.  Check here */
+	if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
+		return ERR_PTR(-ENOMEM);
+	if (copy_from_user(hdr, umod, len) != 0) {
+		err = -EFAULT;
+		goto free_hdr;
+	}
+
+	/* Sanity checks against insmoding binaries or wrong arch,
+           weird elf version */
+	if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
+	    || hdr->e_type != ET_REL
+	    || !elf_check_arch(hdr)
+	    || hdr->e_shentsize != sizeof(*sechdrs)) {
+		err = -ENOEXEC;
+		goto free_hdr;
+	}
+
+	/* Convenience variables */
+	sechdrs = (void *)hdr + hdr->e_shoff;
+	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	/* May not export symbols, or have setup params, so these may
+           not exist */
+	exportindex = setupindex = 0;
+
+	/* And these should exist, but gcc whinges if we don't init them */
+	symindex = strindex = exindex = modnameindex = 0;
+
+	/* Find where important sections are */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		if (sechdrs[i].sh_type == SHT_SYMTAB) {
+			/* Internal symbols */
+			DEBUGP("Symbol table in section %u\n", i);
+			symindex = i;
+		} else if (strcmp(secstrings+sechdrs[i].sh_name, ".modulename")
+			   == 0) {
+			/* This module's name */
+			DEBUGP("Module name in section %u\n", i);
+			modnameindex = i;
+		} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ksymtab")
+			   == 0) {
+			/* Exported symbols. */
+			DEBUGP("EXPORT table in section %u\n", i);
+			exportindex = i;
+		} else if (strcmp(secstrings + sechdrs[i].sh_name, ".strtab")
+			   == 0) {
+			/* Strings */
+			DEBUGP("String table found in section %u\n", i);
+			strindex = i;
+		} else if (strcmp(secstrings+sechdrs[i].sh_name, ".setup.init")
+			   == 0) {
+			/* Setup parameter info */
+			DEBUGP("Setup table found in section %u\n", i);
+			setupindex = i;
+		} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ex_table")
+			   == 0) {
+			/* Exception table */
+			DEBUGP("Exception table found in section %u\n", i);
+			exindex = i;
+		}
+#ifndef CONFIG_MODULE_UNLOAD
+		/* Don't load .exit sections */
+		if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
+			sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
+#endif
+	}
 
-	return -ENOSYS;
-}
+	if (!modnameindex) {
+		DEBUGP("Module has no name!\n");
+		err = -ENOEXEC;
+		goto free_hdr;
+	}
+
+	/* Now allocate space for the module proper, and copy name and args. */
+	err = strlen_user(uargs);
+	if (err < 0)
+		goto free_hdr;
+	arglen = err;
+
+	mod = module_alloc(sizeof(*mod) + arglen+1);
+	if (!mod) {
+		err = -ENOMEM;
+		goto free_hdr;
+	}
+	memset(mod, 0, sizeof(*mod) + arglen+1);
+	if (copy_from_user(mod->args, uargs, arglen) != 0) {
+		err = -EFAULT;
+		goto free_mod;
+	}
+	strncpy(mod->name, (char *)hdr + sechdrs[modnameindex].sh_offset,
+		sizeof(mod->name)-1);
+
+	if (find_module(mod->name)) {
+		err = -EEXIST;
+		goto free_mod;
+	}
+
+	/* Initialize the lists, since they will be list_del'd if init fails */
+	INIT_LIST_HEAD(&mod->extable.list);
+	INIT_LIST_HEAD(&mod->list);
+	INIT_LIST_HEAD(&mod->symbols.list);
+	mod->symbols.owner = mod;
+	mod->live = 0;
+	module_unload_init(mod);
+
+	/* How much space will we need?  (Common area in core) */
+	sizes = get_sizes(hdr, sechdrs, secstrings);
+	common_length = read_commons(hdr, &sechdrs[symindex]);
+	sizes.core_size += common_length;
+
+	/* Set these up, and allow archs to manipulate them. */
+	mod->core_size = sizes.core_size;
+	mod->init_size = sizes.init_size;
+
+	/* Allow archs to add to them. */
+	err = module_init_size(hdr, sechdrs, secstrings, mod);
+	if (err < 0)
+		goto free_mod;
+	mod->init_size = err;
+
+	err = module_core_size(hdr, sechdrs, secstrings, mod);
+	if (err < 0)
+		goto free_mod;
+	mod->core_size = err;
+
+	/* Do the allocs. */
+	ptr = module_alloc(mod->core_size);
+	if (!ptr) {
+		err = -ENOMEM;
+		goto free_mod;
+	}
+	memset(ptr, 0, mod->core_size);
+	mod->module_core = ptr;
+
+	ptr = module_alloc(mod->init_size);
+	if (!ptr) {
+		err = -ENOMEM;
+		goto free_core;
+	}
+	memset(ptr, 0, mod->init_size);
+	mod->module_init = ptr;
+
+	/* Transfer each section which requires ALLOC, and set sh_offset
+	   fields to absolute addresses. */
+	used.core_size = common_length;
+	used.init_size = 0;
+	for (i = 1; i < hdr->e_shnum; i++) {
+		if (sechdrs[i].sh_flags & SHF_ALLOC) {
+			ptr = copy_section(secstrings + sechdrs[i].sh_name,
+					   hdr, &sechdrs[i], mod, &used);
+			if (IS_ERR(ptr))
+				goto cleanup;
+			sechdrs[i].sh_offset = (unsigned long)ptr;
+		} else {
+			sechdrs[i].sh_offset += (unsigned long)hdr;
+		}
+	}
+	/* Don't use more than we allocated! */
+	if (used.init_size > mod->init_size || used.core_size > mod->core_size)
+		BUG();
 
-asmlinkage long
-sys_get_kernel_syms(struct kernel_sym *table)
-{
-	return -ENOSYS;
-}
+	/* Fix up syms, so that st_value is a pointer to location. */
+	simplify_symbols(sechdrs, symindex, strindex, mod->module_core, mod);
 
-int try_inc_mod_count(struct module *mod)
-{
-	return 1;
+	/* Set up EXPORTed symbols */
+	if (exportindex) {
+		mod->symbols.num_syms = (sechdrs[exportindex].sh_size
+					/ sizeof(*mod->symbols.syms));
+		mod->symbols.syms = (void *)sechdrs[exportindex].sh_offset;
+	}
+
+	/* Set up exception table */
+	if (exindex) {
+		/* FIXME: Sort exception table. */
+		mod->extable.num_entries = (sechdrs[exindex].sh_size
+					    / sizeof(struct
+						     exception_table_entry));
+		mod->extable.entry = (void *)sechdrs[exindex].sh_offset;
+	}
+
+	/* Now handle each section. */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		err = handle_section(secstrings + sechdrs[i].sh_name,
+				     sechdrs, strindex, symindex, i, mod);
+		if (err < 0)
+			goto cleanup;
+	}
+
+	err = module_finalize(hdr, sechdrs, mod);
+	if (err < 0)
+		goto cleanup;
+
+#if 0 /* Needs param support */
+	/* Size of section 0 is 0, so this works well */
+	err = parse_args(mod->args,
+			 (struct kernel_param *)
+			 sechdrs[setupindex].sh_offset,
+			 sechdrs[setupindex].sh_size
+			 / sizeof(struct kernel_param),
+			 NULL);
+	if (err < 0)
+		goto cleanup;
+#endif
+
+	/* Get rid of temporary copy */
+	vfree(hdr);
+
+	/* Done! */
+	return mod;
+
+ cleanup:
+	module_unload_free(mod);
+	module_free(mod, mod->module_init);
+ free_core:
+	module_free(mod, mod->module_core);
+ free_mod:
+	module_free(mod, mod);
+ free_hdr:
+	vfree(hdr);
+	if (err < 0) return ERR_PTR(err);
+	else return ptr;
 }
 
-void print_modules(void)
+/* This is where the real work happens */
+asmlinkage long
+sys_init_module(void *umod,
+		unsigned long len,
+		const char *uargs)
 {
-}
+	struct module *mod;
+	int ret;
 
-#endif	/* CONFIG_MODULES */
+	/* Must have permission */
+	if (!capable(CAP_SYS_MODULE))
+		return -EPERM;
+
+	/* Only one module load at a time, please */
+	if (down_interruptible(&module_mutex) != 0)
+		return -EINTR;
+
+	/* Do all the hard work */
+	mod = load_module(umod, len, uargs);
+	if (IS_ERR(mod)) {
+		up(&module_mutex);
+		return PTR_ERR(mod);
+	}
+
+	/* Flush the instruction cache, since we've played with text */
+	if (mod->module_init)
+		flush_icache_range((unsigned long)mod->module_init,
+				   (unsigned long)mod->module_init
+				   + mod->init_size);
+	flush_icache_range((unsigned long)mod->module_core,
+			   (unsigned long)mod->module_core + mod->core_size);
+
+	/* Now sew it into exception list (just in case...). */
+	spin_lock_irq(&modlist_lock);
+	list_add(&mod->extable.list, &extables);
+	spin_unlock_irq(&modlist_lock);
+
+	/* Note, setting the mod->live to 1 here is safe because we haven't
+	 * linked the module into the system's kernel symbol table yet,
+	 * which means that the only way any other kernel code can call
+	 * into this module right now is if this module hands out entry
+	 * pointers to the other code.  We assume that no module hands out
+	 * entry pointers to the rest of the kernel unless it is ready to
+	 * have them used.
+	 */
+	mod->live = 1;
+	/* Start the module */
+	ret = mod->init ? mod->init() : 0;
+	if (ret < 0) {
+		/* Init routine failed: abort.  Try to protect us from
+                   buggy refcounters. */
+		synchronize_kernel();
+		if (mod->unsafe) {
+			printk(KERN_ERR "%s: module is now stuck!\n",
+			       mod->name);
+			/* Mark it "live" so that they can force
+			   deletion later, and we don't keep getting
+			   woken on every decrement. */
+		} else {
+			mod->live = 0;
+			free_module(mod);
+		}
+		up(&module_mutex);
+		return ret;
+	}
 
+	/* Now it's a first class citizen! */
+	spin_lock_irq(&modlist_lock);
+	list_add(&mod->symbols.list, &kernel_symbols.list);
+	spin_unlock_irq(&modlist_lock);
+	list_add(&mod->list, &modules);
 
-#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+	module_free(mod, mod->module_init);
+	mod->module_init = NULL;
 
-#define MAX_SYMBOL_SIZE 512
+	/* All ok! */
+	up(&module_mutex);
+	return 0;
+}
 
-static void
-address_to_exported_symbol(unsigned long address, const char **mod_name, 
-			   const char **sym_name, unsigned long *sym_start,
-			   unsigned long *sym_end)
+/* Called by the /proc file system to return a current list of
+   modules.  Al Viro came up with this interface as an "improvement".
+   God save us from any more such interface improvements. */
+static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	struct module *this_mod;
-	int i;
+	struct list_head *i;
+	loff_t n = 0;
 
-	for (this_mod = module_list; this_mod; this_mod = this_mod->next) {
-		/* walk the symbol list of this module. Only symbols
-		   who's address is smaller than the searched for address
-		   are relevant; and only if it's better than the best so far */
-		for (i = 0; i < this_mod->nsyms; i++)
-			if ((this_mod->syms[i].value <= address) &&
-			    (*sym_start < this_mod->syms[i].value)) {
-				*sym_start = this_mod->syms[i].value;
-				*sym_name  = this_mod->syms[i].name;
-				*mod_name  = this_mod->name;
-				if (i + 1 < this_mod->nsyms)
-					*sym_end = this_mod->syms[i+1].value;
-				else
-					*sym_end = (unsigned long) this_mod + this_mod->size;
-			}
+	down(&module_mutex);
+	list_for_each(i, &modules) {
+		if (n++ == *pos)
+			break;
 	}
+	if (i == &modules)
+		return NULL;
+	return i;
 }
 
-void
-print_symbol(const char *fmt, unsigned long address)
+static void *m_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	/* static to not take up stackspace; if we race here too bad */
-	static char buffer[MAX_SYMBOL_SIZE];
-
-	const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
-	unsigned long mod_start, mod_end, sec_start, sec_end,
-		sym_start, sym_end;
-	char *tag = "";
-	
-	memset(buffer, 0, MAX_SYMBOL_SIZE);
+	struct list_head *i = p;
+	(*pos)++;
+	if (i->next == &modules)
+		return NULL;
+	return i->next;
+}
 
-	sym_start = 0;
-	if (!kallsyms_address_to_symbol(address, &mod_name, &mod_start, &mod_end, &sec_name, &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
-		tag = "E ";
-		address_to_exported_symbol(address, &mod_name, &sym_name, &sym_start, &sym_end);
-	}
+static void m_stop(struct seq_file *m, void *p)
+{
+	up(&module_mutex);
+}
 
-	if (sym_start) {
-		if (*mod_name)
-		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x [%s]",
-			 tag, sym_name,
-			 (unsigned int)(address - sym_start),
-			 (unsigned int)(sym_end - sym_start),
-			 mod_name);
-		else
-		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x",
-			 tag, sym_name,
-			 (unsigned int)(address - sym_start),
-			 (unsigned int)(sym_end - sym_start));
-		printk(fmt, buffer);
-	}
-#if 0
- else {
-		printk(fmt, "[unresolved]");
-	}
-#endif
+static int m_show(struct seq_file *m, void *p)
+{
+	struct module *mod = list_entry(p, struct module, list);
+	seq_printf(m, "%s %lu",
+		   mod->name, mod->init_size + mod->core_size);
+	print_unload_info(m, mod);
+	return 0;
 }
+struct seq_operations modules_op = {
+	.start	= m_start,
+	.next	= m_next,
+	.stop	= m_stop,
+	.show	= m_show
+};
 
-#endif
+void __init extable_init(void)
+{
+	/* Add kernel symbols to symbol table */
+	kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
+	kernel_symbols.syms = __start___ksymtab;
+	list_add(&kernel_symbols.list, &symbols);
+
+	/* Add kernel exception table to exception tables */
+	kernel_extable.num_entries = (__stop___ex_table -__start___ex_table);
+	kernel_extable.entry = __start___ex_table;
+	list_add(&kernel_extable.list, &extables);
+}
+
+/* Obsolete lvalue for broken code which asks about usage */
+int module_dummy_usage = 1;
+EXPORT_SYMBOL(module_dummy_usage);
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Sun Nov 17 20:30:12 2002
+++ b/kernel/suspend.c	Sun Nov 17 20:30:12 2002
@@ -103,7 +103,7 @@
 
 static int resume_status = 0;
 static char resume_file[256] = "";			/* For resume= kernel option */
-static kdev_t resume_device;
+static dev_t resume_device;
 /* Local variables that should not be affected by save */
 unsigned int nr_copy_pages __nosavedata = 0;
 
@@ -1143,13 +1143,13 @@
 	unsigned long scratch_page = 0;
 	int error;
 
-	resume_device = to_kdev_t(name_to_dev_t(specialfile));
+	resume_device = name_to_dev_t(specialfile);
 	scratch_page = get_zeroed_page(GFP_ATOMIC);
 	cur = (void *) scratch_page;
 	if (cur) {
 		struct block_device *bdev;
 		printk("Resuming from device %s\n", __bdevname(resume_device));
-		bdev = bdget(kdev_t_to_nr(resume_device));
+		bdev = bdget(resume_device);
 		if (!bdev) {
 			printk("No such block device ?!\n");
 			BUG();
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Sun Nov 17 20:30:03 2002
+++ b/kernel/sys.c	Sun Nov 17 20:30:03 2002
@@ -206,6 +206,8 @@
 cond_syscall(sys_lookup_dcookie)
 cond_syscall(sys_swapon)
 cond_syscall(sys_swapoff)
+cond_syscall(sys_init_module)
+cond_syscall(sys_delete_module)
 
 static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	Sun Nov 17 20:30:12 2002
+++ b/kernel/time.c	Sun Nov 17 20:30:12 2002
@@ -57,7 +57,7 @@
 
 	/* SMP: This is fairly trivial. We grab CURRENT_TIME and 
 	   stuff it to user space. No side effects */
-	i = CURRENT_TIME;
+	i = get_seconds();
 	if (tloc) {
 		if (put_user(i,tloc))
 			i = -EFAULT;
@@ -404,4 +404,14 @@
 		return -EFAULT;
 	ret = do_adjtimex(&txc);
 	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
+}
+
+struct timespec current_kernel_time(void)
+{
+        struct timespec now;
+        unsigned long flags;
+        read_lock_irqsave(&xtime_lock,flags);
+	now = xtime;
+        read_unlock_irqrestore(&xtime_lock,flags);
+	return now; 
 }
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	Sun Nov 17 20:30:12 2002
+++ b/kernel/timer.c	Sun Nov 17 20:30:12 2002
@@ -66,9 +66,6 @@
 /* Fake initialization */
 static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED };
 
-/* Fake initialization needed to avoid compiler breakage */
-static DEFINE_PER_CPU(struct tasklet_struct, timer_tasklet) = { NULL };
-
 static void check_timer_failed(timer_t *timer)
 {
 	static int whine_count;
@@ -766,9 +763,9 @@
 unsigned long last_time_offset;
 
 /*
- * This function runs timers and the timer-tq in softirq context.
+ * This function runs timers and the timer-tq in bottom half context.
  */
-static void run_timer_tasklet(unsigned long data)
+static void run_timer_softirq(struct softirq_action *h)
 {
 	tvec_base_t *base = &per_cpu(tvec_bases, smp_processor_id());
 
@@ -781,7 +778,7 @@
  */
 void run_local_timers(void)
 {
-	tasklet_hi_schedule(&per_cpu(timer_tasklet, smp_processor_id()));
+	raise_softirq(TIMER_SOFTIRQ);
 }
 
 /*
@@ -1140,7 +1137,6 @@
 	}
 	for (j = 0; j < TVR_SIZE; j++)
 		INIT_LIST_HEAD(base->tv1.vec + j);
-	tasklet_init(&per_cpu(timer_tasklet, cpu), run_timer_tasklet, 0UL);
 }
 	
 static int __devinit timer_cpu_notify(struct notifier_block *self, 
@@ -1167,4 +1163,5 @@
 	timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
 				(void *)(long)smp_processor_id());
 	register_cpu_notifier(&timers_nb);
+	open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
 }
diff -Nru a/lib/string.c b/lib/string.c
--- a/lib/string.c	Sun Nov 17 20:30:15 2002
+++ b/lib/string.c	Sun Nov 17 20:30:15 2002
@@ -272,6 +272,29 @@
 }
 #endif
 
+/**
+ * strcspn - Calculate the length of the initial substring of @s which does
+ * 	not contain letters in @reject
+ * @s: The string to be searched
+ * @reject: The string to avoid
+ */
+size_t strcspn(const char *s, const char *reject)
+{
+	const char *p;
+	const char *r;
+	size_t count = 0;
+
+	for (p = s; *p != '\0'; ++p) {
+		for (r = reject; *r != '\0'; ++r) {
+			if (*p == *r)
+				return count;
+		}
+		++count;
+	}
+
+	return count;
+}	
+
 #ifndef __HAVE_ARCH_STRPBRK
 /**
  * strpbrk - Find the first occurrence of a set of characters
diff -Nru a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
--- a/lib/zlib_deflate/deflate_syms.c	Sun Nov 17 20:30:14 2002
+++ b/lib/zlib_deflate/deflate_syms.c	Sun Nov 17 20:30:14 2002
@@ -19,3 +19,5 @@
 EXPORT_SYMBOL(zlib_deflateCopy);
 EXPORT_SYMBOL(zlib_deflateParams);
 MODULE_LICENSE("GPL");
+
+no_module_init;
diff -Nru a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
--- a/lib/zlib_inflate/inflate_syms.c	Sun Nov 17 20:30:14 2002
+++ b/lib/zlib_inflate/inflate_syms.c	Sun Nov 17 20:30:14 2002
@@ -20,3 +20,5 @@
 EXPORT_SYMBOL(zlib_inflateSyncPoint);
 EXPORT_SYMBOL(zlib_inflateIncomp); 
 MODULE_LICENSE("GPL");
+
+no_module_init;
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Sun Nov 17 20:30:12 2002
+++ b/mm/filemap.c	Sun Nov 17 20:30:12 2002
@@ -1556,7 +1556,6 @@
 	ssize_t		written;
 	int		err;
 	size_t		bytes;
-	time_t		time_now;
 	struct pagevec	lru_pvec;
 	const struct iovec *cur_iov = iov; /* current iovec */
 	size_t		iov_base = 0;	   /* offset in the current iovec */
@@ -1676,12 +1675,7 @@
 		goto out;
 
 	remove_suid(file->f_dentry);
-	time_now = CURRENT_TIME;
-	if (inode->i_ctime != time_now || inode->i_mtime != time_now) {
-		inode->i_ctime = time_now;
-		inode->i_mtime = time_now;
-		mark_inode_dirty_sync(inode);
-	}
+	inode_update_time(inode, 1);
 
 	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
 	if (unlikely(file->f_flags & O_DIRECT)) {
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Sun Nov 17 20:30:14 2002
+++ b/mm/page-writeback.c	Sun Nov 17 20:30:14 2002
@@ -613,6 +613,7 @@
 		if (mapping) {
 			write_lock(&mapping->page_lock);
 			if (page->mapping) {	/* Race with truncate? */
+				BUG_ON(page->mapping != mapping);
 				if (!mapping->backing_dev_info->memory_backed)
 					inc_page_state(nr_dirty);
 				list_del(&page->list);
diff -Nru a/mm/page_io.c b/mm/page_io.c
--- a/mm/page_io.c	Sun Nov 17 20:30:03 2002
+++ b/mm/page_io.c	Sun Nov 17 20:30:03 2002
@@ -30,6 +30,7 @@
 		struct swap_info_struct *sis;
 		swp_entry_t entry;
 
+		BUG_ON(!PageSwapCache(page));
 		entry.val = page->index;
 		sis = get_swap_info_struct(swp_type(entry));
 
@@ -97,6 +98,7 @@
 	bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
 	if (bio == NULL) {
 		set_page_dirty(page);
+		unlock_page(page);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -116,6 +118,7 @@
 	ClearPageUptodate(page);
 	bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
 	if (bio == NULL) {
+		unlock_page(page);
 		ret = -ENOMEM;
 		goto out;
 	}
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	Sun Nov 17 20:30:15 2002
+++ b/mm/rmap.c	Sun Nov 17 20:30:15 2002
@@ -393,9 +393,9 @@
 	}
 
 	/* Nuke the page table entry. */
+	flush_cache_page(vma, address);
 	pte = ptep_get_and_clear(ptep);
 	flush_tlb_page(vma, address);
-	flush_cache_page(vma, address);
 
 	/* Store the swap location in the pte. See handle_pte_fault() ... */
 	if (PageSwapCache(page)) {
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Sun Nov 17 20:30:13 2002
+++ b/mm/shmem.c	Sun Nov 17 20:30:13 2002
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/backing-dev.h>
 #include <linux/shmem_fs.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sun Nov 17 20:30:15 2002
+++ b/mm/slab.c	Sun Nov 17 20:30:15 2002
@@ -507,7 +507,6 @@
 	struct timer_list *rt = &reap_timers[cpu];
 
 	if (rt->function == NULL) {
-		printk(KERN_INFO "slab: reap timer started for cpu %d\n", cpu);
 		init_timer(rt);
 		rt->expires = jiffies + HZ + 3*cpu;
 		rt->function = reap_timer_fnc;
@@ -2123,6 +2122,10 @@
 	unsigned long	active_slabs = 0;
 	unsigned long	num_slabs;
 	const char *name; 
+	char *error = NULL;
+	mm_segment_t old_fs;
+	char tmp; 
+
 
 	if (p == (void*)1) {
 		/*
@@ -2143,38 +2146,45 @@
 	num_slabs = 0;
 	list_for_each(q,&cachep->lists.slabs_full) {
 		slabp = list_entry(q, struct slab, list);
-		if (slabp->inuse != cachep->num)
-			BUG();
+		if (slabp->inuse != cachep->num && !error)
+			error = "slabs_full accounting error";
 		active_objs += cachep->num;
 		active_slabs++;
 	}
 	list_for_each(q,&cachep->lists.slabs_partial) {
 		slabp = list_entry(q, struct slab, list);
-		BUG_ON(slabp->inuse == cachep->num || !slabp->inuse);
+		if (slabp->inuse == cachep->num && !error)
+			error = "slabs_partial inuse accounting error";
+		if (!slabp->inuse && !error)
+			error = "slabs_partial/inuse accounting error";
 		active_objs += slabp->inuse;
 		active_slabs++;
 	}
 	list_for_each(q,&cachep->lists.slabs_free) {
 		slabp = list_entry(q, struct slab, list);
-		if (slabp->inuse)
-			BUG();
+		if (slabp->inuse && !error)
+			error = "slabs_free/inuse accounting error";
 		num_slabs++;
 	}
 	num_slabs+=active_slabs;
 	num_objs = num_slabs*cachep->num;
-	BUG_ON(num_objs - active_objs != cachep->lists.free_objects);
+	if (num_objs - active_objs != cachep->lists.free_objects && !error)
+		error = "free_objects accounting error";
 
 	name = cachep->name; 
-	{
-	char tmp; 
-	mm_segment_t old_fs;
 
+	/*
+	 * Check to see if `name' resides inside a module which has been
+	 * unloaded (someone forgot to destroy their cache)
+	 */
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
 	if (__get_user(tmp, name)) 
 		name = "broken"; 
 	set_fs(old_fs);
-	} 	
+
+	if (error)
+		printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
 
 	seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
 		name, active_objs, num_objs, cachep->objsize,
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Sun Nov 17 20:30:04 2002
+++ b/mm/swapfile.c	Sun Nov 17 20:30:04 2002
@@ -959,24 +959,26 @@
 {
 	struct swap_info_struct * p = NULL;
 	unsigned short *swap_map;
-	struct file *swap_file;
-	struct nameidata nd;
+	struct file *swap_file, *victim;
+	struct address_space *mapping;
 	int i, type, prev;
 	int err;
 	
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	err = user_path_walk(specialfile, &nd);
-	if (err)
+	victim = filp_open(specialfile, O_RDWR, 0);
+	err = PTR_ERR(victim);
+	if (IS_ERR(victim))
 		goto out;
 
+	mapping = victim->f_dentry->d_inode->i_mapping;
 	prev = -1;
 	swap_list_lock();
 	for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
 		p = swap_info + type;
 		if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
-			if (p->swap_file->f_dentry == nd.dentry)
+			if (p->swap_file->f_dentry->d_inode->i_mapping==mapping)
 				break;
 		}
 		prev = type;
@@ -1040,7 +1042,7 @@
 	err = 0;
 
 out_dput:
-	path_release(&nd);
+	filp_close(victim, NULL);
 out:
 	return err;
 }
diff -Nru a/net/802/tr.c b/net/802/tr.c
--- a/net/802/tr.c	Sun Nov 17 20:30:03 2002
+++ b/net/802/tr.c	Sun Nov 17 20:30:03 2002
@@ -541,10 +541,10 @@
 
 static int __init rif_init(void)
 {
+	init_timer(&rif_timer);
 	rif_timer.expires  = RIF_TIMEOUT;
 	rif_timer.data     = 0L;
 	rif_timer.function = rif_check_expire;
-	init_timer(&rif_timer);
 	add_timer(&rif_timer);
 
 	proc_net_create("tr_rif",0,rif_get_info);
diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c
--- a/net/atm/mpc.c	Sun Nov 17 20:30:15 2002
+++ b/net/atm/mpc.c	Sun Nov 17 20:30:15 2002
@@ -104,7 +104,7 @@
 
 struct mpoa_client *mpcs = NULL; /* FIXME */
 static struct atm_mpoa_qos *qos_head = NULL;
-static struct timer_list mpc_timer;
+static struct timer_list mpc_timer = TIMER_INITIALIZER(NULL, 0, 0);
 
 
 static struct mpoa_client *find_mpc_by_itfnum(int itf)
diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c
--- a/net/core/neighbour.c	Sun Nov 17 20:30:02 2002
+++ b/net/core/neighbour.c	Sun Nov 17 20:30:02 2002
@@ -1151,8 +1151,8 @@
 	tasklet_init(&tbl->gc_task, SMP_TIMER_NAME(neigh_periodic_timer),
 		     (unsigned long)tbl);
 #endif
-	init_timer(&tbl->gc_timer);
 	tbl->lock	       = RW_LOCK_UNLOCKED;
+	init_timer(&tbl->gc_timer);
 	tbl->gc_timer.data     = (unsigned long)tbl;
 	tbl->gc_timer.function = neigh_periodic_timer;
 	tbl->gc_timer.expires  = now + tbl->gc_interval +
diff -Nru a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/Kconfig	Sun Nov 17 20:30:15 2002
@@ -362,5 +362,13 @@
 
 	  If unsure, say Y.
 
+config XFRM_USER
+	tristate "IP: IPsec user configuration interface"
+	---help---
+	  Support for IPsec user configuration interface used
+	  by native Linux tools.
+
+	  If unsure, say Y.
+
 source "net/ipv4/netfilter/Kconfig"
 
diff -Nru a/net/ipv4/Makefile b/net/ipv4/Makefile
--- a/net/ipv4/Makefile	Sun Nov 17 20:30:12 2002
+++ b/net/ipv4/Makefile	Sun Nov 17 20:30:12 2002
@@ -20,6 +20,7 @@
 obj-$(CONFIG_INET_ESP) += esp.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
+obj-$(CONFIG_XFRM_USER) += xfrm_user.o
 
 obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o
 
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Sun Nov 17 20:30:03 2002
+++ b/net/ipv4/af_inet.c	Sun Nov 17 20:30:03 2002
@@ -1160,16 +1160,20 @@
 /* ------------------------------------------------------------------------ */
 
 #ifdef CONFIG_PROC_FS
-
-extern int ip_misc_proc_init(void);
-extern int raw_get_info(char *, char **, off_t, int);
-extern int tcp_get_info(char *, char **, off_t, int);
+extern int  fib_proc_init(void);
+extern void fib_proc_exit(void);
+extern int  ip_misc_proc_init(void);
+extern int  raw_proc_init(void);
+extern void raw_proc_exit(void);
+extern int  tcp_get_info(char *buffer, char **start, off_t offset, int length);
+extern int  udp_proc_init(void);
+extern void udp_proc_exit(void);
 
 int __init ipv4_proc_init(void)
 {
 	int rc = 0;
 
-	if (!proc_net_create("raw", 0, raw_get_info))
+	if (raw_proc_init())
 		goto out_raw;
 	if (!proc_net_create("tcp", 0, tcp_get_info))
 		goto out_tcp;
@@ -1188,7 +1192,7 @@
 out_udp:
 	proc_net_remove("tcp");
 out_tcp:
-	proc_net_remove("raw");
+	raw_proc_exit();
 out_raw:
 	rc = -ENOMEM;
 	goto out;
diff -Nru a/net/ipv4/ah.c b/net/ipv4/ah.c
--- a/net/ipv4/ah.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/ah.c	Sun Nov 17 20:30:15 2002
@@ -189,7 +189,7 @@
 		top_iph->saddr = x->props.saddr.xfrm4_addr;
 		top_iph->daddr = x->id.daddr.xfrm4_addr;
 		ah = (struct ip_auth_hdr*)(top_iph+1);
-		ah->nexthdr = IPPROTO_IP;
+		ah->nexthdr = IPPROTO_IPIP;
 	} else {
 		memcpy(&tmp_iph, skb->data, iph->ihl*4);
 		top_iph = (struct iphdr*)skb_push(skb, x->props.header_len);
diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c
--- a/net/ipv4/arp.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/arp.c	Sun Nov 17 20:30:15 2002
@@ -90,6 +90,7 @@
 #include <linux/seq_file.h>
 #include <linux/stat.h>
 #include <linux/init.h>
+#include <linux/net.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -1142,65 +1143,115 @@
 	int is_pneigh, bucket;
 };
 
-static __inline__ struct neighbour *neigh_get_bucket(struct seq_file *seq,
-						     loff_t *pos)
+static struct neighbour *neigh_get_first(struct seq_file *seq)
 {
-	struct neighbour *n = NULL;
 	struct arp_iter_state* state = seq->private;
-	loff_t l = *pos;
-	int i;
+	struct neighbour *n = NULL;
+
+	state->is_pneigh = 0;
+
+	for (state->bucket = 0;
+	     state->bucket <= NEIGH_HASHMASK;
+	     ++state->bucket) {
+		n = arp_tbl.hash_buckets[state->bucket];
+		while (n && !(n->nud_state & ~NUD_NOARP))
+			n = n->next;
+		if (n)
+			break;
+	}
 
-	for (; state->bucket <= NEIGH_HASHMASK; ++state->bucket)
-		for (i = 0, n = arp_tbl.hash_buckets[state->bucket]; n;
-		     ++i, n = n->next)
-			/* Do not confuse users "arp -a" with magic entries */
-			if ((n->nud_state & ~NUD_NOARP) && !l--) {
-				*pos = i;
-				goto out;
-			}
-out:
 	return n;
 }
 
-static __inline__ struct pneigh_entry *pneigh_get_bucket(struct seq_file *seq,
-							 loff_t *pos)
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+					struct neighbour *n)
 {
-	struct pneigh_entry *n = NULL;
 	struct arp_iter_state* state = seq->private;
-	loff_t l = *pos;
-	int i;
 
-	for (; state->bucket <= PNEIGH_HASHMASK; ++state->bucket)
-		for (i = 0, n = arp_tbl.phash_buckets[state->bucket]; n;
-		     ++i, n = n->next)
-			if (!l--) {
-				*pos = i;
-				goto out;
-			}
+	do {
+		n = n->next;
+		/* Don't confuse "arp -a" w/ magic entries */
+try_again:
+	} while (n && !(n->nud_state & ~NUD_NOARP));
+
+	if (n)
+		goto out;
+	if (++state->bucket > NEIGH_HASHMASK)
+		goto out;
+	n = arp_tbl.hash_buckets[state->bucket];
+	goto try_again;
 out:
 	return n;
 }
 
-static __inline__ void *arp_get_bucket(struct seq_file *seq, loff_t *pos)
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
 {
-	void *rc = neigh_get_bucket(seq, pos);
+	struct neighbour *n = neigh_get_first(seq);
 
-	if (!rc) {
-		struct arp_iter_state* state = seq->private;
+	if (n)
+		while (*pos && (n = neigh_get_next(seq, n)))
+			--*pos;
+	return *pos ? NULL : n;
+}
+
+static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+{
+	struct arp_iter_state* state = seq->private;
+	struct pneigh_entry *pn;
+
+	state->is_pneigh = 1;
+
+	for (state->bucket = 0;
+	     state->bucket <= PNEIGH_HASHMASK;
+	     ++state->bucket) {
+		pn = arp_tbl.phash_buckets[state->bucket];
+		if (pn)
+			break;
+	}
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+					    struct pneigh_entry *pn)
+{
+	struct arp_iter_state* state = seq->private;
+
+	pn = pn->next;
+	while (!pn) {
+		if (++state->bucket > PNEIGH_HASHMASK)
+			break;
+		pn = arp_tbl.phash_buckets[state->bucket];
+	}
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct pneigh_entry *pn = pneigh_get_first(seq);
+
+	if (pn)
+		while (pos && (pn = pneigh_get_next(seq, pn)))
+			--pos;
+	return pos ? NULL : pn;
+}
+
+static void *arp_get_idx(struct seq_file *seq, loff_t pos)
+{
+	void *rc;
 
+	read_lock_bh(&arp_tbl.lock);
+	rc = neigh_get_idx(seq, &pos);
+
+	if (!rc) {
 		read_unlock_bh(&arp_tbl.lock);
-		state->is_pneigh = 1;
-		state->bucket	 = 0;
-		*pos		 = 0;
-		rc = pneigh_get_bucket(seq, pos);
+		rc = pneigh_get_idx(seq, pos);
 	}
 	return rc;
 }
 
 static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	read_lock_bh(&arp_tbl.lock);
-	return *pos ? arp_get_bucket(seq, pos) : (void *)1;
+	return *pos ? arp_get_idx(seq, *pos - 1) : (void *)1;
 }
 
 static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
@@ -1209,38 +1260,19 @@
 	struct arp_iter_state* state;
 
 	if (v == (void *)1) {
-		rc = arp_get_bucket(seq, pos);
+		rc = arp_get_idx(seq, 0);
 		goto out;
 	}
 
 	state = seq->private;
 	if (!state->is_pneigh) {
-		struct neighbour *n = v;
-
-		rc = n = n->next;
-		if (n)
-			goto out;
-		*pos = 0;
-		++state->bucket;
-		rc = neigh_get_bucket(seq, pos);
+		rc = neigh_get_next(seq, v);
 		if (rc)
 			goto out;
 		read_unlock_bh(&arp_tbl.lock);
-		state->is_pneigh = 1;
-		state->bucket	 = 0;
-		*pos		 = 0;
-		rc = pneigh_get_bucket(seq, pos);
-	} else {
-		struct pneigh_entry *pn = v;
-
-		pn = pn->next;
-		if (!pn) {
-			++state->bucket;
-			*pos = 0;
-			pn   = pneigh_get_bucket(seq, pos);
-		}
-		rc = pn;
-	}
+		rc = pneigh_get_first(seq);
+	} else
+		rc = pneigh_get_next(seq, v);
 out:
 	++*pos;
 	return rc;
@@ -1291,7 +1323,6 @@
 static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
 					       struct pneigh_entry *n)
 {
-
 	struct net_device *dev = n->dev;
 	int hatype = dev ? dev->type : 0;
 	char tbuf[16];
diff -Nru a/net/ipv4/esp.c b/net/ipv4/esp.c
--- a/net/ipv4/esp.c	Sun Nov 17 20:30:14 2002
+++ b/net/ipv4/esp.c	Sun Nov 17 20:30:14 2002
@@ -190,11 +190,10 @@
 	struct crypto_tfm *tfm = esp->auth.tfm;
 	char *digest = esp->auth.work_digest;
 
-	memset(auth_data, 0, esp->auth.authlen);
  	crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
 	skb_digest_walk(skb, tfm, offset, len);
 	crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, digest);
-	memcpy(auth_data, digest, crypto_tfm_alg_digestsize(tfm));
+	memcpy(auth_data, digest, esp->auth.authlen);
 }
 
 /* Check that skb data bits are writable. If they are not, copy data
@@ -370,7 +369,7 @@
 	if (x->props.mode) {
 		top_iph = (struct iphdr*)skb_push(skb, x->props.header_len);
 		esph = (struct ip_esp_hdr*)(top_iph+1);
-		*(u8*)(trailer->tail - 1) = IPPROTO_IP;
+		*(u8*)(trailer->tail - 1) = IPPROTO_IPIP;
 		top_iph->ihl = 5;
 		top_iph->version = 4;
 		top_iph->tos = iph->tos;	/* DS disclosed */
@@ -463,16 +462,16 @@
 
 	/* If integrity check is required, do this. */
 	if (esp->auth.authlen) {
-		int icvsize = crypto_tfm_alg_digestsize(esp->auth.tfm);
-		u8 sum[icvsize];
-		u8 sum1[icvsize];
+		u8 sum[esp->auth.authlen];
+		u8 sum1[esp->auth.authlen];
 
 		esp->auth.digest(esp, skb, 0, skb->len-esp->auth.authlen, sum);
 
-		if (skb_copy_bits(skb, skb->len-esp->auth.authlen, sum1, icvsize))
+		if (skb_copy_bits(skb, skb->len-esp->auth.authlen, sum1, 
+				esp->auth.authlen))
 			BUG();
 
-		if (unlikely(memcmp(sum, sum1, icvsize))) {
+		if (unlikely(memcmp(sum, sum1, esp->auth.authlen))) {
 			x->stats.integrity_failed++;
 			goto out;
 		}
@@ -605,14 +604,20 @@
 	memset(esp, 0, sizeof(*esp));
 
 	if (x->aalg) {
+		int digestsize;
+
 		esp->auth.key = x->aalg->alg_key;
 		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
 		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
 		if (esp->auth.tfm == NULL)
 			goto error;
 		esp->auth.digest = esp_hmac_digest;
-		esp->auth.authlen = crypto_tfm_alg_digestsize(esp->auth.tfm);
-		esp->auth.work_digest = kmalloc(esp->auth.authlen, GFP_KERNEL);
+		digestsize = crypto_tfm_alg_digestsize(esp->auth.tfm);
+		/* XXX RFC2403 and RFC 2404 truncate auth to 96 bit */
+		esp->auth.authlen = 12;
+		if (esp->auth.authlen > digestsize) /* XXX */
+			BUG();
+		esp->auth.work_digest = kmalloc(digestsize, GFP_KERNEL);
 		if (!esp->auth.work_digest)
 			goto error;
 	}
diff -Nru a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
--- a/net/ipv4/fib_hash.c	Sun Nov 17 20:30:14 2002
+++ b/net/ipv4/fib_hash.c	Sun Nov 17 20:30:14 2002
@@ -1092,16 +1092,4 @@
 {
 	remove_proc_entry("route", proc_net);
 }
-
-#else /* CONFIG_PROC_FS */
-
-int __init fib_proc_init(void)
-{
-	return 0;
-}
-
-void __init fib_proc_exit(void)
-{
-	return 0;
-}
 #endif /* CONFIG_PROC_FS */
diff -Nru a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
--- a/net/ipv4/inetpeer.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/inetpeer.c	Sun Nov 17 20:30:15 2002
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/net.h>
 #include <net/inetpeer.h>
 
 /*
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/ip_output.c	Sun Nov 17 20:30:15 2002
@@ -815,14 +815,16 @@
 				alloclen = maxfraglen;
 			else
 				alloclen = datalen + fragheaderlen;
-			if (!(flags & MSG_DONTWAIT) || transhdrlen) {
+			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk, 
 						alloclen + hh_len + 15,
 						(flags & MSG_DONTWAIT), &err);
 			} else {
-				skb = sock_wmalloc(sk, 
-						alloclen + hh_len + 15, 1,
-						sk->allocation);
+				skb = NULL;
+				if (atomic_read(&sk->wmem_alloc) <= 2*sk->sndbuf)
+					skb = sock_wmalloc(sk, 
+							   alloclen + hh_len + 15, 1,
+							   sk->allocation);
 				if (unlikely(skb == NULL))
 					err = -ENOBUFS;
 			}
diff -Nru a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
--- a/net/ipv4/ip_sockglue.c	Sun Nov 17 20:30:12 2002
+++ b/net/ipv4/ip_sockglue.c	Sun Nov 17 20:30:12 2002
@@ -626,6 +626,7 @@
 	                break;			
  
 		case IP_IPSEC_POLICY:
+		case IP_XFRM_POLICY:
 			err = xfrm_user_policy(sk, optname, optval, optlen);
 			break;
 
diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
--- a/net/ipv4/netfilter/ip_nat_helper.c	Sun Nov 17 20:30:04 2002
+++ b/net/ipv4/netfilter/ip_nat_helper.c	Sun Nov 17 20:30:04 2002
@@ -361,8 +361,6 @@
 	return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
 }
 
-#define MODULE_MAX_NAMELEN		32
-
 int ip_nat_helper_register(struct ip_nat_helper *me)
 {
 	int ret = 0;
@@ -374,14 +372,13 @@
 		    && ct_helper->me) {
 			__MOD_INC_USE_COUNT(ct_helper->me);
 		} else {
-
 			/* We are a NAT helper for protocol X.  If we need
 			 * respective conntrack helper for protoccol X, compute
 			 * conntrack helper name and try to load module */
-			char name[MODULE_MAX_NAMELEN];
-			const char *tmp = me->me->name;
+			char name[MODULE_NAME_LEN];
+			const char *tmp = module_name(me->me);
 			
-			if (strlen(tmp) + 6 > MODULE_MAX_NAMELEN) {
+			if (strlen(tmp) + 6 > MODULE_NAME_LEN) {
 				printk("%s: unable to "
 				       "compute conntrack helper name "
 				       "from %s\n", __FUNCTION__, tmp);
@@ -466,9 +463,12 @@
 		if ((ct_helper = ip_ct_find_helper(&me->tuple))
 		    && ct_helper->me) {
 			__MOD_DEC_USE_COUNT(ct_helper->me);
-		} else 
+		}
+#ifdef CONFIG_MODULES
+		else 
 			printk("%s: unable to decrement usage count"
 			       " of conntrack helper %s\n",
 			       __FUNCTION__, me->me->name);
+#endif
 	}
 }
diff -Nru a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
--- a/net/ipv4/netfilter/ipt_TCPMSS.c	Sun Nov 17 20:30:14 2002
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c	Sun Nov 17 20:30:14 2002
@@ -92,7 +92,7 @@
 			return NF_DROP; /* or IPT_CONTINUE ?? */
 		}
 
-		newmss = dst_pmtu((*pskb)->dst->pmtu) - sizeof(struct iphdr) - sizeof(struct tcphdr);
+		newmss = dst_pmtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);
 	} else
 		newmss = tcpmssinfo->mss;
 
diff -Nru a/net/ipv4/proc.c b/net/ipv4/proc.c
--- a/net/ipv4/proc.c	Sun Nov 17 20:30:02 2002
+++ b/net/ipv4/proc.c	Sun Nov 17 20:30:02 2002
@@ -23,30 +23,21 @@
  *		Alan Cox	:	Handle dead sockets properly.
  *	Gerhard Koerting	:	Show both timers
  *		Alan Cox	:	Allow inode to be NULL (kernel socket)
- *	Andi Kleen		:	Add support for open_requests and 
+ *	Andi Kleen		:	Add support for open_requests and
  *					split functions for more readibility.
  *	Andi Kleen		:	Add support for /proc/net/netstat
+ *	Arnaldo C. Melo		:	Convert to seq_file
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
-#include <asm/system.h>
-#include <linux/sched.h>
-#include <linux/socket.h>
-#include <linux/net.h>
-#include <linux/un.h>
-#include <linux/in.h>
-#include <linux/param.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
+#include <linux/types.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
 #include <net/udp.h>
-#include <linux/skbuff.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <net/sock.h>
@@ -57,7 +48,7 @@
 	int res = 0;
 	int cpu;
 
-	for (cpu=0; cpu<NR_CPUS; cpu++)
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		res += proto->stats[cpu].inuse;
 
 	return res;
@@ -66,38 +57,35 @@
 /*
  *	Report socket allocation statistics [mea@utu.fi]
  */
-int afinet_get_info(char *buffer, char **start, off_t offset, int length)
+static int sockstat_seq_show(struct seq_file *seq, void *v)
 {
-	/* From  net/socket.c  */
-	extern int socket_get_info(char *, char **, off_t, int);
+	/* From net/socket.c */
+	extern void socket_seq_show(struct seq_file *seq);
 
-	int len  = socket_get_info(buffer,start,offset,length);
+	socket_seq_show(seq);
+	seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
+		   fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
+		   tcp_tw_count, atomic_read(&tcp_sockets_allocated),
+		   atomic_read(&tcp_memory_allocated));
+	seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
+	seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
+	seq_printf(seq,  "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
+		   atomic_read(&ip_frag_mem));
+	return 0;
+}
 
-	len += sprintf(buffer+len,"TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
-		       fold_prot_inuse(&tcp_prot),
-		       atomic_read(&tcp_orphan_count), tcp_tw_count,
-		       atomic_read(&tcp_sockets_allocated),
-		       atomic_read(&tcp_memory_allocated));
-	len += sprintf(buffer+len,"UDP: inuse %d\n",
-		       fold_prot_inuse(&udp_prot));
-	len += sprintf(buffer+len,"RAW: inuse %d\n",
-		       fold_prot_inuse(&raw_prot));
-	len += sprintf(buffer+len, "FRAG: inuse %d memory %d\n",
-		       ip_frag_nqueues, atomic_read(&ip_frag_mem));
-	if (offset >= len)
-	{
-		*start = buffer;
-		return 0;
-	}
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+static int sockstat_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sockstat_seq_show, NULL);
 }
 
+static struct file_operations sockstat_seq_fops = {
+	.open	 = sockstat_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
 static unsigned long fold_field(unsigned long *begin, int sz, int nr)
 {
 	unsigned long res = 0;
@@ -105,72 +93,91 @@
 
 	sz /= sizeof(unsigned long);
 
-	for (i=0; i<NR_CPUS; i++) {
-		res += begin[2*i*sz + nr];
-		res += begin[(2*i+1)*sz + nr];
+	for (i = 0; i < NR_CPUS; i++) {
+		res += begin[2 * i * sz + nr];
+		res += begin[(2 * i + 1) * sz + nr];
 	}
 	return res;
 }
 
-/* 
+/*
  *	Called from the PROCfs module. This outputs /proc/net/snmp.
  */
- 
-int snmp_get_info(char *buffer, char **start, off_t offset, int length)
+static int snmp_seq_show(struct seq_file *seq, void *v)
 {
 	extern int sysctl_ip_default_ttl;
-	int len, i;
+	int i;
 
-	len = sprintf (buffer,
-		"Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
-		"Ip: %d %d", ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
-	for (i=0; i<offsetof(struct ip_mib, __pad)/sizeof(unsigned long); i++)
-		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)ip_statistics, sizeof(struct ip_mib), i));
-
-	len += sprintf (buffer + len,
-		"\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
-		  "Icmp:");
-	for (i=0; i<offsetof(struct icmp_mib, dummy)/sizeof(unsigned long); i++)
-		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)icmp_statistics, sizeof(struct icmp_mib), i));
-
-	len += sprintf (buffer + len,
-		"\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts\n"
-		  "Tcp:");
-	for (i=0; i<offsetof(struct tcp_mib, __pad)/sizeof(unsigned long); i++)
-		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)tcp_statistics, sizeof(struct tcp_mib), i));
-
-	len += sprintf (buffer + len,
-		"\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
-		  "Udp:");
-	for (i=0; i<offsetof(struct udp_mib, __pad)/sizeof(unsigned long); i++)
-		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)udp_statistics, sizeof(struct udp_mib), i));
-
-	len += sprintf (buffer + len, "\n");
-
-	if (offset >= len)
-	{
-		*start = buffer;
-		return 0;
-	}
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0; 
-	return len;
+	seq_printf(seq, "Ip: Forwarding DefaultTTL InReceives InHdrErrors "
+			"InAddrErrors ForwDatagrams InUnknownProtos "
+			"InDiscards InDelivers OutRequests OutDiscards "
+			"OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs "
+			"ReasmFails FragOKs FragFails FragCreates\nIp: %d %d",
+			ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+
+	for (i = 0;
+	     i < offsetof(struct ip_mib, __pad) / sizeof(unsigned long); i++)
+		seq_printf(seq, " %lu",
+			   fold_field((unsigned long *)ip_statistics,
+				      sizeof(struct ip_mib), i));
+
+	seq_printf(seq, "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds "
+			"InParmProbs InSrcQuenchs InRedirects InEchos "
+			"InEchoReps InTimestamps InTimestampReps InAddrMasks "
+			"InAddrMaskReps OutMsgs OutErrors OutDestUnreachs "
+			"OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects "
+			"OutEchos OutEchoReps OutTimestamps OutTimestampReps "
+			"OutAddrMasks OutAddrMaskReps\nIcmp:");
+
+	for (i = 0;
+	     i < offsetof(struct icmp_mib, dummy) / sizeof(unsigned long); i++)
+		seq_printf(seq, " %lu",
+			   fold_field((unsigned long *)icmp_statistics,
+				      sizeof(struct icmp_mib), i));
+
+	seq_printf(seq, "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens "
+			"PassiveOpens AttemptFails EstabResets CurrEstab "
+			"InSegs OutSegs RetransSegs InErrs OutRsts\nTcp:");
+
+	for (i = 0;
+	     i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++)
+		seq_printf(seq, " %lu",
+			   fold_field((unsigned long *)tcp_statistics,
+				      sizeof(struct tcp_mib), i));
+
+	seq_printf(seq, "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
+			"Udp:");
+
+	for (i = 0;
+	     i < offsetof(struct udp_mib, __pad) / sizeof(unsigned long); i++)
+		seq_printf(seq, " %lu",
+			   fold_field((unsigned long *)udp_statistics,
+				      sizeof(struct udp_mib), i));
+
+	seq_putc(seq, '\n');
+	return 0;
+}
+
+static int snmp_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, snmp_seq_show, NULL);
 }
 
-/* 
+static struct file_operations snmp_seq_fops = {
+	.open	 = snmp_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+/*
  *	Output /proc/net/netstat
  */
- 
-int netstat_get_info(char *buffer, char **start, off_t offset, int length)
+static int netstat_seq_show(struct seq_file *seq, void *v)
 {
-	int len, i;
+	int i;
 
-	len = sprintf(buffer,
-		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
+	seq_puts(seq, "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
 		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
 		      " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
 		      " TW TWRecycled TWKilled"
@@ -183,7 +190,8 @@
 		      " TCPPureAcks TCPHPAcks"
 		      " TCPRenoRecovery TCPSackRecovery"
 		      " TCPSACKReneging"
-		      " TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder"
+		      " TCPFACKReorder TCPSACKReorder TCPRenoReorder"
+		      " TCPTSReorder"
 		      " TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo"
 		      " TCPLoss TCPLostRetransmit"
 		      " TCPRenoFailures TCPSackFailures TCPLossFailures"
@@ -191,46 +199,58 @@
 		      " TCPTimeouts"
 		      " TCPRenoRecoveryFail TCPSackRecoveryFail"
 		      " TCPSchedulerFailed TCPRcvCollapsed"
-		      " TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv"
+		      " TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv"
+		      " TCPDSACKOfoRecv"
 		      " TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose"
 		      " TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger"
 		      " TCPAbortFailed TCPMemoryPressures\n"
 		      "TcpExt:");
-	for (i=0; i<offsetof(struct linux_mib, __pad)/sizeof(unsigned long); i++)
-		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)net_statistics, sizeof(struct linux_mib), i));
-
-	len += sprintf (buffer + len, "\n");
+	for (i = 0;
+	     i < offsetof(struct linux_mib, __pad) / sizeof(unsigned long); i++)
+		seq_printf(seq, " %lu",
+			   fold_field((unsigned long *)net_statistics,
+				      sizeof(struct linux_mib), i));
+	seq_putc(seq, '\n');
+	return 0;
+}
 
-	if (offset >= len)
-	{
-		*start = buffer;
-		return 0;
-	}
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0; 
-	return len;
+static int netstat_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, netstat_seq_show, NULL);
 }
 
+static struct file_operations netstat_seq_fops = {
+	.open	 = netstat_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
 int __init ip_misc_proc_init(void)
 {
 	int rc = 0;
+	struct proc_dir_entry *p;
 
-	if (!proc_net_create("netstat", 0, netstat_get_info))
+	p = create_proc_entry("netstat", S_IRUGO, proc_net);
+	if (!p)
 		goto out_netstat;
-	if (!proc_net_create("snmp", 0, snmp_get_info))
+	p->proc_fops = &netstat_seq_fops;
+
+	p = create_proc_entry("snmp", S_IRUGO, proc_net);
+	if (!p)
 		goto out_snmp;
-	if (!proc_net_create("sockstat", 0, afinet_get_info))
+	p->proc_fops = &snmp_seq_fops;
+
+	p = create_proc_entry("sockstat", S_IRUGO, proc_net);
+	if (!p)
 		goto out_sockstat;
+	p->proc_fops = &sockstat_seq_fops;
 out:
 	return rc;
 out_sockstat:
-	proc_net_remove("snmp");
+	remove_proc_entry("snmp", proc_net);
 out_snmp:
-	proc_net_remove("netstat");
+	remove_proc_entry("netstat", proc_net);
 out_netstat:
 	rc = -ENOMEM;
 	goto out;
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Sun Nov 17 20:30:02 2002
+++ b/net/ipv4/raw.c	Sun Nov 17 20:30:02 2002
@@ -40,31 +40,43 @@
  */
  
 #include <linux/config.h> 
-#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+#include <asm/current.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
+#include <linux/aio.h>
 #include <linux/kernel.h>
-#include <linux/fcntl.h>
+#include <linux/spinlock.h>
+#include <linux/sockios.h>
 #include <linux/socket.h>
 #include <linux/in.h>
-#include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/mroute.h>
-#include <net/tcp.h>
-#include <net/protocol.h>
+#include <linux/in_route.h>
+#include <linux/route.h>
+#include <linux/tcp.h>
 #include <linux/skbuff.h>
+#include <net/dst.h>
 #include <net/sock.h>
+#include <linux/gfp.h>
+#include <linux/ip.h>
+#include <linux/net.h>
+#include <net/ip.h>
 #include <net/icmp.h>
 #include <net/udp.h>
 #include <net/raw.h>
+#include <net/snmp.h>
 #include <net/inet_common.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
+#include <linux/rtnetlink.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 
 struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
@@ -431,7 +443,7 @@
 						.saddr = saddr,
 						.tos = tos } },
 				    .proto = inet->hdrincl ? IPPROTO_RAW : sk->protocol };
-		err = ip_route_output_flow(&rt, &fl, sk, msg->msg_flags&MSG_DONTWAIT);
+		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
 	}
 	if (err)
 		goto done;
@@ -656,7 +668,95 @@
 	}
 }
 
-static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
+struct proto raw_prot = {
+	.name =		"RAW",
+	.close =	raw_close,
+	.connect =	udp_connect,
+	.disconnect =	udp_disconnect,
+	.ioctl =	raw_ioctl,
+	.init =		raw_init,
+	.setsockopt =	raw_setsockopt,
+	.getsockopt =	raw_getsockopt,
+	.sendmsg =	raw_sendmsg,
+	.recvmsg =	raw_recvmsg,
+	.bind =		raw_bind,
+	.backlog_rcv =	raw_rcv_skb,
+	.hash =		raw_v4_hash,
+	.unhash =	raw_v4_unhash,
+};
+
+#ifdef CONFIG_PROC_FS
+struct raw_iter_state {
+	int bucket;
+};
+
+#define raw_seq_private(seq) ((struct raw_iter_state *)&seq->private)
+
+static struct sock *raw_get_first(struct seq_file *seq)
+{
+	struct sock *sk = NULL;
+	struct raw_iter_state* state = raw_seq_private(seq);
+
+	for (state->bucket = 0; state->bucket < RAWV4_HTABLE_SIZE; ++state->bucket) {
+		sk = raw_v4_htable[state->bucket];
+		while (sk && sk->family != PF_INET)
+			sk = sk->next;
+		if (sk)
+			break;
+	}
+	return sk;
+}
+
+static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
+{
+	struct raw_iter_state* state = raw_seq_private(seq);
+
+	do {
+		sk = sk->next;
+try_again:
+	} while (sk && sk->family != PF_INET);
+
+	if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
+		sk = raw_v4_htable[state->bucket];
+		goto try_again;
+	}
+	return sk;
+}
+
+static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct sock *sk = raw_get_first(seq);
+
+	if (sk)
+		while (pos && (sk = raw_get_next(seq, sk)) != NULL)
+			--pos;
+	return pos ? NULL : sk;
+}
+
+static void *raw_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&raw_v4_lock);
+	return *pos ? raw_get_idx(seq, *pos) : (void *)1;
+}
+
+static void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct sock *sk;
+
+	if (v == (void *)1)
+		sk = raw_get_first(seq);
+	else
+		sk = raw_get_next(seq, v);
+	++*pos;
+	return sk;
+}
+
+static void raw_seq_stop(struct seq_file *seq, void *v)
+{
+	read_unlock(&raw_v4_lock);
+}
+
+static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i)
 {
 	struct inet_opt *inet = inet_sk(sp);
 	unsigned int dest = inet->daddr,
@@ -668,65 +768,63 @@
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
 		i, src, srcp, dest, destp, sp->state, 
 		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
-		0, 0L, 0,
-		sock_i_uid(sp), 0,
-		sock_i_ino(sp),
+		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
 		atomic_read(&sp->refcnt), sp);
+	return tmpbuf;
 }
 
-int raw_get_info(char *buffer, char **start, off_t offset, int length)
+static int raw_seq_show(struct seq_file *seq, void *v)
 {
-	int len = 0, num = 0, i;
-	off_t pos = 128;
-	off_t begin;
 	char tmpbuf[129];
 
-	if (offset < 128) 
-		len += sprintf(buffer, "%-127s\n",
+	if (v == (void *)1)
+		seq_printf(seq, "%-127s\n",
 			       "  sl  local_address rem_address   st tx_queue "
 			       "rx_queue tr tm->when retrnsmt   uid  timeout "
 			       "inode");
-	read_lock(&raw_v4_lock);
-	for (i = 0; i < RAWV4_HTABLE_SIZE; i++) {
-		struct sock *sk;
+	else {
+		struct raw_iter_state *state = raw_seq_private(seq);
 
-		for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
-			if (sk->family != PF_INET)
-				continue;
-			pos += 128;
-			if (pos <= offset)
-				continue;
-			get_raw_sock(sk, tmpbuf, i);
-			len += sprintf(buffer + len, "%-127s\n", tmpbuf);
-			if (len >= length)
-				goto out;
-		}
+		seq_printf(seq, "%-127s\n",
+			   get_raw_sock(v, tmpbuf, state->bucket));
 	}
-out:
-	read_unlock(&raw_v4_lock);
-	begin = len - (pos - offset);
-	*start = buffer + begin;
-	len -= begin;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0; 
-	return len;
+	return 0;
 }
 
-struct proto raw_prot = {
-	.name =		"RAW",
-	.close =	raw_close,
-	.connect =	udp_connect,
-	.disconnect =	udp_disconnect,
-	.ioctl =	raw_ioctl,
-	.init =		raw_init,
-	.setsockopt =	raw_setsockopt,
-	.getsockopt =	raw_getsockopt,
-	.sendmsg =	raw_sendmsg,
-	.recvmsg =	raw_recvmsg,
-	.bind =		raw_bind,
-	.backlog_rcv =	raw_rcv_skb,
-	.hash =		raw_v4_hash,
-	.unhash =	raw_v4_unhash,
+static struct seq_operations raw_seq_ops = {
+	.start = raw_seq_start,
+	.next  = raw_seq_next,
+	.stop  = raw_seq_stop,
+	.show  = raw_seq_show,
+};
+
+static int raw_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &raw_seq_ops);
+}
+
+static struct file_operations raw_seq_fops = {
+	.open	 = raw_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
 };
+
+int __init raw_proc_init(void)
+{
+	struct proc_dir_entry *p;
+	int rc = 0;
+
+	p = create_proc_entry("raw", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &raw_seq_fops;
+	else
+		rc = -ENOMEM;
+	return rc;
+}
+
+void __init raw_proc_exit(void)
+{
+	remove_proc_entry("raw", proc_net);
+}
+#endif /* CONFIG_PROC_FS */
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Sun Nov 17 20:30:12 2002
+++ b/net/ipv4/tcp_ipv4.c	Sun Nov 17 20:30:12 2002
@@ -780,7 +780,7 @@
 	tmp = ip_route_connect(&rt, nexthop, inet->saddr,
 			       RT_CONN_FLAGS(sk), sk->bound_dev_if,
 			       IPPROTO_TCP,
-			       inet->sport, usin->sin_port);
+			       inet->sport, usin->sin_port, sk);
 	if (tmp < 0)
 		return tmp;
 
@@ -837,7 +837,7 @@
 	if (err)
 		goto failure;
 
-	err = ip_route_newports(&rt, inet->sport, inet->dport);
+	err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
 	if (err)
 		goto failure;
 
@@ -1896,7 +1896,7 @@
 			       RT_TOS(inet->tos) | sk->localroute,
 			       sk->bound_dev_if,
 			       IPPROTO_TCP,
-			       inet->sport, inet->dport);
+			       inet->sport, inet->dport, sk);
 	if (err)
 		return err;
 
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Sun Nov 17 20:30:04 2002
+++ b/net/ipv4/udp.c	Sun Nov 17 20:30:04 2002
@@ -601,7 +601,7 @@
 				    .uli_u = { .ports =
 					       { .sport = inet->sport,
 						 .dport = dport } } };
-		err = ip_route_output_flow(&rt, &fl, sk, msg->msg_flags&MSG_DONTWAIT);
+		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
 		if (err)
 			goto out;
 
@@ -884,7 +884,7 @@
 	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
 			       RT_CONN_FLAGS(sk), oif,
 			       IPPROTO_UDP,
-			       inet->sport, usin->sin_port);
+			       inet->sport, usin->sin_port, sk);
 	if (err)
 		return err;
 	if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
@@ -944,7 +944,7 @@
 	/*
 	 *	Charge it to the socket, dropping if the queue is full.
 	 */
-	if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb)) {
 		kfree_skb(skb);
 		return -1;
 	}
@@ -1376,17 +1376,5 @@
 void __init udp_proc_exit(void)
 {
 	remove_proc_entry("udp", proc_net);
-}
-
-#else /* CONFIG_PROC_FS */
-
-int __init udp_proc_init(void)
-{
-	return 0;
-}
-
-void __init udp_proc_exit(void)
-{
-	return 0;
 }
 #endif /* CONFIG_PROC_FS */
diff -Nru a/net/ipv4/xfrm_input.c b/net/ipv4/xfrm_input.c
--- a/net/ipv4/xfrm_input.c	Sun Nov 17 20:30:02 2002
+++ b/net/ipv4/xfrm_input.c	Sun Nov 17 20:30:02 2002
@@ -91,7 +91,7 @@
 		iph = skb->nh.iph;
 
 		if (x->props.mode) {
-			if (iph->protocol != IPPROTO_IP)
+			if (iph->protocol != IPPROTO_IPIP)
 				goto drop;
 			skb->nh.raw = skb->data;
 			iph = skb->nh.iph;
diff -Nru a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
--- a/net/ipv4/xfrm_policy.c	Sun Nov 17 20:30:14 2002
+++ b/net/ipv4/xfrm_policy.c	Sun Nov 17 20:30:14 2002
@@ -1,10 +1,12 @@
 #include <net/xfrm.h>
 #include <net/ip.h>
 
+DECLARE_MUTEX(xfrm_cfg_sem);
+
 static u32      xfrm_policy_genid;
 static rwlock_t xfrm_policy_lock = RW_LOCK_UNLOCKED;
 
-struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX];
+struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 extern struct dst_ops xfrm4_dst_ops;
 
@@ -263,10 +265,13 @@
 {
 	u32 idx;
 	struct xfrm_policy *p;
-	static u32 pol_id;
+	static u32 idx_generator;
 
 	for (;;) {
-		idx = (++pol_id ? : ++pol_id);
+		idx = (idx_generator | dir);
+		idx_generator += 8;
+		if (idx == 0)
+			idx = 8;
 		for (p = xfrm_policy_list[dir]; p; p = p->next) {
 			if (p->index == idx)
 				break;
@@ -300,6 +305,7 @@
 	write_unlock_bh(&xfrm_policy_lock);
 
 	if (pol) {
+		atomic_dec(&pol->refcnt);
 		xfrm_policy_kill(pol);
 		xfrm_pol_put(pol);
 	}
@@ -328,7 +334,7 @@
 	struct xfrm_policy *pol, **p;
 
 	write_lock_bh(&xfrm_policy_lock);
-	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
+	for (p = &xfrm_policy_list[id & 7]; (pol=*p)!=NULL; p = &pol->next) {
 		if (pol->index == id) {
 			if (delete)
 				*p = pol->next;
@@ -375,7 +381,7 @@
 	int error = 0;
 
 	read_lock(&xfrm_policy_lock);
-	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+	for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
 		for (xp = xfrm_policy_list[dir]; xp; xp = xp->next)
 			count++;
 	}
@@ -385,9 +391,9 @@
 		goto out;
 	}
 
-	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+	for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
 		for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) {
-			error = func(xp, dir, --count, data);
+			error = func(xp, dir%XFRM_POLICY_MAX, --count, data);
 			if (error)
 				goto out;
 		}
@@ -423,18 +429,37 @@
 	struct xfrm_policy *pol;
 
 	read_lock(&xfrm_policy_lock);
-	for (pol = sk->policy[dir]; pol; pol = pol->next) {
-		struct xfrm_selector *sel = &pol->selector;
-
-		if (xfrm4_selector_match(sel, fl)) {
+	if ((pol = sk->policy[dir]) != NULL) {
+		if (xfrm4_selector_match(&pol->selector, fl))
 			atomic_inc(&pol->refcnt);
-			break;
-		}
+		else
+			pol = NULL;
 	}
 	read_unlock(&xfrm_policy_lock);
 	return pol;
 }
 
+void xfrm_sk_policy_link(struct xfrm_policy *pol, int dir)
+{
+	pol->next = xfrm_policy_list[XFRM_POLICY_MAX+dir];
+	xfrm_policy_list[XFRM_POLICY_MAX+dir] = pol;
+	atomic_inc(&pol->refcnt);
+}
+
+void xfrm_sk_policy_unlink(struct xfrm_policy *pol, int dir)
+{
+	struct xfrm_policy **polp;
+
+	for (polp = &xfrm_policy_list[XFRM_POLICY_MAX+dir];
+	     *polp != NULL; polp = &(*polp)->next) {
+		if (*polp == pol) {
+			*polp = pol->next;
+			atomic_dec(&pol->refcnt);
+			return;
+		}
+	}
+}
+
 int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
 {
 	struct xfrm_policy *old_pol;
@@ -442,6 +467,13 @@
 	write_lock_bh(&xfrm_policy_lock);
 	old_pol = sk->policy[dir];
 	sk->policy[dir] = pol;
+	if (pol) {
+		pol->curlft.add_time = (unsigned long)xtime.tv_sec;
+		pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir);
+		xfrm_sk_policy_link(pol, dir);
+	}
+	if (old_pol)
+		xfrm_sk_policy_unlink(old_pol, dir);
 	write_unlock_bh(&xfrm_policy_lock);
 
 	if (old_pol) {
@@ -451,7 +483,7 @@
 	return 0;
 }
 
-static struct xfrm_policy *clone_policy(struct xfrm_policy *old)
+static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
 {
 	struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC);
 
@@ -462,8 +494,12 @@
 		newp->action = old->action;
 		newp->flags = old->flags;
 		newp->xfrm_nr = old->xfrm_nr;
+		newp->index = old->index;
 		memcpy(newp->xfrm_vec, old->xfrm_vec,
 		       newp->xfrm_nr*sizeof(struct xfrm_tmpl));
+		write_lock_bh(&xfrm_policy_lock);
+		xfrm_sk_policy_link(newp, dir);
+		write_unlock_bh(&xfrm_policy_lock);
 	}
 	return newp;
 }
@@ -475,15 +511,19 @@
 	p1 = sk->policy[1];
 	sk->policy[0] = NULL;
 	sk->policy[1] = NULL;
-	if (p0 && (sk->policy[0] = clone_policy(p0)) == NULL)
+	if (p0 && (sk->policy[0] = clone_policy(p0, 0)) == NULL)
 		return -ENOMEM;
-	if (p1 && (sk->policy[1] = clone_policy(p1)) == NULL)
+	if (p1 && (sk->policy[1] = clone_policy(p1, 1)) == NULL)
 		return -ENOMEM;
 	return 0;
 }
 
-void __xfrm_sk_free_policy(struct xfrm_policy *pol)
+void __xfrm_sk_free_policy(struct xfrm_policy *pol, int dir)
 {
+	write_lock_bh(&xfrm_policy_lock);
+	xfrm_sk_policy_unlink(pol, dir);
+	write_unlock_bh(&xfrm_policy_lock);
+
 	xfrm_policy_kill(pol);
 	xfrm_pol_put(pol);
 }
@@ -734,12 +774,12 @@
 					goto error;
 
 				__set_task_state(tsk, TASK_INTERRUPTIBLE);
-				add_wait_queue(km_waitq, &wait);
+				add_wait_queue(&km_waitq, &wait);
 				err = xfrm_tmpl_resolve(policy, fl, xfrm);
 				if (err == -EAGAIN)
 					schedule();
 				__set_task_state(tsk, TASK_RUNNING);
-				remove_wait_queue(km_waitq, &wait);
+				remove_wait_queue(&km_waitq, &wait);
 
 				if (err == -EAGAIN && signal_pending(current)) {
 					err = -ERESTART;
@@ -888,7 +928,7 @@
 
 	pol = NULL;
 	if (sk && sk->policy[dir])
-		pol =xfrm_sk_policy_lookup(sk, dir, &fl);
+		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
 	if (!pol)
 		pol = flow_lookup(dir, &fl);
@@ -985,7 +1025,7 @@
 	struct dst_entry *dst, **dstp, *gc_list = NULL;
 
 	read_lock_bh(&xfrm_policy_lock);
-	for (i=0; i<XFRM_POLICY_MAX; i++) {
+	for (i=0; i<2*XFRM_POLICY_MAX; i++) {
 		for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
 			write_lock(&pol->lock);
 			dstp = &pol->bundles;
@@ -1028,7 +1068,7 @@
 	struct dst_entry *dst, **dstp, *gc_list = NULL;
 
 	read_lock_bh(&xfrm_policy_lock);
-	for (i=0; i<XFRM_POLICY_MAX; i++) {
+	for (i=0; i<2*XFRM_POLICY_MAX; i++) {
 		for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
 			write_lock(&pol->lock);
 			dstp = &pol->bundles;
diff -Nru a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c
--- a/net/ipv4/xfrm_state.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv4/xfrm_state.c	Sun Nov 17 20:30:15 2002
@@ -22,7 +22,7 @@
 static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
 static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
 
-wait_queue_head_t *km_waitq;
+DECLARE_WAIT_QUEUE_HEAD(km_waitq);
 
 #define ACQ_EXPIRES 30
 
@@ -163,7 +163,7 @@
 
 	if (kill && x->type)
 		x->type->destructor(x);
-	wake_up(km_waitq);
+	wake_up(&km_waitq);
 }
 
 void xfrm_state_delete(struct xfrm_state *x)
@@ -195,7 +195,7 @@
 		}
 	}
 	spin_unlock_bh(&xfrm_state_lock);
-	wake_up(km_waitq);
+	wake_up(&km_waitq);
 }
 
 struct xfrm_state *
@@ -213,6 +213,7 @@
 	spin_lock_bh(&xfrm_state_lock);
 	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
 		if (daddr == x->id.daddr.xfrm4_addr &&
+		    x->props.reqid == tmpl->reqid &&
 		    (saddr == x->props.saddr.xfrm4_addr || !saddr || !x->props.saddr.xfrm4_addr) &&
 		    tmpl->mode == x->props.mode &&
 		    tmpl->id.proto == x->id.proto) {
@@ -278,6 +279,7 @@
 		if (x->props.saddr.xfrm4_addr == 0)
 			x->props.saddr.xfrm4_addr = saddr;
 		x->props.mode = tmpl->mode;
+		x->props.reqid = tmpl->reqid;
 
 		if (km_query(x, tmpl, pol) == 0) {
 			x->km.state = XFRM_STATE_ACQ;
@@ -323,7 +325,7 @@
 		atomic_inc(&x->refcnt);
 
 	spin_unlock_bh(&xfrm_state_lock);
-	wake_up(km_waitq);
+	wake_up(&km_waitq);
 }
 
 int xfrm_state_check_expire(struct xfrm_state *x)
@@ -384,7 +386,7 @@
 }
 
 struct xfrm_state *
-xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
+xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
 {
 	struct xfrm_state *x, *x0;
 	unsigned h = ntohl(daddr);
@@ -398,10 +400,11 @@
 		    mode == x->props.mode &&
 		    proto == x->id.proto &&
 		    saddr == x->props.saddr.xfrm4_addr &&
-		    (!reqid || reqid == x->props.reqid)) {
+		    reqid == x->props.reqid &&
+		    x->km.state == XFRM_STATE_ACQ) {
 			    if (!x0)
 				    x0 = x;
-			    if (x->km.state != XFRM_STATE_ACQ)
+			    if (x->id.spi)
 				    continue;
 			    x0 = x;
 			    break;
@@ -409,7 +412,7 @@
 	}
 	if (x0) {
 		atomic_inc(&x0->refcnt);
-	} else if ((x0 = xfrm_state_alloc()) != NULL) {
+	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
 		x0->sel.daddr.xfrm4_addr = daddr;
 		x0->sel.daddr.xfrm4_mask = ~0;
 		x0->sel.saddr.xfrm4_addr = saddr;
@@ -427,7 +430,7 @@
 		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
 		atomic_inc(&x0->refcnt);
 		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
-		wake_up(km_waitq);
+		wake_up(&km_waitq);
 	}
 	spin_unlock_bh(&xfrm_state_lock);
 	return x0;
@@ -491,7 +494,7 @@
 		list_add(&x->byspi, xfrm_state_byspi+h);
 		atomic_inc(&x->refcnt);
 		spin_unlock_bh(&xfrm_state_lock);
-		wake_up(km_waitq);
+		wake_up(&km_waitq);
 	}
 }
 
diff -Nru a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/ipv4/xfrm_user.c	Sun Nov 17 20:30:16 2002
@@ -0,0 +1,1045 @@
+/* xfrm_user.c: User interface to configure xfrm engine.
+ *
+ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+#include <linux/string.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/pfkeyv2.h>
+#include <linux/ipsec.h>
+#include <linux/init.h>
+#include <net/sock.h>
+#include <net/xfrm.h>
+
+static struct sock *xfrm_nl;
+
+static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
+{
+	struct rtattr *rt = xfrma[type];
+	struct xfrm_algo *algp;
+
+	if (!rt)
+		return 0;
+
+	if ((rt->rta_len - sizeof(*rt)) < sizeof(*algp))
+		return -EINVAL;
+
+	algp = RTA_DATA(rt);
+	switch (type) {
+	case XFRMA_ALG_AUTH:
+	case XFRMA_ALG_CRYPT:
+		if (!algp->alg_key_len)
+			return -EINVAL;
+		break;
+
+	case XFRMA_ALG_COMP:
+		/* Zero length keys are legal.  */
+		break;
+
+	default:
+		return -EINVAL;
+	};
+
+	algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
+	return 0;
+}
+
+static int verify_newsa_info(struct xfrm_usersa_info *p,
+			     struct rtattr **xfrma)
+{
+	int err;
+
+	err = -EINVAL;
+	switch (p->family) {
+	case AF_INET:
+		break;
+
+	case AF_INET6: /* XXX */
+		err = -EAFNOSUPPORT;
+
+		/* fallthru */
+	default:
+		goto out;
+	};
+
+	err = -EINVAL;
+	switch (p->id.proto) {
+	case IPPROTO_AH:
+		if (!xfrma[XFRMA_ALG_AUTH]	||
+		    xfrma[XFRMA_ALG_CRYPT]	||
+		    xfrma[XFRMA_ALG_COMP])
+			goto out;
+		break;
+
+	case IPPROTO_ESP:
+		if ((!xfrma[XFRMA_ALG_AUTH] &&
+		     !xfrma[XFRMA_ALG_CRYPT])	||
+		    xfrma[XFRMA_ALG_COMP])
+			goto out;
+		break;
+
+	case IPPROTO_COMP:
+		if (!xfrma[XFRMA_ALG_COMP]	||
+		    xfrma[XFRMA_ALG_AUTH]	||
+		    xfrma[XFRMA_ALG_CRYPT])
+			goto out;
+		break;
+
+	default:
+		goto out;
+	};
+
+	if ((err = verify_one_alg(xfrma, XFRMA_ALG_AUTH)))
+		goto out;
+	if ((err = verify_one_alg(xfrma, XFRMA_ALG_CRYPT)))
+		goto out;
+	if ((err = verify_one_alg(xfrma, XFRMA_ALG_COMP)))
+		goto out;
+
+	err = -EINVAL;
+	switch (p->mode) {
+	case 0:
+	case 1:
+		break;
+
+	default:
+		goto out;
+	};
+
+	err = 0;
+
+out:
+	return err;
+}
+
+static int attach_one_algo(struct xfrm_algo **algpp, struct rtattr *u_arg)
+{
+	struct rtattr *rta = u_arg;
+	struct xfrm_algo *p, *ualg;
+
+	if (!rta)
+		return 0;
+
+	ualg = RTA_DATA(rta);
+	p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	memcpy(p, ualg, sizeof(*ualg) + ualg->alg_key_len);
+	*algpp = p;
+	return 0;
+}
+
+static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
+{
+	memcpy(&x->id, &p->id, sizeof(x->id));
+	memcpy(&x->sel, &p->sel, sizeof(x->sel));
+	memcpy(&x->lft, &p->lft, sizeof(x->lft));
+	x->props.mode = p->mode;
+	x->props.replay_window = p->replay_window;
+	x->props.reqid = p->reqid;
+	x->props.family = p->family;
+	x->props.saddr = x->sel.saddr;
+}
+
+static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
+					       struct rtattr **xfrma,
+					       int *errp)
+{
+	struct xfrm_state *x = xfrm_state_alloc();
+	int err = -ENOMEM;
+
+	if (!x)
+		goto error_no_put;
+
+	copy_from_user_state(x, p);
+
+	if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH])))
+		goto error;
+	if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT])))
+		goto error;
+	if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP])))
+		goto error;
+
+	err = -ENOENT;
+	x->type = xfrm_get_type(x->id.proto);
+	if (x->type == NULL)
+		goto error;
+
+	err = x->type->init_state(x, NULL);
+	if (err)
+		goto error;
+
+	x->curlft.add_time = (unsigned long) xtime.tv_sec;
+	x->km.state = XFRM_STATE_VALID;
+	x->km.seq = p->seq;
+
+	return x;
+
+error:
+	xfrm_state_put(x);
+error_no_put:
+	*errp = err;
+	return NULL;
+}
+
+static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
+	struct xfrm_state *x, *x1;
+	int err;
+
+	err = verify_newsa_info(p, (struct rtattr **) xfrma);
+	if (err)
+		return err;
+
+	x = xfrm_state_construct(p, (struct rtattr **) xfrma, &err);
+	if (!x)
+		return err;
+
+	x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
+			       x->id.spi, x->id.proto);
+	if (x1) {
+		xfrm_state_put(x);
+		xfrm_state_put(x1);
+		return -EEXIST;
+	}
+
+	xfrm_state_insert(x);
+
+	return 0;
+}
+
+static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_state *x;
+	struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
+
+	x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+	if (x == NULL)
+		return -ESRCH;
+
+	xfrm_state_delete(x);
+	xfrm_state_put(x);
+
+	return 0;
+}
+
+static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
+{
+	memcpy(&p->id, &x->id, sizeof(p->id));
+	memcpy(&p->sel, &x->sel, sizeof(p->sel));
+	memcpy(&p->lft, &x->lft, sizeof(p->lft));
+	memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
+	memcpy(&p->stats, &x->stats, sizeof(p->stats));
+	p->mode = x->props.mode;
+	p->replay_window = x->props.replay_window;
+	p->reqid = x->props.reqid;
+	p->family = x->props.family;
+	p->seq = x->km.seq;
+}
+
+struct xfrm_dump_info {
+	struct sk_buff *in_skb;
+	struct sk_buff *out_skb;
+	u32 nlmsg_seq;
+	int start_idx;
+	int this_idx;
+};
+
+static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+{
+	struct xfrm_dump_info *sp = ptr;
+	struct sk_buff *in_skb = sp->in_skb;
+	struct sk_buff *skb = sp->out_skb;
+	struct xfrm_usersa_info *p;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+
+	if (sp->this_idx < sp->start_idx)
+		goto out;
+
+	nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid,
+			sp->nlmsg_seq,
+			XFRM_MSG_NEWSA, sizeof(*p));
+	nlh->nlmsg_flags = 0;
+
+	p = NLMSG_DATA(nlh);
+	copy_to_user_state(x, p);
+
+	if (x->aalg)
+		RTA_PUT(skb, XFRMA_ALG_AUTH, sizeof(*(x->aalg)), x->aalg);
+	if (x->ealg)
+		RTA_PUT(skb, XFRMA_ALG_CRYPT, sizeof(*(x->ealg)), x->ealg);
+	if (x->calg)
+		RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
+
+	nlh->nlmsg_len = skb->tail - b;
+out:
+	sp->this_idx++;
+	return 0;
+
+nlmsg_failure:
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct xfrm_dump_info info;
+
+	info.in_skb = cb->skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.this_idx = 0;
+	info.start_idx = cb->args[0];
+	(void) xfrm_state_walk(IPSEC_PROTO_ANY, dump_one_state, &info);
+	cb->args[0] = info.this_idx;
+
+	return skb->len;
+}
+
+static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
+					  struct xfrm_state *x, u32 seq)
+{
+	struct xfrm_dump_info info;
+	struct sk_buff *skb;
+
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+	info.in_skb = in_skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = seq;
+	info.this_idx = info.start_idx = 0;
+
+	if (dump_one_state(x, 0, &info)) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	return skb;
+}
+
+static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
+	struct xfrm_state *x;
+	struct sk_buff *resp_skb;
+	int err;
+
+	x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+	err = -ESRCH;
+	if (x == NULL)
+		goto out_noput;
+
+	resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
+	if (IS_ERR(resp_skb)) {
+		err = PTR_ERR(resp_skb);
+	} else {
+		err = netlink_unicast(xfrm_nl, resp_skb,
+				      NETLINK_CB(skb).pid, MSG_DONTWAIT);
+	}
+	xfrm_state_put(x);
+out_noput:
+	return err;
+}
+
+static int verify_userspi_info(struct xfrm_userspi_info *p)
+{
+	switch (p->info.id.proto) {
+	case IPPROTO_AH:
+	case IPPROTO_ESP:
+		break;
+
+	case IPPROTO_COMP:
+		/* IPCOMP spi is 16-bits. */
+		if (p->min >= 0x10000 ||
+		    p->max >= 0x10000)
+			return -EINVAL;
+
+	default:
+		return -EINVAL;
+	};
+
+	if (p->min > p->max)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_state *x;
+	struct xfrm_userspi_info *p;
+	struct sk_buff *resp_skb;
+	int err;
+
+	p = NLMSG_DATA(nlh);
+	err = verify_userspi_info(p);
+	if (err)
+		goto out_noput;
+	x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
+			  p->info.sel.daddr.xfrm4_addr,
+			  p->info.sel.saddr.xfrm4_addr, 1);
+	err = -ENOENT;
+	if (x == NULL)
+		goto out_noput;
+
+	resp_skb = ERR_PTR(-ENOENT);
+
+	spin_lock_bh(&x->lock);
+	if (x->km.state != XFRM_STATE_DEAD) {
+		xfrm_alloc_spi(x, p->min, p->max);
+		if (x->id.spi)
+			resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
+	}
+	spin_unlock_bh(&x->lock);
+
+	if (IS_ERR(resp_skb)) {
+		err = PTR_ERR(resp_skb);
+		goto out;
+	}
+
+	err = netlink_unicast(xfrm_nl, resp_skb,
+			      NETLINK_CB(skb).pid, MSG_DONTWAIT);
+
+out:
+	xfrm_state_put(x);
+out_noput:
+	return err;
+}
+
+static int verify_policy_dir(__u8 dir)
+{
+	switch (dir) {
+	case XFRM_POLICY_IN:
+	case XFRM_POLICY_OUT:
+	case XFRM_POLICY_FWD:
+		break;
+
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
+{
+	switch (p->share) {
+	case XFRM_SHARE_ANY:
+	case XFRM_SHARE_SESSION:
+	case XFRM_SHARE_USER:
+	case XFRM_SHARE_UNIQUE:
+		break;
+
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->action) {
+	case XFRM_POLICY_ALLOW:
+	case XFRM_POLICY_BLOCK:
+		break;
+
+	default:
+		return -EINVAL;
+	};
+
+	return verify_policy_dir(p->dir);
+}
+
+static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
+			   int nr)
+{
+	int i;
+
+	xp->xfrm_nr = nr;
+	for (i = 0; i < nr; i++, ut++) {
+		struct xfrm_tmpl *t = &xp->xfrm_vec[i];
+
+		memcpy(&t->id, &ut->id, sizeof(struct xfrm_id));
+		memcpy(&t->saddr, &ut->saddr,
+		       sizeof(xfrm_address_t));
+		t->reqid = ut->reqid;
+		t->mode = ut->mode;
+		t->share = ut->share;
+		t->optional = ut->optional;
+		t->aalgos = ut->aalgos;
+		t->ealgos = ut->ealgos;
+		t->calgos = ut->calgos;
+	}
+}
+
+static int copy_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma)
+{
+	struct rtattr *rt = xfrma[XFRMA_TMPL];
+	struct xfrm_user_tmpl *utmpl;
+	int nr;
+
+	if (!rt) {
+		pol->xfrm_nr = 0;
+	} else {
+		nr = (rt->rta_len - sizeof(*rt)) / sizeof(*utmpl);
+
+		if (nr > XFRM_MAX_DEPTH)
+			return -EINVAL;
+
+		copy_templates(pol, RTA_DATA(rt), nr);
+	}
+	return 0;
+}
+
+static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p)
+{
+	xp->priority = p->priority;
+	xp->index = p->index;
+	memcpy(&xp->selector, &p->sel, sizeof(xp->selector));
+	memcpy(&xp->lft, &p->lft, sizeof(xp->lft));
+	xp->action = p->action;
+	xp->flags = p->flags;
+	xp->family = p->family;
+	/* XXX xp->share = p->share; */
+}
+
+static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
+{
+	memcpy(&p->sel, &xp->selector, sizeof(p->sel));
+	memcpy(&p->lft, &xp->lft, sizeof(p->lft));
+	memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
+	p->priority = xp->priority;
+	p->index = xp->index;
+	p->family = xp->family;
+	p->dir = dir;
+	p->action = xp->action;
+	p->flags = xp->flags;
+	p->share = XFRM_SHARE_ANY; /* XXX xp->share */
+}
+
+static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, struct rtattr **xfrma, int *errp)
+{
+	struct xfrm_policy *xp = xfrm_policy_alloc(GFP_KERNEL);
+	int err;
+
+	if (!xp) {
+		*errp = -ENOMEM;
+		return NULL;
+	}
+
+	copy_from_user_policy(xp, p);
+	err = copy_user_tmpl(xp, xfrma);
+	if (err) {
+		*errp = err;
+		kfree(xp);
+		xp = NULL;
+	}
+
+	return xp;
+}
+
+static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
+	struct xfrm_policy *xp;
+	int err;
+
+	err = verify_newpolicy_info(p);
+	if (err)
+		return err;
+
+	xp = xfrm_policy_construct(p, (struct rtattr **) xfrma, &err);
+	if (!xp)
+		return err;
+
+	err = xfrm_policy_insert(p->dir, xp, 1);
+	if (err) {
+		kfree(xp);
+		return err;
+	}
+
+	xfrm_pol_put(xp);
+
+	return 0;
+}
+
+static int xfrm_del_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_policy *xp;
+	struct xfrm_userpolicy_id *p;
+	int err;
+
+	p = NLMSG_DATA(nlh);
+
+	err = verify_policy_dir(p->dir);
+	if (err)
+		return err;
+
+	xp = xfrm_policy_delete(p->dir, &p->sel);
+	if (xp == NULL)
+		return -ENOENT;
+	xfrm_policy_kill(xp);
+	xfrm_pol_put(xp);
+	return 0;
+}
+
+static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
+{
+	struct xfrm_dump_info *sp = ptr;
+	struct xfrm_userpolicy_info *p;
+	struct sk_buff *in_skb = sp->in_skb;
+	struct sk_buff *skb = sp->out_skb;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+
+	if (sp->this_idx < sp->start_idx)
+		goto out;
+
+	nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid,
+			sp->nlmsg_seq,
+			XFRM_MSG_NEWPOLICY, sizeof(*p));
+	p = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	copy_to_user_policy(xp, p, dir);
+
+	if (xp->xfrm_nr) {
+		struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH];
+		int i;
+
+		for (i = 0; i < xp->xfrm_nr; i++) {
+			struct xfrm_user_tmpl *up = &vec[i];
+			struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
+
+			memcpy(&up->id, &kp->id, sizeof(up->id));
+			memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
+			up->reqid = kp->reqid;
+			up->mode = kp->mode;
+			up->share = kp->share;
+			up->optional = kp->optional;
+			up->aalgos = kp->aalgos;
+			up->ealgos = kp->ealgos;
+			up->calgos = kp->calgos;
+		}
+		RTA_PUT(skb, XFRMA_TMPL,
+			(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr),
+			vec);
+	}
+
+	nlh->nlmsg_len = skb->tail - b;
+out:
+	sp->this_idx++;
+	return 0;
+
+nlmsg_failure:
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct xfrm_dump_info info;
+
+	info.in_skb = cb->skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.start_idx = cb->args[0];
+	(void) xfrm_policy_walk(dump_one_policy, &info);
+	cb->args[0] = info.this_idx;
+
+	return skb->len;
+}
+
+static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
+					  struct xfrm_policy *xp,
+					  int dir, u32 seq)
+{
+	struct xfrm_dump_info info;
+	struct sk_buff *skb;
+
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+	info.in_skb = in_skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = seq;
+	info.this_idx = info.start_idx = 0;
+
+	if (dump_one_policy(xp, dir, 0, &info) < 0) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	return skb;
+}
+
+static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+	struct xfrm_policy *xp;
+	struct xfrm_userpolicy_id *p;
+	struct sk_buff *resp_skb;
+	int err;
+
+	p = NLMSG_DATA(nlh);
+	xp = xfrm_policy_byid(p->dir, p->index, 0);
+	if (xp == NULL)
+		return -ENOENT;
+
+	resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);
+	if (IS_ERR(resp_skb)) {
+		err = PTR_ERR(resp_skb);
+	} else {
+		err = netlink_unicast(xfrm_nl, resp_skb,
+				      NETLINK_CB(skb).pid, MSG_DONTWAIT);
+	}
+
+	xfrm_pol_put(xp);
+
+	return err;
+}
+
+static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
+	NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)),	/* NEW SA */
+	NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),	/* DEL SA */
+	NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),	/* GET SA */
+	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)),/* NEW POLICY */
+	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)),  /* DEL POLICY */
+	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)),  /* GET POLICY */
+	NLMSG_LENGTH(sizeof(struct xfrm_userspi_info)),	/* ALLOC SPI */
+	NLMSG_LENGTH(sizeof(struct xfrm_user_acquire)),	/* ACQUIRE */
+	NLMSG_LENGTH(sizeof(struct xfrm_user_expire)),	/* EXPIRE */
+};
+
+static struct xfrm_link {
+	int (*doit)(struct sk_buff *, struct nlmsghdr *, void **);
+	int (*dump)(struct sk_buff *, struct netlink_callback *);
+} xfrm_dispatch[] = {
+	{	.doit	=	xfrm_add_sa, 		},
+	{	.doit	=	xfrm_del_sa, 		},
+	{
+		.doit	=	xfrm_get_sa,
+		.dump	=	xfrm_dump_sa,
+	},
+	{	.doit	=	xfrm_add_policy 	},
+	{	.doit	=	xfrm_del_policy 	},
+	{
+		.doit	=	xfrm_get_policy,
+		.dump	=	xfrm_dump_policy,
+	},
+	{	.doit	=	xfrm_alloc_userspi	},
+};
+
+static int xfrm_done(struct netlink_callback *cb)
+{
+	return 0;
+}
+
+static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
+{
+	struct rtattr *xfrma[XFRMA_MAX];
+	struct xfrm_link *link;
+	int type, min_len, kind;
+
+	if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
+		return 0;
+
+	type = nlh->nlmsg_type;
+
+	/* A control message: ignore them */
+	if (type < XFRM_MSG_BASE)
+		return 0;
+
+	/* Unknown message: reply with EINVAL */
+	if (type > XFRM_MSG_MAX)
+		goto err_einval;
+
+	type -= XFRM_MSG_BASE;
+	kind = (type & 3);
+	link = &xfrm_dispatch[type];
+
+	/* All operations require privileges, even GET */
+	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
+		*errp = -EPERM;
+		return -1;
+	}
+
+	if (kind == 2 && (nlh->nlmsg_flags & NLM_F_DUMP)) {
+		u32 rlen;
+
+		if (link->dump == NULL)
+			goto err_einval;
+
+		if ((*errp = netlink_dump_start(xfrm_nl, skb, nlh,
+						link->dump,
+						xfrm_done)) != 0) {
+			return -1;
+		}
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > skb->len)
+			rlen = skb->len;
+		skb_pull(skb, rlen);
+		return -1;
+	}
+
+	memset(xfrma, 0, sizeof(xfrma));
+
+	if (nlh->nlmsg_len < (min_len = xfrm_msg_min[type]))
+		goto err_einval;
+
+	if (nlh->nlmsg_len > min_len) {
+		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
+		struct rtattr *attr = (void *) nlh + NLMSG_ALIGN(min_len);
+
+		while (RTA_OK(attr, attrlen)) {
+			unsigned short flavor = attr->rta_type;
+			if (flavor) {
+				if (flavor > XFRMA_MAX)
+					goto err_einval;
+				xfrma[flavor - 1] = attr;
+			}
+			attr = RTA_NEXT(attr, attrlen);
+		}
+	}
+
+	if (link->doit == NULL)
+		goto err_einval;
+	*errp = link->doit(skb, nlh, (void **) &xfrma);
+
+	return *errp;
+
+err_einval:
+	*errp = -EINVAL;
+	return -1;
+}
+
+static int xfrm_user_rcv_skb(struct sk_buff *skb)
+{
+	int err;
+	struct nlmsghdr *nlh;
+
+	while (skb->len >= NLMSG_SPACE(0)) {
+		u32 rlen;
+
+		nlh = (struct nlmsghdr *) skb->data;
+		if (nlh->nlmsg_len < sizeof(*nlh) ||
+		    skb->len < nlh->nlmsg_len)
+			return 0;
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > skb->len)
+			rlen = skb->len;
+		if (xfrm_user_rcv_msg(skb, nlh, &err)) {
+			if (err == 0)
+				return -1;
+			netlink_ack(skb, nlh, err);
+		} else if (nlh->nlmsg_flags & NLM_F_ACK)
+			netlink_ack(skb, nlh, 0);
+		skb_pull(skb, rlen);
+	}
+
+	return 0;
+}
+
+static void xfrm_netlink_rcv(struct sock *sk, int len)
+{
+	do {
+		struct sk_buff *skb;
+
+		down(&xfrm_cfg_sem);
+
+		while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
+			if (xfrm_user_rcv_skb(skb)) {
+				if (skb->len)
+					skb_queue_head(&sk->receive_queue, skb);
+				else
+					kfree_skb(skb);
+				break;
+			}
+			kfree_skb(skb);
+		}
+
+		up(&xfrm_cfg_sem);
+
+	} while (xfrm_nl && xfrm_nl->receive_queue.qlen);
+}
+
+static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard)
+{
+	struct xfrm_user_expire *ue;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_EXPIRE,
+			sizeof(*ue));
+	ue = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	copy_to_user_state(x, &ue->state);
+	ue->hard = (hard != 0) ? 1 : 0;
+
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_send_notify(struct xfrm_state *x, int hard)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (build_expire(skb, x, hard) < 0)
+		BUG();
+
+	NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
+	netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+
+	return 0;
+}
+
+/* XXX Make this xfrm_state.c:xfrm_get_acqseq() */
+static u32 get_acqseq(void)
+{
+	u32 res;
+	static u32 acqseq;
+	static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED;
+
+	spin_lock_bh(&acqseq_lock);
+	res = (++acqseq ? : ++acqseq);
+	spin_unlock_bh(&acqseq_lock);
+	return res;
+}
+
+static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
+			 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
+			 int dir)
+{
+	struct xfrm_user_acquire *ua;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+	__u32 seq = get_acqseq();
+
+	nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_ACQUIRE,
+			sizeof(*ua));
+	ua = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	memcpy(&ua->id, &x->id, sizeof(ua->id));
+	memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr));
+	copy_to_user_policy(xp, &ua->policy, dir);
+	ua->aalgos = xt->aalgos;
+	ua->ealgos = xt->ealgos;
+	ua->calgos = xt->calgos;
+	ua->seq = x->km.seq = seq;
+
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
+			     struct xfrm_policy *xp, int dir)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(sizeof(struct xfrm_user_acquire) + 16, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (build_acquire(skb, x, xt, xp, dir) < 0)
+		BUG();
+
+	NETLINK_CB(skb).dst_groups = XFRMGRP_ACQUIRE;
+	netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC);
+
+	return 0;
+}
+
+/* User gives us xfrm_user_policy_info followed by an array of 0
+ * or more templates.
+ */
+struct xfrm_policy *xfrm_compile_policy(int opt, u8 *data, int len, int *dir)
+{
+	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
+	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
+	struct xfrm_policy *xp;
+	int nr;
+
+	if (opt != IP_XFRM_POLICY) {
+		*dir = -EOPNOTSUPP;
+		return NULL;
+	}
+	*dir = -EINVAL;
+
+	if (len < sizeof(*p) ||
+	    verify_newpolicy_info(p))
+		return NULL;
+
+	nr = ((len - sizeof(*p)) / sizeof(*ut));
+	if (nr > XFRM_MAX_DEPTH)
+		return NULL;
+
+	xp = xfrm_policy_alloc(GFP_KERNEL);
+	if (xp == NULL) {
+		*dir = -ENOBUFS;
+		return NULL;
+	}
+
+	copy_from_user_policy(xp, p);
+	copy_templates(xp, ut, nr);
+
+	*dir = p->dir;
+
+	return xp;
+}
+
+static struct xfrm_mgr netlink_mgr = {
+	.id		= "netlink",
+	.notify		= xfrm_send_notify,
+	.acquire	= xfrm_send_acquire,
+	.compile_policy	= xfrm_compile_policy,
+};
+
+static int __init xfrm_user_init(void)
+{
+	printk(KERN_INFO "Initializing IPsec netlink socket\n");
+
+	xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
+	if (xfrm_nl == NULL)
+		panic("xfrm_user_init: cannot initialize xfrm_nl\n");
+
+
+	xfrm_register_km(&netlink_mgr);
+
+	return 0;
+}
+
+static void __exit xfrm_user_exit(void)
+{
+	xfrm_unregister_km(&netlink_mgr);
+	sock_release(xfrm_nl->socket);
+}
+
+module_init(xfrm_user_init);
+module_exit(xfrm_user_exit);
diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
--- a/net/ipv6/af_inet6.c	Sun Nov 17 20:30:14 2002
+++ b/net/ipv6/af_inet6.c	Sun Nov 17 20:30:14 2002
@@ -538,6 +538,7 @@
 };
 
 #ifdef MODULE
+#if 0 /* FIXME --RR */
 int ipv6_unload(void)
 {
 	if (!unloadable) return 1;
@@ -545,6 +546,7 @@
 	return atomic_read(&(__this_module.uc.usecount)) - 3;
 }
 #endif
+#endif
 
 #if defined(MODULE) && defined(CONFIG_SYSCTL)
 extern void ipv6_sysctl_register(void);
@@ -624,10 +626,12 @@
 	int err;
 
 #ifdef MODULE
+#if 0 /* FIXME --RR */
 	if (!mod_member_present(&__this_module, can_unload))
 	  return -EINVAL;
 
 	__this_module.can_unload = &ipv6_unload;
+#endif
 #endif
 
 	printk(KERN_INFO "IPv6 v0.8 for NET4.0\n");
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	Sun Nov 17 20:30:15 2002
+++ b/net/ipv6/mcast.c	Sun Nov 17 20:30:15 2002
@@ -296,6 +296,7 @@
 	}
 
 	memset(mc, 0, sizeof(struct ifmcaddr6));
+	init_timer(&mc->mca_timer);
 	mc->mca_timer.function = igmp6_timer_handler;
 	mc->mca_timer.data = (unsigned long) mc;
 
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	Sun Nov 17 20:30:12 2002
+++ b/net/irda/af_irda.c	Sun Nov 17 20:30:12 2002
@@ -2364,6 +2364,7 @@
 
 			/* Set watchdog timer to expire in <val> ms. */
 			self->errno = 0;
+			init_timer(&self->watchdog);
 			self->watchdog.function = irda_discovery_timeout;
 			self->watchdog.data = (unsigned long) self;
 			self->watchdog.expires = jiffies + (val * HZ/1000);
diff -Nru a/net/key/af_key.c b/net/key/af_key.c
--- a/net/key/af_key.c	Sun Nov 17 20:30:12 2002
+++ b/net/key/af_key.c	Sun Nov 17 20:30:12 2002
@@ -30,6 +30,7 @@
 #define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
 #define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
 
+
 /* List of all pfkey sockets. */
 static struct sock * pfkey_table;
 static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
@@ -527,8 +528,7 @@
 
 	switch (((struct sockaddr *)(addr + 1))->sa_family) {
 	case AF_INET:
-		x = xfrm_state_lookup(
-				      ((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
+		x = xfrm_state_lookup(((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
 				      sa->sadb_sa_spi, proto);
 		break;
 	case AF_INET6:
@@ -871,10 +871,6 @@
 	    !!ext_hdrs[SADB_EXT_LIFETIME_SOFT-1])
 		return ERR_PTR(-EINVAL);
 
-	/* XXX Do we need this check ? */
-	if (((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1])->sadb_address_prefixlen != 32 ||
-	    ((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1])->sadb_address_prefixlen != 32)
-		return ERR_PTR(-EINVAL);
 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
 	if (proto == 0)
 		return ERR_PTR(-EINVAL);
@@ -1046,7 +1042,7 @@
 	daddr = (struct sockaddr_in*)(addr + 1);
 
 	x = xfrm_find_acq(mode, reqid, proto, daddr->sin_addr.s_addr,
-			  saddr->sin_addr.s_addr);
+			  saddr->sin_addr.s_addr, 1);
 	if (x == NULL)
 		return -ENOENT;
 
@@ -1125,7 +1121,17 @@
 
 	/* XXX there is race condition */
 	x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
-	if (x1 && hdr->sadb_msg_type == SADB_ADD) {
+	if (!x1) {
+		x1 = xfrm_find_acq(x->props.mode, x->props.reqid, x->id.proto,
+				   x->id.daddr.xfrm4_addr,
+				   x->props.saddr.xfrm4_addr, 0);
+		if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
+			xfrm_state_put(x1);
+			x1 = NULL;
+		}
+	}
+
+	if (x1 && x1->id.spi && hdr->sadb_msg_type == SADB_ADD) {
 		x->km.state = XFRM_STATE_DEAD;
 		xfrm_state_put(x);
 		xfrm_state_put(x1);
@@ -1134,7 +1140,7 @@
 
 	xfrm_state_insert(x);
 
-	if (x1 && hdr->sadb_msg_type != SADB_ADD) {
+	if (x1) {
 		xfrm_state_delete(x1);
 		xfrm_state_put(x1);
 	}
@@ -1228,7 +1234,7 @@
 		esp_len += sizeof(struct sadb_supported);
 	len = esp_len + ah_len + sizeof(struct sadb_msg);
 
-	skb = alloc_skb(allocation, len + 16);
+	skb = alloc_skb(len + 16, allocation);
 	if (!skb)
 		goto out_put_algs;
 
@@ -1379,6 +1385,34 @@
 	return 0;
 }
 
+static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
+{
+	int i;
+	u16 reqid = *(u16*)ptr;
+
+	for (i=0; i<xp->xfrm_nr; i++) {
+		if (xp->xfrm_vec[i].reqid == reqid)
+			return -EEXIST;
+	}
+	return 0;
+}
+
+static u16 gen_reqid(void)
+{
+	u16 start;
+	static u16 reqid = IPSEC_MANUAL_REQID_MAX;
+
+	start = reqid;
+	do {
+		++reqid;
+		if (reqid == 0)
+			reqid = IPSEC_MANUAL_REQID_MAX+1;
+		if (xfrm_policy_walk(check_reqid, (void*)&reqid) != -EEXIST)
+			return reqid;
+	} while (reqid != start);
+	return 0;
+}
+
 static int
 parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
 {
@@ -1395,7 +1429,14 @@
 	t->mode = rq->sadb_x_ipsecrequest_mode-1;
 	if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
 		t->optional = 1;
-	t->reqid = rq->sadb_x_ipsecrequest_reqid;
+	else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
+		t->reqid = rq->sadb_x_ipsecrequest_reqid;
+		if (t->reqid > IPSEC_MANUAL_REQID_MAX)
+			t->reqid = 0;
+		if (!t->reqid && !(t->reqid = gen_reqid()))
+			return -ENOBUFS;
+	}
+
 	/* addresses present only in tunnel mode */
 	if (t->mode) {
 		addr = (void*)(rq+1);
@@ -1544,6 +1585,8 @@
 		rq->sadb_x_ipsecrequest_proto = t->id.proto;
 		rq->sadb_x_ipsecrequest_mode = t->mode+1;
 		rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
+		if (t->reqid)
+			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
 		if (t->optional)
 			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
 		rq->sadb_x_ipsecrequest_reqid = t->reqid;
@@ -1590,7 +1633,6 @@
 	if (xp == NULL)
 		return -ENOBUFS;
 
-	xp->index = pol->sadb_x_policy_id;
 	xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?
 		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
 
@@ -2013,6 +2055,18 @@
 	return 0;
 }
 
+static u32 get_acqseq(void)
+{
+	u32 res;
+	static u32 acqseq;
+	static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED;
+
+	spin_lock_bh(&acqseq_lock);
+	res = (++acqseq ? : ++acqseq);
+	spin_unlock_bh(&acqseq_lock);
+	return res;
+}
+
 static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp, int dir)
 {
 	struct sk_buff *skb;
@@ -2020,7 +2074,6 @@
 	struct sadb_address *addr;
 	struct sadb_x_policy *pol;
 	int size;
-	static u32 acqseq;
 	
 	size = sizeof(struct sadb_msg) +
 		sizeof(struct sadb_address)*2 + 
@@ -2043,10 +2096,9 @@
 	hdr->sadb_msg_len = size / sizeof(uint64_t);
 	hdr->sadb_msg_errno = 0;
 	hdr->sadb_msg_reserved = 0;
-	hdr->sadb_msg_seq = (++acqseq ? : ++acqseq);
-	x->km.seq = acqseq;
+	hdr->sadb_msg_seq = x->km.seq = get_acqseq();
 	hdr->sadb_msg_pid = 0;
-	
+
 	/* src address */
 	addr = (struct sadb_address*) skb_put(skb, 
 					      sizeof(struct sadb_address)+sizeof(struct sockaddr_in));
@@ -2076,7 +2128,7 @@
 	((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr = 
 		x->id.daddr.xfrm4_addr;
 	((struct sockaddr_in*)(addr + 1))->sin_port = 0;
-	
+
 	pol = (struct sadb_x_policy *)  skb_put(skb, sizeof(struct sadb_x_policy));
 	pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);
 	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
@@ -2113,13 +2165,12 @@
 	    (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
 		return NULL;
 
-	xp = xfrm_policy_alloc(GFP_KERNEL);
+	xp = xfrm_policy_alloc(GFP_ATOMIC);
 	if (xp == NULL) {
 		*dir = -ENOBUFS;
 		return NULL;
 	}
 
-	xp->index = pol->sadb_x_policy_id;
 	xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?
 		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
 
@@ -2171,7 +2222,9 @@
 	if (!hdr)
 		goto out;
 
+	down(&xfrm_cfg_sem);
 	err = pfkey_process(sk, skb, hdr);
+	up(&xfrm_cfg_sem);
 
 out:
 	if (err && hdr && pfkey_error(hdr, err, sk) == 0)
@@ -2179,7 +2232,7 @@
 	if (skb)
 		kfree_skb(skb);
 
-	return err;
+	return err ? : len;
 }
 
 static int pfkey_recvmsg(struct kiocb *kiocb,
diff -Nru a/net/llc/llc_main.c b/net/llc/llc_main.c
--- a/net/llc/llc_main.c	Sun Nov 17 20:30:13 2002
+++ b/net/llc/llc_main.c	Sun Nov 17 20:30:13 2002
@@ -181,18 +181,22 @@
 	llc->inc_cntr = llc->dec_cntr = 2;
 	llc->dec_step = llc->connect_step = 1;
 
+	init_timer(&llc->ack_timer);
 	llc->ack_timer.expire	      = LLC_ACK_TIME;
 	llc->ack_timer.timer.data     = (unsigned long)sk;
 	llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
 
+	init_timer(&llc->pf_cycle_timer);
 	llc->pf_cycle_timer.expire	   = LLC_P_TIME;
 	llc->pf_cycle_timer.timer.data     = (unsigned long)sk;
 	llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
 
+	init_timer(&llc->rej_sent_timer);
 	llc->rej_sent_timer.expire	   = LLC_REJ_TIME;
 	llc->rej_sent_timer.timer.data     = (unsigned long)sk;
 	llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
 
+	init_timer(&llc->busy_state_timer);
 	llc->busy_state_timer.expire	     = LLC_BUSY_TIME;
 	llc->busy_state_timer.timer.data     = (unsigned long)sk;
 	llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
@@ -552,6 +556,7 @@
 	skb_queue_head_init(&llc_main_station.mac_pdu_q);
 	skb_queue_head_init(&llc_main_station.ev_q.list);
 	spin_lock_init(&llc_main_station.ev_q.lock);
+	init_timer(&llc_main_station.ack_timer);
 	llc_main_station.ack_timer.data     = (unsigned long)&llc_main_station;
 	llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
 
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Sun Nov 17 20:30:13 2002
+++ b/net/netsyms.c	Sun Nov 17 20:30:13 2002
@@ -283,6 +283,7 @@
 EXPORT_SYMBOL(dlci_ioctl_hook);
 #endif
 
+EXPORT_SYMBOL(xfrm_cfg_sem);
 EXPORT_SYMBOL(xfrm_policy_alloc);
 EXPORT_SYMBOL(__xfrm_policy_destroy);
 EXPORT_SYMBOL(xfrm_policy_lookup);
diff -Nru a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
--- a/net/sched/sch_sfq.c	Sun Nov 17 20:30:15 2002
+++ b/net/sched/sch_sfq.c	Sun Nov 17 20:30:15 2002
@@ -411,9 +411,9 @@
 	struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data;
 	int i;
 
+	init_timer(&q->perturb_timer);
 	q->perturb_timer.data = (unsigned long)sch;
 	q->perturb_timer.function = sfq_perturbation;
-	init_timer(&q->perturb_timer);
 
 	for (i=0; i<SFQ_HASH_DIVISOR; i++)
 		q->ht[i] = SFQ_DEPTH;
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Sun Nov 17 20:30:12 2002
+++ b/net/socket.c	Sun Nov 17 20:30:12 2002
@@ -66,6 +66,7 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wanrouter.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
@@ -76,6 +77,7 @@
 #include <linux/highmem.h>
 #include <linux/wireless.h>
 #include <linux/divert.h>
+#include <linux/mount.h>
 
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 #include <linux/kmod.h>
@@ -1839,29 +1841,19 @@
 #endif
 }
 
-int socket_get_info(char *buffer, char **start, off_t offset, int length)
+#ifdef CONFIG_PROC_FS
+void socket_seq_show(struct seq_file *seq)
 {
-	int len, cpu;
+	int cpu;
 	int counter = 0;
 
-	for (cpu=0; cpu<NR_CPUS; cpu++)
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		counter += sockets_in_use[cpu].counter;
 
 	/* It can be negative, by the way. 8) */
 	if (counter < 0)
 		counter = 0;
 
-	len = sprintf(buffer, "sockets: used %d\n", counter);
-	if (offset >= len)
-	{
-		*start = buffer;
-		return 0;
-	}
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0;
-	return len;
+	seq_printf(seq, "sockets: used %d\n", counter);
 }
+#endif /* CONFIG_PROC_FS */
diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c
--- a/net/sunrpc/cache.c	Sun Nov 17 20:30:14 2002
+++ b/net/sunrpc/cache.c	Sun Nov 17 20:30:14 2002
@@ -23,6 +23,7 @@
 #include <asm/uaccess.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
+#include <linux/net.h>
 #include <asm/ioctls.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
@@ -32,7 +33,7 @@
 
 void cache_init(struct cache_head *h)
 {
-	time_t now = CURRENT_TIME;
+	time_t now = get_seconds();
 	h->next = NULL;
 	h->flags = 0;
 	atomic_set(&h->refcnt, 0);
@@ -61,7 +62,7 @@
 
 	/* First decide return status as best we can */
 	if (!test_bit(CACHE_VALID, &h->flags) ||
-	    h->expiry_time < CURRENT_TIME)
+	    h->expiry_time < get_seconds())
 		rv = -EAGAIN;
 	else if (detail->flush_time > h->last_refresh)
 		rv = -EAGAIN;
@@ -74,7 +75,7 @@
 
 	/* now see if we want to start an upcall */
 	refresh_age = (h->expiry_time - h->last_refresh);
-	age = CURRENT_TIME - h->last_refresh;
+	age = get_seconds() - h->last_refresh;
 
 	if (rqstp == NULL) {
 		if (rv == -EAGAIN)
@@ -87,7 +88,7 @@
 				clear_bit(CACHE_PENDING, &h->flags);
 				if (rv == -EAGAIN) {
 					set_bit(CACHE_NEGATIVE, &h->flags);
-					cache_fresh(detail, h, CURRENT_TIME+CACHE_NEW_EXPIRY);
+					cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY);
 					rv = -ENOENT;
 				}
 				break;
@@ -115,7 +116,7 @@
 {
 
 	head->expiry_time = expiry;
-	head->last_refresh = CURRENT_TIME;
+	head->last_refresh = get_seconds();
 	if (!test_and_set_bit(CACHE_VALID, &head->flags))
 		cache_revisit_request(head);
 	if (test_and_clear_bit(CACHE_PENDING, &head->flags))
@@ -182,7 +183,7 @@
 	cd->nextcheck = 0;
 	cd->entries = 0;
 	atomic_set(&cd->readers, 0);
-	cd->last_close = CURRENT_TIME;
+	cd->last_close = get_seconds();
 	list_add(&cd->others, &cache_list);
 	spin_unlock(&cache_list_lock);
 }
@@ -261,11 +262,11 @@
 			return -1;
 		}
 		current_detail = list_entry(next, struct cache_detail, others);
-		if (current_detail->nextcheck > CURRENT_TIME)
+		if (current_detail->nextcheck > get_seconds())
 			current_index = current_detail->hash_size;
 		else {
 			current_index = 0;
-			current_detail->nextcheck = CURRENT_TIME+30*60;
+			current_detail->nextcheck = get_seconds()+30*60;
 		}
 	}
 
@@ -289,7 +290,7 @@
 		for (; ch; cp= & ch->next, ch= *cp) {
 			if (atomic_read(&ch->refcnt))
 				continue;
-			if (ch->expiry_time < CURRENT_TIME
+			if (ch->expiry_time < get_seconds()
 			    || ch->last_refresh < current_detail->flush_time
 				)
 				break;
@@ -330,8 +331,8 @@
 
 void cache_purge(struct cache_detail *detail)
 {
-	detail->flush_time = CURRENT_TIME+1;
-	detail->nextcheck = CURRENT_TIME;
+	detail->flush_time = get_seconds()+1;
+	detail->nextcheck = get_seconds();
 	cache_flush();
 }
 
@@ -372,7 +373,7 @@
 		return;
 
 	dreq->item = item;
-	dreq->recv_time = CURRENT_TIME;
+	dreq->recv_time = get_seconds();
 
 	spin_lock(&cache_defer_lock);
 
@@ -702,7 +703,7 @@
 	filp->private_data = NULL;
 	kfree(rp);
 
-	cd->last_close = CURRENT_TIME;
+	cd->last_close = get_seconds();
 	atomic_dec(&cd->readers);
 	return 0;
 }
@@ -831,7 +832,7 @@
 		return -EINVAL;
 
 	if (atomic_read(&detail->readers) == 0 &&
-	    detail->last_close < CURRENT_TIME - 60)
+	    detail->last_close < get_seconds() - 60)
 		/* nobody is listening */
 		return -EINVAL;
 
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Sun Nov 17 20:30:13 2002
+++ b/net/sunrpc/clnt.c	Sun Nov 17 20:30:13 2002
@@ -379,20 +379,12 @@
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 
-	if (task->tk_msg.rpc_proc > clnt->cl_maxproc) {
-		printk(KERN_ERR "%s (vers %d): bad procedure number %d\n",
-				clnt->cl_protname, clnt->cl_vers,
-				task->tk_msg.rpc_proc);
-		rpc_exit(task, -EIO);
-		return;
-	}
-
 	dprintk("RPC: %4d call_start %s%d proc %d (%s)\n", task->tk_pid,
-		clnt->cl_protname, clnt->cl_vers, task->tk_msg.rpc_proc,
+		clnt->cl_protname, clnt->cl_vers, task->tk_msg.rpc_proc->p_proc,
 		(RPC_IS_ASYNC(task) ? "async" : "sync"));
 
 	/* Increment call count */
-	rpcproc_count(clnt, task->tk_msg.rpc_proc)++;
+	task->tk_msg.rpc_proc->p_count++;
 	clnt->cl_stats->rpccnt++;
 	task->tk_action = call_reserve;
 }
@@ -474,7 +466,6 @@
 static void
 call_allocate(struct rpc_task *task)
 {
-	struct rpc_clnt	*clnt = task->tk_client;
 	unsigned int	bufsiz;
 
 	dprintk("RPC: %4d call_allocate (status %d)\n", 
@@ -485,7 +476,7 @@
 
 	/* FIXME: compute buffer requirements more exactly using
 	 * auth->au_wslack */
-	bufsiz = rpcproc_bufsiz(clnt, task->tk_msg.rpc_proc) + RPC_SLACK_SPACE;
+	bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE;
 
 	if (rpc_malloc(task, bufsiz << 1) != NULL)
 		return;
@@ -538,7 +529,7 @@
 	memset(task->tk_buffer, 0, bufsiz);
 
 	/* Encode header and provided arguments */
-	encode = rpcproc_encode(clnt, task->tk_msg.rpc_proc);
+	encode = task->tk_msg.rpc_proc->p_encode;
 	if (!(p = call_header(task))) {
 		printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
 		rpc_exit(task, -EIO);
@@ -620,8 +611,6 @@
 static void
 call_transmit(struct rpc_task *task)
 {
-	struct rpc_clnt	*clnt = task->tk_client;
-
 	dprintk("RPC: %4d call_transmit (status %d)\n", 
 				task->tk_pid, task->tk_status);
 
@@ -629,7 +618,7 @@
 	if (task->tk_status < 0)
 		return;
 	xprt_transmit(task);
-	if (!rpcproc_decode(clnt, task->tk_msg.rpc_proc) && task->tk_status >= 0) {
+	if (!task->tk_msg.rpc_proc->p_decode && task->tk_status >= 0) {
 		task->tk_action = NULL;
 		rpc_wake_up_task(task);
 	}
@@ -732,7 +721,7 @@
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
-	kxdrproc_t	decode = rpcproc_decode(clnt, task->tk_msg.rpc_proc);
+	kxdrproc_t	decode = task->tk_msg.rpc_proc->p_decode;
 	u32		*p;
 
 	dprintk("RPC: %4d call_decode (status %d)\n", 
@@ -832,7 +821,7 @@
 	*p++ = htonl(RPC_VERSION);	/* RPC version */
 	*p++ = htonl(clnt->cl_prog);	/* program number */
 	*p++ = htonl(clnt->cl_vers);	/* program version */
-	*p++ = htonl(task->tk_msg.rpc_proc);	/* procedure */
+	*p++ = htonl(task->tk_msg.rpc_proc->p_proc);	/* procedure */
 	return rpcauth_marshcred(task, p);
 }
 
diff -Nru a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
--- a/net/sunrpc/pmap_clnt.c	Sun Nov 17 20:30:14 2002
+++ b/net/sunrpc/pmap_clnt.c	Sun Nov 17 20:30:14 2002
@@ -28,6 +28,7 @@
 #define PMAP_UNSET		2
 #define PMAP_GETPORT		3
 
+static struct rpc_procinfo	pmap_procedures[];
 static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
 static void			pmap_getport_done(struct rpc_task *);
 extern struct rpc_program	pmap_program;
@@ -43,7 +44,7 @@
 	struct rpc_portmap *map = &clnt->cl_pmap;
 	struct sockaddr_in *sap = &clnt->cl_xprt->addr;
 	struct rpc_message msg = {
-		.rpc_proc	= PMAP_GETPORT,
+		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
 		.rpc_argp	= map,
 		.rpc_resp	= &clnt->cl_port,
 		.rpc_cred	= NULL
@@ -219,12 +220,6 @@
  * XDR encode/decode functions for PMAP
  */
 static int
-xdr_error(struct rpc_rqst *req, u32 *p, void *dummy)
-{
-	return -EIO;
-}
-
-static int
 xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map)
 {
 	dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n",
@@ -252,26 +247,23 @@
 	return 0;
 }
 
-static struct rpc_procinfo	pmap_procedures[4] = {
-	{ .p_procname		= "pmap_null",
-	  .p_encode		= (kxdrproc_t) xdr_error,	
-	  .p_decode		= (kxdrproc_t) xdr_error,
-	  .p_bufsiz		= 0,
-	  .p_count		= 0,
-	},
-	{ .p_procname		= "pmap_set",
+static struct rpc_procinfo	pmap_procedures[] = {
+[PMAP_SET] = {
+	  .p_proc		= PMAP_SET,
 	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
 	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
 	  .p_bufsiz		= 4,
 	  .p_count		= 1,
 	},
-	{ .p_procname		= "pmap_unset",
+[PMAP_UNSET] = {
+	  .p_proc		= PMAP_UNSET,
 	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
 	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
 	  .p_bufsiz		= 4,
 	  .p_count		= 1,
 	},
-	{ .p_procname		= "pmap_get",
+[PMAP_GETPORT] = {
+	  .p_proc		= PMAP_GETPORT,
 	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
 	  .p_decode		= (kxdrproc_t) xdr_decode_port,
 	  .p_bufsiz		= 4,
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	Sun Nov 17 20:30:14 2002
+++ b/net/sunrpc/sched.c	Sun Nov 17 20:30:14 2002
@@ -1123,7 +1123,8 @@
 		"-rpcwait -action- --exit--\n");
 	alltask_for_each(t, le, &all_tasks)
 		printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n",
-			t->tk_pid, t->tk_msg.rpc_proc, t->tk_flags, t->tk_status,
+			t->tk_pid, t->tk_msg.rpc_proc->p_proc,
+			t->tk_flags, t->tk_status,
 			t->tk_client, t->tk_client->cl_prog,
 			t->tk_rqstp, t->tk_timeout,
 			t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " <NULL> ",
diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
--- a/net/sunrpc/svcsock.c	Sun Nov 17 20:30:03 2002
+++ b/net/sunrpc/svcsock.c	Sun Nov 17 20:30:03 2002
@@ -1109,7 +1109,7 @@
 		 * 6 minutes
 		 *   http://www.connectathon.org/talks96/nfstcp.pdf 
 		 */
-		if (CURRENT_TIME - svsk->sk_lastrecv < 6*60
+		if (get_seconds() - svsk->sk_lastrecv < 6*60
 		    || test_bit(SK_BUSY, &svsk->sk_flags))
 			svsk = NULL;
 	}
@@ -1159,7 +1159,7 @@
 		svc_sock_release(rqstp);
 		return -EAGAIN;
 	}
-	svsk->sk_lastrecv = CURRENT_TIME;
+	svsk->sk_lastrecv = get_seconds();
 	if (test_bit(SK_TEMP, &svsk->sk_flags)) {
 		/* push active sockets to end of list */
 		spin_lock_bh(&serv->sv_lock);
@@ -1246,7 +1246,7 @@
 	svsk->sk_odata = inet->data_ready;
 	svsk->sk_owspace = inet->write_space;
 	svsk->sk_server = serv;
-	svsk->sk_lastrecv = CURRENT_TIME;
+	svsk->sk_lastrecv = get_seconds();
 	INIT_LIST_HEAD(&svsk->sk_deferred);
 	sema_init(&svsk->sk_sem, 1);
 
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Sun Nov 17 20:30:14 2002
+++ b/net/sunrpc/xprt.c	Sun Nov 17 20:30:14 2002
@@ -585,7 +585,7 @@
 		__xprt_put_cong(xprt, req);
 	       	if (!req->rq_nresend) {
 			unsigned timer =
-				rpcproc_timer(clnt, task->tk_msg.rpc_proc);
+				task->tk_msg.rpc_proc->p_timer;
 			if (timer)
 				rpc_update_rtt(&clnt->cl_rtt, timer,
 						(long)jiffies - req->rq_xtime);
@@ -1223,7 +1223,7 @@
 	/* Set the task's receive timeout value */
 	if (!xprt->nocong) {
 		task->tk_timeout = rpc_calc_rto(&clnt->cl_rtt,
-				rpcproc_timer(clnt, task->tk_msg.rpc_proc));
+				task->tk_msg.rpc_proc->p_timer);
 		req->rq_ntimeo = 0;
 		if (task->tk_timeout > req->rq_timeout.to_maxval)
 			task->tk_timeout = req->rq_timeout.to_maxval;
@@ -1284,7 +1284,7 @@
 	static u32	xid = 0;
 
 	if (!xid)
-		xid = CURRENT_TIME << 12;
+		xid = get_seconds() << 12;
 
 	dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, req, xid);
 	req->rq_timeout = xprt->timeout;
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Sun Nov 17 20:30:14 2002
+++ b/net/unix/af_unix.c	Sun Nov 17 20:30:14 2002
@@ -79,6 +79,8 @@
  *		  with BSD names.
  */
 
+#undef unix	/* KBUILD_MODNAME */
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -110,6 +112,7 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/rtnetlink.h>
+#include <linux/mount.h>
 #include <net/checksum.h>
 
 int sysctl_unix_max_dgram_qlen = 10;
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	Sun Nov 17 20:30:15 2002
+++ b/scripts/Makefile.build	Sun Nov 17 20:30:15 2002
@@ -53,34 +53,50 @@
 
 # Default is built-in, unless we know otherwise
 modkern_cflags := $(CFLAGS_KERNEL)
+quiet_modtag := $(empty)   $(empty)
 
 $(real-objs-m)        : modkern_cflags := $(CFLAGS_MODULE)
 $(real-objs-m:.o=.i)  : modkern_cflags := $(CFLAGS_MODULE)
+$(real-objs-m:.o=.s)  : modkern_cflags := $(CFLAGS_MODULE)
 $(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
 
+$(real-objs-m)        : quiet_modtag := [M]
+$(real-objs-m:.o=.i)  : quiet_modtag := [M]
+$(real-objs-m:.o=.s)  : quiet_modtag := [M]
+$(real-objs-m:.o=.lst): quiet_modtag := [M]
+
+$(obj-m)              : quiet_modtag := [M]
+
 $(export-objs)        : export_flags   := $(EXPORT_FLAGS)
 $(export-objs:.o=.i)  : export_flags   := $(EXPORT_FLAGS)
 $(export-objs:.o=.s)  : export_flags   := $(EXPORT_FLAGS)
 $(export-objs:.o=.lst): export_flags   := $(EXPORT_FLAGS)
 
-c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
-	  $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
-	  -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
-	  $(export_flags) 
+# Default for not multi-part modules
+modname = $(*F)
+
+$(multi-objs-m)         : modname = $(modname-multi)
+$(multi-objs-m:.o=.i)   : modname = $(modname-multi)
+$(multi-objs-m:.o=.s)   : modname = $(modname-multi)
+$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
+$(multi-objs-y)         : modname = $(modname-multi)
+$(multi-objs-y:.o=.i)   : modname = $(modname-multi)
+$(multi-objs-y:.o=.s)   : modname = $(modname-multi)
+$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
 
-quiet_cmd_cc_s_c = CC      $@
+quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@
 cmd_cc_s_c       = $(CC) $(c_flags) -S -o $@ $< 
 
 %.s: %.c FORCE
 	$(call if_changed_dep,cc_s_c)
 
-quiet_cmd_cc_i_c = CPP     $@
+quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
 cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
 
 %.i: %.c FORCE
 	$(call if_changed_dep,cc_i_c)
 
-quiet_cmd_cc_o_c = CC      $@
+quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
 cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
 
 %.o: %.c FORCE
@@ -103,13 +119,13 @@
 a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS) \
 	  $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
 
-quiet_cmd_as_s_S = CPP     $@
+quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
 cmd_as_s_S       = $(CPP) $(a_flags)   -o $@ $< 
 
 %.s: %.S FORCE
 	$(call if_changed_dep,as_s_S)
 
-quiet_cmd_as_o_S = AS      $@
+quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
 cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 
 %.o: %.S FORCE
@@ -156,7 +172,7 @@
 # Rule to link composite objects
 #
 
-quiet_cmd_link_multi = LD      $@
+quiet_cmd_link_multi = LD $(quiet_modtag)  $@
 cmd_link_multi = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^)
 
 # We would rather have a list of rules like
diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	Sun Nov 17 20:30:14 2002
+++ b/scripts/Makefile.lib	Sun Nov 17 20:30:14 2002
@@ -5,6 +5,8 @@
 # Standard vars
 
 comma   := ,
+empty   :=
+space   := $(empty) $(empty)
 
 # Figure out what we need to build from the various variables
 # ===========================================================================
@@ -40,11 +42,13 @@
 # if $(foo-objs) exists, foo.o is a composite object 
 multi-used-y := $(sort $(foreach m,$(__obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
 multi-used-m := $(sort $(foreach m,$(__obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
+multi-used   := $(multi-used-y) $(multi-used-m)
 
 # Build list of the parts of our composite objects, our composite
 # objects depend on those (obviously)
 multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
 multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
+multi-objs   := $(multi-objs-y) $(multi-objs-m)
 
 # $(subdir-obj-y) is the list of objects in $(obj-y) which do not live
 # in the local directory
@@ -111,6 +115,23 @@
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
 depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
+
+# These flags are needed for modversions and compiling, so we define them here
+# already
+# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will 
+# end up in (or would, if it gets compiled in)
+# Note: It's possible that one object gets potentially linked into more
+#       than one module. In that case KBUILD_MODNAME will be set to foo_bar,
+#       where foo and bar are the name of the modules.
+basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
+modname_flags  = -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname)))
+c_flags        = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
+	         $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
+	         $(basename_flags) $(modname_flags) $(export_flags) 
+
+# Finds the multi-part object the current object will be linked into
+modname-multi = $(subst $(space),_,$(strip $(foreach m,$(multi-used),\
+		$(if $(filter $(*F).o,$($(m:.o=-objs))),$(m:.o=)))))
 
 # Shipped files
 # ===========================================================================
diff -Nru a/scripts/Makefile.modinst b/scripts/Makefile.modinst
--- a/scripts/Makefile.modinst	Sun Nov 17 20:30:14 2002
+++ b/scripts/Makefile.modinst	Sun Nov 17 20:30:14 2002
@@ -16,8 +16,8 @@
 # ==========================================================================
 
 quiet_cmd_modules_install = INSTALL $(obj-m)
-      cmd_modules_install = mkdir -p $(MODLIB)/kernel/$(obj); \
-			    cp $(obj-m) $(MODLIB)/kernel/$(obj)
+      cmd_modules_install = mkdir -p $(MODLIB)/kernel && \
+		      cp $(obj-m) $(MODLIB)/kernel/
 
 modules_install: $(subdir-ym)
 ifneq ($(obj-m),)
diff -Nru a/scripts/Makefile.modver b/scripts/Makefile.modver
--- a/scripts/Makefile.modver	Sun Nov 17 20:30:13 2002
+++ b/scripts/Makefile.modver	Sun Nov 17 20:30:13 2002
@@ -48,11 +48,10 @@
 $(addprefix $(MODVERDIR)/,$(real-objs-y:.o=.ver)): modkern_cflags := $(CFLAGS_KERNEL)
 $(addprefix $(MODVERDIR)/,$(real-objs-m:.o=.ver)): modkern_cflags := $(CFLAGS_MODULE)
 $(addprefix $(MODVERDIR)/,$(export-objs:.o=.ver)): export_flags   := -D__GENKSYMS__
+# Default for not multi-part modules
+modname = $(*F)
 
-c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
-	  $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
-	  -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
-	  $(export_flags) 
+$(addprefix $(MODVERDIR)/,$(multi-objs:.o=.ver)) : modname = $(modname-multi)
 
 # Our objects only depend on modversions.h, not on the individual .ver
 # files (fix-dep filters them), so touch modversions.h if any of the .ver
diff -Nru a/sound/core/info.c b/sound/core/info.c
--- a/sound/core/info.c	Sun Nov 17 20:30:15 2002
+++ b/sound/core/info.c	Sun Nov 17 20:30:15 2002
@@ -29,9 +29,7 @@
 #include <sound/info.h>
 #include <sound/version.h>
 #include <linux/proc_fs.h>
-#ifdef CONFIG_DEVFS_FS
 #include <linux/devfs_fs_kernel.h>
-#endif
 #include <stdarg.h>
 
 /*
@@ -965,20 +963,12 @@
 
 void snd_info_free_device(snd_info_entry_t * entry)
 {
-#ifdef CONFIG_DEVFS_FS
-	char dname[32];
-#endif
-
 	snd_runtime_check(entry, return);
 	down(&info_mutex);
 	snd_remove_proc_entry(snd_proc_dev, entry->p);
 	up(&info_mutex);
-#ifdef CONFIG_DEVFS_FS
-	if (entry->p && strncmp(entry->name, "controlC", 8)) {
-		sprintf(dname, "snd/%s", entry->name);
-		devfs_find_and_unregister(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0);
-	}
-#endif
+	if (entry->p && strncmp(entry->name, "controlC", 8))
+		devfs_remove("snd/%s", entry->name);
 	snd_info_free_entry(entry);
 }
 
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	Sun Nov 17 20:30:12 2002
+++ b/sound/core/pcm_native.c	Sun Nov 17 20:30:12 2002
@@ -24,6 +24,7 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/uio.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/info.h>
diff -Nru a/sound/core/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	Sun Nov 17 20:30:14 2002
+++ b/sound/core/sound.c	Sun Nov 17 20:30:14 2002
@@ -30,9 +30,7 @@
 #include <sound/control.h>
 #include <sound/initval.h>
 #include <linux/kmod.h>
-#ifdef CONFIG_DEVFS_FS
 #include <linux/devfs_fs_kernel.h>
-#endif
 
 #define SNDRV_OS_MINORS 256
 
@@ -351,16 +349,11 @@
 
 static void __exit alsa_sound_exit(void)
 {
-#ifdef CONFIG_DEVFS_FS
-	char controlname[24];
 	short controlnum;
 
-	for (controlnum = 0; controlnum < cards_limit; controlnum++) {
-		sprintf(controlname, "snd/controlC%d", controlnum);
-		devfs_find_and_unregister(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0);
-	}
-#endif
-	
+	for (controlnum = 0; controlnum < cards_limit; controlnum++)
+		devfs_remove("snd/controlC%d", controlnum);
+
 #ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_unregister();
 #endif
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c	Sun Nov 17 20:30:15 2002
+++ b/sound/drivers/dummy.c	Sun Nov 17 20:30:15 2002
@@ -314,6 +314,7 @@
 		snd_magic_kfree(dpcm);
 		return -ENOMEM;
 	}
+	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
 	spin_lock_init(&dpcm->lock);
diff -Nru a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
--- a/sound/drivers/mpu401/mpu401_uart.c	Sun Nov 17 20:30:12 2002
+++ b/sound/drivers/mpu401/mpu401_uart.c	Sun Nov 17 20:30:12 2002
@@ -29,7 +29,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <sound/core.h>
 #include <sound/mpu401.h>
@@ -103,6 +103,7 @@
 
 	spin_lock_irqsave (&mpu->timer_lock, flags);
 	if (mpu->timer_invoked == 0) {
+		init_timer(&mpu->timer);
 		mpu->timer.data = (unsigned long)mpu;
 		mpu->timer.function = snd_mpu401_uart_timer;
 		mpu->timer.expires = 1 + jiffies;
diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
--- a/sound/drivers/mtpav.c	Sun Nov 17 20:30:15 2002
+++ b/sound/drivers/mtpav.c	Sun Nov 17 20:30:15 2002
@@ -51,8 +51,8 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
@@ -61,6 +61,8 @@
 #include <sound/rawmidi.h>
 #include <linux/delay.h>
 
+#include <asm/io.h>
+
 /*
  *      globals
  */
@@ -424,6 +426,7 @@
 /* spinlock held! */
 static void snd_mtpav_add_output_timer(mtpav_t *chip)
 {
+	init_timer(&chip->timer);
 	chip->timer.function = snd_mtpav_output_timer;
 	chip->timer.data = (unsigned long) mtp_card;
 	chip->timer.expires = 1 + jiffies;
diff -Nru a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
--- a/sound/drivers/opl3/opl3_seq.c	Sun Nov 17 20:30:14 2002
+++ b/sound/drivers/opl3/opl3_seq.c	Sun Nov 17 20:30:14 2002
@@ -267,6 +267,7 @@
 
 	/* setup system timer */
 	memset(&opl3->tlist, 0, sizeof(opl3->tlist));
+	init_timer(&opl3->tlist);
 	opl3->tlist.function = snd_opl3_timer_func;
 	opl3->tlist.data = (unsigned long) opl3;
 	spin_lock_init(&opl3->sys_timer_lock);
diff -Nru a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
--- a/sound/drivers/serial-u16550.c	Sun Nov 17 20:30:03 2002
+++ b/sound/drivers/serial-u16550.c	Sun Nov 17 20:30:03 2002
@@ -31,8 +31,8 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
@@ -41,6 +41,8 @@
 #include <sound/initval.h>
 
 #include <linux/serial_reg.h>
+
+#include <asm/io.h>
 
 MODULE_DESCRIPTION("MIDI serial u16550");
 MODULE_LICENSE("GPL");
diff -Nru a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
--- a/sound/isa/ad1848/ad1848_lib.c	Sun Nov 17 20:30:15 2002
+++ b/sound/isa/ad1848/ad1848_lib.c	Sun Nov 17 20:30:15 2002
@@ -21,15 +21,17 @@
 
 #define SNDRV_MAIN_OBJECT_FILE
 #include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
 #include <sound/ad1848.h>
 #include <sound/pcm_params.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c	Sun Nov 17 20:30:04 2002
+++ b/sound/isa/cs423x/cs4231_lib.c	Sun Nov 17 20:30:04 2002
@@ -25,17 +25,19 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/irq.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
 #include <sound/cs4231.h>
 #include <sound/pcm_params.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
diff -Nru a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
--- a/sound/isa/es1688/es1688_lib.c	Sun Nov 17 20:30:14 2002
+++ b/sound/isa/es1688/es1688_lib.c	Sun Nov 17 20:30:14 2002
@@ -20,15 +20,17 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
 #include <sound/es1688.h>
 #include <sound/initval.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
diff -Nru a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
--- a/sound/isa/gus/gus_main.c	Sun Nov 17 20:30:03 2002
+++ b/sound/isa/gus/gus_main.c	Sun Nov 17 20:30:03 2002
@@ -20,14 +20,16 @@
  */
 
 #include <sound/driver.h>
-#include <asm/dma.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
 #include <sound/gus.h>
 #include <sound/control.h>
+
+#include <asm/dma.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
diff -Nru a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
--- a/sound/isa/opl3sa2.c	Sun Nov 17 20:30:15 2002
+++ b/sound/isa/opl3sa2.c	Sun Nov 17 20:30:15 2002
@@ -20,8 +20,8 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
 #ifndef LINUX_ISAPNP_H
@@ -35,6 +35,8 @@
 #include <sound/opl3.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
+
+#include <asm/io.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Yamaha OPL3SA2+");
diff -Nru a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
--- a/sound/isa/sb/sb8_midi.c	Sun Nov 17 20:30:02 2002
+++ b/sound/isa/sb/sb8_midi.c	Sun Nov 17 20:30:02 2002
@@ -205,6 +205,7 @@
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_TRIGGER)) {
+			init_timer(&chip->midi_timer);
 			chip->midi_timer.function = snd_sb8dsp_midi_output_timer;
 			chip->midi_timer.data = (unsigned long) substream;
 			chip->midi_timer.expires = 1 + jiffies;
diff -Nru a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
--- a/sound/isa/sb/sb_common.c	Sun Nov 17 20:30:15 2002
+++ b/sound/isa/sb/sb_common.c	Sun Nov 17 20:30:15 2002
@@ -21,15 +21,17 @@
  */
 
 #include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
 #include <sound/sb.h>
 #include <sound/initval.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
 
 #define chip_t sb_t
 
diff -Nru a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
--- a/sound/isa/wavefront/wavefront.c	Sun Nov 17 20:30:15 2002
+++ b/sound/isa/wavefront/wavefront.c	Sun Nov 17 20:30:15 2002
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #ifndef LINUX_ISAPNP_H
 #include <linux/isapnp.h>
diff -Nru a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
--- a/sound/isa/wavefront/wavefront_midi.c	Sun Nov 17 20:30:15 2002
+++ b/sound/isa/wavefront/wavefront_midi.c	Sun Nov 17 20:30:15 2002
@@ -377,6 +377,7 @@
 	if (up) {
 		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
 			if (!midi->istimer) {
+				init_timer(&midi->timer);
 				midi->timer.function = snd_wavefront_midi_output_timer;
 				midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
 				midi->timer.expires = 1 + jiffies;
diff -Nru a/sound/oss/ad1816.c b/sound/oss/ad1816.c
--- a/sound/oss/ad1816.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/ad1816.c	Sun Nov 17 20:30:15 2002
@@ -35,6 +35,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/isapnp.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
diff -Nru a/sound/oss/ad1848.c b/sound/oss/ad1848.c
--- a/sound/oss/ad1848.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/ad1848.c	Sun Nov 17 20:30:14 2002
@@ -43,6 +43,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/pm.h>
diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/cmpci.c	Sun Nov 17 20:30:14 2002
@@ -90,6 +90,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -98,15 +99,16 @@
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/wrapper.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/bitops.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 #include "dm.h"
 
@@ -1466,11 +1468,11 @@
 }
 
 static /*const*/ struct file_operations cm_mixer_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	ioctl:		cm_ioctl_mixdev,
-	open:		cm_open_mixdev,
-	release:	cm_release_mixdev,
+	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
+	.ioctl	 = cm_ioctl_mixdev,
+	.open	 = cm_open_mixdev,
+	.release = cm_release_mixdev,
 };
 
 
@@ -2278,15 +2280,15 @@
 }
 
 static /*const*/ struct file_operations cm_audio_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	read:		cm_read,
-	write:		cm_write,
-	poll:		cm_poll,
-	ioctl:		cm_ioctl,
-	mmap:		cm_mmap,
-	open:		cm_open,
-	release:	cm_release,
+	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
+	.read	 = cm_read,
+	.write	 = cm_write,
+	.poll	 = cm_poll,
+	.ioctl	 = cm_ioctl,
+	.mmap	 = cm_mmap,
+	.open	 = cm_open,
+	.release = cm_release,
 };
 
 #ifdef CONFIG_SOUND_CMPCI_MIDI
@@ -2556,13 +2558,13 @@
 }
 
 static /*const*/ struct file_operations cm_midi_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	read:		cm_midi_read,
-	write:		cm_midi_write,
-	poll:		cm_midi_poll,
-	open:		cm_midi_open,
-	release:	cm_midi_release,
+	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
+	.read	 = cm_midi_read,
+	.write	 = cm_midi_write,
+	.poll	 = cm_midi_poll,
+	.open	 = cm_midi_open,
+	.release = cm_midi_release,
 };
 #endif
 
@@ -2722,11 +2724,11 @@
 }
 
 static /*const*/ struct file_operations cm_dmfm_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	ioctl:		cm_dmfm_ioctl,
-	open:		cm_dmfm_open,
-	release:	cm_dmfm_release,
+	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
+	.ioctl	 = cm_dmfm_ioctl,
+	.open	 = cm_dmfm_open,
+	.release = cm_dmfm_release,
 };
 #endif /* CONFIG_SOUND_CMPCI_FM */
 
diff -Nru a/sound/oss/es1370.c b/sound/oss/es1370.c
--- a/sound/oss/es1370.c	Sun Nov 17 20:30:16 2002
+++ b/sound/oss/es1370.c	Sun Nov 17 20:30:16 2002
@@ -140,6 +140,7 @@
 /*****************************************************************************/
       
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -151,14 +152,15 @@
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/gameport.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/sound/oss/es1371.c b/sound/oss/es1371.c
--- a/sound/oss/es1371.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/es1371.c	Sun Nov 17 20:30:15 2002
@@ -109,6 +109,7 @@
 /*****************************************************************************/
       
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -126,11 +127,12 @@
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
+#include <linux/gameport.h>
+#include <linux/wait.h>
+
 #include <asm/io.h>
-#include <asm/dma.h>
+#include <asm/page.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
-#include <linux/gameport.h>
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
--- a/sound/oss/esssolo1.c	Sun Nov 17 20:30:03 2002
+++ b/sound/oss/esssolo1.c	Sun Nov 17 20:30:03 2002
@@ -87,6 +87,7 @@
 /*****************************************************************************/
       
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -97,16 +98,17 @@
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/gameport.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 #include "dm.h"
 
diff -Nru a/sound/oss/gus_card.c b/sound/oss/gus_card.c
--- a/sound/oss/gus_card.c	Sun Nov 17 20:30:02 2002
+++ b/sound/oss/gus_card.c	Sun Nov 17 20:30:02 2002
@@ -17,6 +17,7 @@
  
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 
 #include "sound_config.h"
diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
--- a/sound/oss/i810_audio.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/i810_audio.c	Sun Nov 17 20:30:15 2002
@@ -70,24 +70,24 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/string.h>
-#include <linux/ctype.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #ifndef PCI_DEVICE_ID_INTEL_82801
 #define PCI_DEVICE_ID_INTEL_82801	0x2415
diff -Nru a/sound/oss/mpu401.c b/sound/oss/mpu401.c
--- a/sound/oss/mpu401.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/mpu401.c	Sun Nov 17 20:30:15 2002
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #define USE_SEQ_MACROS
 #define USE_SIMPLE_MACROS
diff -Nru a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
--- a/sound/oss/nm256_audio.c	Sun Nov 17 20:30:13 2002
+++ b/sound/oss/nm256_audio.c	Sun Nov 17 20:30:13 2002
@@ -22,6 +22,7 @@
 #define __NO_VERSION__
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/delay.h>
diff -Nru a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c
--- a/sound/oss/pas2_card.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/pas2_card.c	Sun Nov 17 20:30:15 2002
@@ -6,6 +6,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include "sound_config.h"
diff -Nru a/sound/oss/sb_common.c b/sound/oss/sb_common.c
--- a/sound/oss/sb_common.c	Sun Nov 17 20:30:02 2002
+++ b/sound/oss/sb_common.c	Sun Nov 17 20:30:02 2002
@@ -28,6 +28,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
diff -Nru a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
--- a/sound/oss/sonicvibes.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/sonicvibes.c	Sun Nov 17 20:30:14 2002
@@ -103,22 +103,23 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/gameport.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
 
 #include "dm.h"
 
diff -Nru a/sound/oss/soundcard.c b/sound/oss/soundcard.c
--- a/sound/oss/soundcard.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/soundcard.c	Sun Nov 17 20:30:14 2002
@@ -542,38 +542,6 @@
 	 &num_audiodevs},
 };
 
-static char * 
-soundcard_make_name(char *buf, char *name, int idx) {
-	if (idx==0)
-		sprintf(buf, "sound/%s", name);
-	else
-		sprintf(buf, "sound/%s%d", name, idx);
-	return buf;
-}
-	
-/* Register/unregister audio entries */
-static void soundcard_register_devfs (int do_register)
-{
-	char name_buf[32];
-	int i, j, num;
-
-	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
-		num = (dev_list[i].num == NULL) ? 0 : *dev_list[i].num;
-		for (j = 0; j < num || j == 0; j++) {
-			soundcard_make_name (name_buf, dev_list[i].name, j);
-			if (do_register)
-				devfs_register (NULL, name_buf, DEVFS_FL_NONE,
-					SOUND_MAJOR, dev_list[i].minor+ (j* 0x10),
-					S_IFCHR | dev_list[i].mode,
-					&oss_sound_fops, NULL);
-			else
-				devfs_find_and_unregister(NULL, name_buf, 0, 0,
-							  DEVFS_SPECIAL_CHR,0);
-		}
-	}
-}
-
-
 static int dmabuf = 0;
 static int dmabug = 0;
 
@@ -583,6 +551,8 @@
 static int __init oss_init(void)
 {
 	int             err;
+	char name_buf[32];
+	int i, j;
 	
 	/* drag in sound_syms.o */
 	{
@@ -604,7 +574,22 @@
 	/* Protecting the innocent */
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
-	soundcard_register_devfs(1);
+	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+		sprintf(name_buf, "sound/%s", dev_list[i].name);
+		devfs_register (NULL, name_buf, DEVFS_FL_NONE,
+			SOUND_MAJOR, dev_list[i].minor,
+			S_IFCHR | dev_list[i].mode,
+			&oss_sound_fops, NULL);
+		if (!dev_list[i].num)
+			continue;
+		for (j = 1; j < *dev_list[i].num; j++) {
+			sprintf(name_buf, "sound/%s%d", dev_list[i].name, j);
+			devfs_register (NULL, name_buf, DEVFS_FL_NONE,
+				SOUND_MAJOR, dev_list[i].minor + (j * 0x10),
+				S_IFCHR | dev_list[i].mode,
+				&oss_sound_fops, NULL);
+		}
+	}
 
 	if (sound_nblocks >= 1024)
 		printk(KERN_ERR "Sound warning: Deallocation table was too small.\n");
@@ -614,12 +599,18 @@
 
 static void __exit oss_cleanup(void)
 {
-	int i;
+	int i, j;
 
 	if (MOD_IN_USE)
 		return;
 
-	soundcard_register_devfs (0);
+	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+		devfs_remove("snd/%s", dev_list[i].name);
+		if (!dev_list[i].num)
+			continue;
+		for (j = 1; j < *dev_list[i].num; j++)
+			devfs_remove("sound/%s%d", dev_list[i].name, j);
+	}
 	
 	unregister_sound_special(1);
 	unregister_sound_special(8);
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/trident.c	Sun Nov 17 20:30:15 2002
@@ -4148,6 +4148,7 @@
 	}
 	memset(card, 0, sizeof(*card));
 
+	init_timer(&card->timer);
 	card->iobase = iobase;
 	card->pci_dev = pci_dev;
 	card->pci_id = pci_id->device;
diff -Nru a/sound/oss/uart401.c b/sound/oss/uart401.c
--- a/sound/oss/uart401.c	Sun Nov 17 20:30:15 2002
+++ b/sound/oss/uart401.c	Sun Nov 17 20:30:15 2002
@@ -22,6 +22,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include "sound_config.h"
diff -Nru a/sound/oss/uart6850.c b/sound/oss/uart6850.c
--- a/sound/oss/uart6850.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/uart6850.c	Sun Nov 17 20:30:14 2002
@@ -22,6 +22,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 /* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
diff -Nru a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
--- a/sound/oss/via82cxxx_audio.c	Sun Nov 17 20:30:12 2002
+++ b/sound/oss/via82cxxx_audio.c	Sun Nov 17 20:30:12 2002
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/sound.h>
@@ -34,7 +35,6 @@
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/semaphore.h>
 #include "sound_config.h"
 #include "dev_table.h"
diff -Nru a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
--- a/sound/oss/ymfpci.c	Sun Nov 17 20:30:14 2002
+++ b/sound/oss/ymfpci.c	Sun Nov 17 20:30:14 2002
@@ -54,6 +54,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
diff -Nru a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
--- a/sound/synth/emux/emux.c	Sun Nov 17 20:30:14 2002
+++ b/sound/synth/emux/emux.c	Sun Nov 17 20:30:14 2002
@@ -53,6 +53,7 @@
 	emu->max_voices = 0;
 	emu->use_time = 0;
 
+	init_timer(&emu->tlist);
 	emu->tlist.function = snd_emux_timer_callback;
 	emu->tlist.data = (unsigned long)emu;
 	emu->timer_active = 0;
