## Automatically generated incremental diff
## From:   linux-2.4.7-pre3
## To:     linux-2.4.7-pre4
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.7-pre3/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.7-pre3/Documentation/Configure.help	Mon Jul  2 14:07:55 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:54:19 2001
@@ -8842,6 +8842,18 @@
   say M here and read Documentation/modules.txt. This is recommended.
   The module will be called myri_sbus.o.
 
+D-Link 2000-based Gigabit Ethernet support
+CONFIG_DL2K
+  This driver supports D-Link 2000-based gigabit ethernet cards, which
+  includes
+	D-Link DGE-550T Gigabit Ethernet Adapter.
+	D-Link DL2000-based Gigabit Ethernet Adapter.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. This is recommended.
+  The module will be called dl2k.o.
+
 AMD LANCE and PCnet (AT1500 and NE2100) support
 CONFIG_LANCE
   If you have a network (Ethernet) card of this type, say Y and read
diff -urN linux-2.4.7-pre3/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- linux-2.4.7-pre3/Documentation/DocBook/Makefile	Mon Jul  2 13:56:40 2001
+++ linux/Documentation/DocBook/Makefile	Mon Dec  3 22:54:19 2001
@@ -1,7 +1,7 @@
 BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
 	   kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
 	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
-	   deviceiobook.sgml procfs-guide.sgml
+	   deviceiobook.sgml procfs-guide.sgml tulip-user.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -61,6 +61,9 @@
 via-audio.sgml: via-audio.tmpl $(TOPDIR)/drivers/sound/via82cxxx_audio.c
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/sound/via82cxxx_audio.c \
 		<via-audio.tmpl >via-audio.sgml
+
+tulip-user.sgml: tulip-user.tmpl
+	$(TOPDIR)/scripts/docgen <$< >$@
 
 sis900.sgml: sis900.tmpl $(TOPDIR)/drivers/net/sis900.c
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/sis900.c \
diff -urN linux-2.4.7-pre3/Documentation/DocBook/via-audio.tmpl linux/Documentation/DocBook/via-audio.tmpl
--- linux-2.4.7-pre3/Documentation/DocBook/via-audio.tmpl	Mon Oct 30 12:24:22 2000
+++ linux/Documentation/DocBook/via-audio.tmpl	Mon Dec  3 22:54:19 2001
@@ -17,7 +17,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2000</year>
+   <year>1999-2001</year>
    <holder>Jeff Garzik</holder>
   </copyright>
 
@@ -149,23 +149,6 @@
      <title>Known Bugs And Assumptions</title>
   <para>
   <variablelist>
-    <varlistentry><term>MMAP support</term>
-    <listitem>
-    <para>
-    	MMAP support is currently missing.  Make sure to
-	test with Quake.
-    </para>
-    </listitem></varlistentry>
-
-    <varlistentry><term>AC97 codec timeout during init</term>
-    <listitem>
-    <para>
-    	A warning message "via82cxxx: timeout while reading AC97
-	codec" is printed during driver initialization.  This
-	message can safely be ignored.
-    </para>
-    </listitem></varlistentry>
-
     <varlistentry><term>Low volume</term>
     <listitem>
     <para>
@@ -198,6 +181,16 @@
   <para>
 	AC97 mixer interface fixes and debugging by Ron Cemer <email>roncemer@gte.net</email>.
   </para>
+  <para>
+	Rui Sousa <email>rui.sousa@conexant.com</email>, for bugfixing
+	MMAP support, and several other notable fixes that resulted from
+	his hard work and testing.
+  </para>
+  <para>
+	Adrian Cox <email>adrian@humboldt.co.uk</email>, for bugfixing
+	MMAP support, and several other notable fixes that resulted from
+	his hard work and testing.
+  </para>
   </chapter>
   
   <chapter id="notes">
@@ -219,7 +212,10 @@
 	and device ids are not examined.
   </para>
   <para>
-	GNU indent formatting options:  -kr -i8 -pcs
+	GNU indent formatting options:
+  <programlisting>
+-kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl
+  </programlisting>
   </para>
   <para>
 	Via has graciously donated e-mail support and source code to help further
@@ -237,6 +233,79 @@
 
   <chapter id="changelog">
       <title>Driver ChangeLog</title>
+
+<sect1 id="version1115"><title>
+Version 1.1.15
+</title>
+  <itemizedlist spacing=compact>
+   <listitem>
+    <para>
+    Support for variable fragment size and variable fragment number (Rui
+    Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &
+    write mode (Rui Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Mmaped sound is now fully functional. (Rui Sousa)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Make sure to enable PCI device before reading any of its PCI
+    config information. (fixes potential hotplug problems)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Clean up code a bit and add more internal function documentation.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    AC97 codec access fixes (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Big endian fixes (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    MIDI support (Adrian Cox)
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Detect and report locked-rate AC97 codecs.  If your hardware only
+    supports 48Khz (locked rate), then your recording/playback software
+    must upsample or downsample accordingly.  The hardware cannot do it.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+    Use new pci_request_regions and pci_disable_device functions in
+    kernel 2.4.6.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+</sect1>
 
 <sect1 id="version1114"><title>
 Version 1.1.14
diff -urN linux-2.4.7-pre3/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- linux-2.4.7-pre3/Documentation/networking/8139too.txt	Mon May  7 14:13:19 2001
+++ linux/Documentation/networking/8139too.txt	Mon Dec  3 22:54:19 2001
@@ -185,6 +185,20 @@
 Change History
 --------------
 
+Version 0.9.18 - July 6, 2001
+
+* Fix race leading to crashes on some machines.
+* Minimize race leading to low performance.
+* Correct interrupt acknowledgement to cover all three
+  relevant Rx events.
+* Add ethtool driver info support.
+* Collect additional driver-internal statistics.
+* Add descriptions for module parameters.
+* Support new SIOCxMIIxxx ioctls added in kernel 2.4.6.
+* Multicast filter big endian fix.
+* Support new PCI PM API added in kernel 2.4.6.
+
+
 Version 0.9.17 - May 7, 2001
 
 * Fix chipset wakeup bug which prevent media connection for 8139B
diff -urN linux-2.4.7-pre3/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- linux-2.4.7-pre3/Documentation/networking/dl2k.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/dl2k.txt	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,236 @@
+
+    D-Link DL2000-based Gigabit Ethernet Adapter Installation 
+    for Linux
+    July 5, 2001
+
+Contents
+========
+ - Compatibility List
+ - Quick Install
+ - Compiling the Driver
+ - Installing the Driver
+ - Option parameter
+ - Configuration Script Sample
+ - Troubleshooting
+
+
+Compatiblity List
+=================
+Adapter Support:
+
+D-Link DGE-550T Gigabit Ethernet Adapter.
+D-Link DL2000-based Gigabit Ethernet Adapter.
+
+
+The driver support Linux kernal 2.4.x later. We had tested it 
+on the environments below.
+
+ . Red Hat v6.2 (update to kernel 2.4.4)
+ . Red Hat v7.0 (update to kernel 2.4.4)
+ . Red Hat v7.1 (kernel 2.4.2-2)
+
+
+Quick Install
+=============
+Install linux driver as following command:
+
+1. make all
+2. insmod dl2x.o 
+3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0
+                    ^^^^^^^^^^^^^^^\        ^^^^^^^^\
+		    		    IP	             NETMASK 
+Now eth0 bring up, you can test it by "ping" or get more information by 
+"ifconfig". If test ok, then continue next step.
+
+4. cp dl2x.o /lib/modules/`uname -r`/kernel/drivers/net
+5. Add the following lines to /etc/modules.conf:
+	alias eth0 dl2x
+6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0 
+   located at /etc/sysconfig/network-scripts or create it manually.
+   [see - Configuration Script Sample]
+7. Driver will automatically load and configure at next boot time.
+
+Compiling the Driver
+====================
+  In Linux, NIC drivers are most commonly configured as loadable modules.
+The approach of building a monolithic kernel has become obsolete. The driver
+can be compiled as part of a monolithic kernel, but is strongly discouraged.
+The remainder of this section assumes the driver is built as a loadable module.
+In the Linux environment, it is a good idea to rebuild the driver from the
+source instead of relying on a precompiled version. This approach provides
+better reliability since a precompiled driver might depend on libraries or
+kernel features that are not present in a given Linux installation.
+
+The 3 files necessary to build Linux device driver are dl2x.c, dl2x.h and
+Makefile. To compile, the Linux installation must include the gcc compiler,
+the kernel source, and the kernel headers. The Linux driver supports Linux
+Kernels 2.4.x. Copy the files to a directory and enter the following command 
+to compile and link the driver:
+
+CD-ROM drive
+------------
+
+[root@XXX /] mkdir cdrom
+[root@XXX /] mount -r -t iso9660 -o conv=auto /dev/cdrom /cdrom
+[root@XXX /] cd root
+[root@XXX /root] mkdir dl2x
+[root@XXX /root] cd dl2x
+[root@XXX dl2x] cp /cdrom/linux/dl2x.tgz /root/dl2x
+[root@XXX dl2x] tar xfvz dl2x.tgz 
+[root@XXX dl2x] make all
+
+Floppy disc drive
+-----------------
+
+[root@XXX /] cd root
+[root@XXX /root] mkdir dl2x
+[root@XXX /root] cd dl2x
+[root@XXX dl2x] mcopy a:/linux/dl2x.tgz /root/dl2x
+[root@XXX dl2x] tar xfvz dl2x.tgz 
+[root@XXX dl2x] make all
+
+Installing the Driver
+=====================
+
+  Manual Installation
+  -------------------
+  Once the driver has been compiled, it must be loaded, enabled, and bound
+  to a protocol stack in order to establish network connectivity. To load a
+  module enter the command:
+
+  insmod dl2x.o
+ 
+
+  or
+
+  insmod dl2x.o <optional parameter>    ; add parameter
+  
+  ===============================================================
+   example: insmod dl2x.o media=100mbps_hd
+   or       insmod dl2x.o media=3
+   or	    insmod dl2x.o media=3 2	; for 2 cards
+  ===============================================================
+
+  Please reference the list of the command line parameters supported by
+  the Linux device driver below.
+
+  The insmod command only loads the driver and gives it a name of the form
+  eth0, eth1, etc. To bring the NIC into an operational state,
+  it is necessary to issue the following command:
+
+  ifconfig eth0 up
+
+  Finally, to bind the driver to the active protocol (e.g., TCP/IP with
+  Linux), enter the following command:
+
+  ifup eth0
+
+  Note that this is meaningful only if the system can find a configuration
+  script that contains the necessary network information. A sample will be
+  given in the next paragraph.
+
+  The commands to unload a driver are as follows:
+
+  ifdown eth0
+  ifconfig eth0 down
+  rmmod dl2x.o
+
+  The following are the commands to list the currently loaded modules and
+  to see the current network configuration.
+
+  lsmod
+  ifconfig
+
+
+  Automated Installation
+  ----------------------
+  This section describes how to install the driver such that it is
+  automatically loaded and configured at boot time. The following description
+  is based on a Red Hat 6.0/7.0 distribution, but it can easily be ported to
+  other distributions as well.
+
+  Red Hat v6.x/v7.x
+  -----------------
+  1. Copy dl2x.o to the network modules directory, typically
+     /lib/modules/2.x.x-xx/net or /lib/modules/2.x.x/kernel/drivers/net.
+  2. Locate the boot module configuration file, most commonly modules.conf
+     or conf.modules in the /etc directory. Add the following lines:
+
+     alias ethx dl2x
+     options dl2x <optional parameters>
+
+     where ethx will be eth0 if the NIC is the only ethernet adapter, eth1 if
+     one other ethernet adapter is installed, etc. Refer to the table in the
+     previous section for the list of optional parameters.
+  3. Locate the network configuration scripts, normally the
+     /etc/sysconfig/network-scripts directory, and create a configuration
+     script named ifcfg-ethx that contains network information.
+  4. Note that for most Linux distributions, Red Hat included, a configuration
+     utility with a graphical user interface is provided to perform steps 2
+     and 3 above.
+
+
+Parameter Description
+=====================
+You can install this driver without any addtional parameter. However, if you 
+are going to have extensive functions then it is necessary to set extra 
+parameter. Below is a list of the command line parameters supported by the 
+Linux device
+driver.
+
+mtu=packet_size                 - Specifies the maximum packet size. default
+                                  is 1500.
+
+media=xxxxxxxxx			- Specifies the media type the NIC operates at.
+				  autosense	Autosensing active media.
+				  10mbps_hd 	10Mbps half duplex.
+				  10mbps_fd 	10Mbps full duplex.
+				  100mbps_hd 	100Mbps half duplex.
+				  100mbps_fd 	100Mbps full duplex.
+				  1000mbps_fd	1000Mbps full duplex.
+				  1000mbps_hd	1000Mbps half duplex.
+				  0		Autosensing active media.
+				  1	 	10Mbps half duplex.
+				  2	 	10Mbps full duplex.
+				  3	 	100Mbps half duplex.
+				  4	 	100Mbps full duplex.
+				  5		1000Mbps full duplex.
+				  6		1000Mbps half duplex.
+				  By default, the NIC operates at autosense.
+				  
+vlan=x				- Specifies the VLAN ID. If vlan=0, the  
+				  Virtual Local Area Network (VLAN) function is
+				  disable. 
+				  
+jumbo=x				- Specifies the jumbo frame support. If jumbo=1, 
+				  the NIC accept jumbo frames. By default, this
+				  function is disabled.
+
+Configuration Script Sample
+===========================
+Here is a sample of a simple configuration script:
+
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+POOTPROTO=none
+BROADCAST=207.200.5.255
+NETWORK=207.200.5.0
+NETMASK=255.255.255.0
+IPADDR=207.200.5.2
+
+
+Troubleshooting
+===============
+Q: Couldn't compiler the driver ?
+A1: Copy all necessary files on same current directory. Make sure all files 
+   are Unix file format (no LF). You can use some convertible program conver 
+   it from DOS to UNIX. (Like dos2unix,  UltraEdit-32 ...).
+      
+A2: The default include directory configured in Makefile is 
+    /usr/src/linux/include. If kernel source was not installed, you could 
+    not compile driver. Try to install kernel source, and make sure kernel 
+    source in /usr/src/linux. If there is a copy of header files in 
+    /usr/include, you can try to change the variable "INCLUDEDIR" in Makefile from 
+    /usr/src/linux/include to /usr/include.
+    
diff -urN linux-2.4.7-pre3/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.7-pre3/MAINTAINERS	Wed Jun 27 13:59:32 2001
+++ linux/MAINTAINERS	Mon Dec  3 22:54:19 2001
@@ -106,6 +106,12 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+ACENIC DRIVER
+P:	Jes Sorensen
+M:	jes@trained-monkey.org
+L:	linux-acenic@sunsite.dk
+S:	Maintained
+
 ACI MIXER DRIVER
 P:	Robert Siemer
 M:	Robert.Siemer@gmx.de
@@ -566,8 +572,8 @@
 
 HIPPI
 P:	Jes Sorensen
-M:	jes@linuxcare.com
-L:	linux-hippi@sunsite.auc.dk
+M:	jes@trained-monkey.org
+L:	linux-hippi@sunsite.dk
 S:	Maintained
 
 HP100:	Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
@@ -812,7 +818,7 @@
 
 M68K
 P:	Jes Sorensen
-M:	jes@linuxcare.com
+M:	jes@trained-monkey.org
 W:	http://www.clark.net/pub/lawrencc/linux/index.html
 L:	linux-m68k@lists.linux-m68k.org
 S:	Maintained
diff -urN linux-2.4.7-pre3/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.7-pre3/arch/i386/defconfig	Mon Jul  2 16:08:28 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 22:54:19 2001
@@ -414,6 +414,7 @@
 #
 # CONFIG_ACENIC is not set
 # CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
diff -urN linux-2.4.7-pre3/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- linux-2.4.7-pre3/arch/i386/kernel/vm86.c	Sun Oct  1 20:35:15 2000
+++ linux/arch/i386/kernel/vm86.c	Mon Dec  3 22:54:19 2001
@@ -456,7 +456,7 @@
 	if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
 		pushw(ssp,sp,popw(ssp,sp) | TF_MASK);
 #define VM86_FAULT_RETURN \
-	if (VMPI.force_return_for_pic  && (VEFLAGS & IF_MASK)) \
+	if (VMPI.force_return_for_pic  && (VEFLAGS & (IF_MASK | VIF_MASK))) \
 		return_to_32bit(regs, VM86_PICRETURN); \
 	return;
 	                                   
diff -urN linux-2.4.7-pre3/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- linux-2.4.7-pre3/arch/ppc/kernel/prom.c	Mon Jul  2 14:34:57 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Dec  3 22:54:19 2001
@@ -116,8 +116,11 @@
 unsigned int rtas_size;
 unsigned int old_rtas;
 
-/* Set for a newworld machine */
+/* Set for a newworld or CHRP machine */
 int use_of_interrupt_tree;
+struct device_node *dflt_interrupt_controller;
+int num_interrupt_controllers;
+
 int pmac_newworld;
 
 static struct device_node *allnodes;
@@ -1153,7 +1156,19 @@
 		*prev_propp = PTRUNRELOC(pp);
 		prev_propp = &pp->next;
 	}
-	*prev_propp = 0;
+	if (np->node != NULL) {
+		/* Add a "linux,phandle" property" */
+		pp = (struct property *) mem_start;
+		*prev_propp = PTRUNRELOC(pp);
+		prev_propp = &pp->next;
+		namep = (char *) (pp + 1);
+		pp->name = PTRUNRELOC(namep);
+		strcpy(namep, RELOC("linux,phandle"));
+		mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
+		pp->value = (unsigned char *) PTRUNRELOC(&np->node);
+		pp->length = sizeof(np->node);
+	}
+	*prev_propp = NULL;
 
 	/* get the node's full name */
 	l = (int) call_prom(RELOC("package-to-path"), 3, 1, node,
@@ -1186,19 +1201,46 @@
 finish_device_tree(void)
 {
 	unsigned long mem = (unsigned long) klimit;
+	struct device_node *np;
 
-	/* All newworld machines now use the interrupt tree */
-	struct device_node *np = allnodes;
-
-	while(np && (_machine == _MACH_Pmac)) {
+	/* All newworld pmac machines and CHRPs now use the interrupt tree */
+	for (np = allnodes; np != NULL; np = np->allnext) {
 		if (get_property(np, "interrupt-parent", 0)) {
-			pmac_newworld = 1;
+			use_of_interrupt_tree = 1;
 			break;
 		}
-		np = np->allnext;
 	}
-	if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld))
-		use_of_interrupt_tree = 1;
+	if (_machine == _MACH_Pmac && use_of_interrupt_tree)
+		pmac_newworld = 1;
+
+#ifdef CONFIG_BOOTX_TEXT
+	if (boot_infos && pmac_newworld) {
+		prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
+		prom_print("          You should use an Open Firmware bootloader\n");
+	}
+#endif /* CONFIG_BOOTX_TEXT */
+
+	if (use_of_interrupt_tree) {
+		/*
+		 * We want to find out here how many interrupt-controller
+		 * nodes there are, and if we are booted from BootX,
+		 * we need a pointer to the first (and hopefully only)
+		 * such node.  But we can't use find_devices here since
+		 * np->name has not been set yet.  -- paulus
+		 */
+		int n = 0;
+		char *name;
+
+		for (np = allnodes; np != NULL; np = np->allnext) {
+			if ((name = get_property(np, "name", NULL)) == NULL
+			    || strcmp(name, "interrupt-controller") != 0)
+				continue;
+			if (n == 0)
+				dflt_interrupt_controller = np;
+			++n;
+		}
+		num_interrupt_controllers = n;
+	}
 
 	mem = finish_node(allnodes, mem, NULL, 1, 1);
 	dev_tree_size = mem - (unsigned long) allnodes;
@@ -1240,9 +1282,8 @@
 	if (ifunc != NULL) {
 		mem_start = ifunc(np, mem_start, naddrc, nsizec);
 	}
-	if (use_of_interrupt_tree) {
+	if (use_of_interrupt_tree)
 		mem_start = finish_node_interrupts(np, mem_start);
-	}
 
 	/* Look for #address-cells and #size-cells properties. */
 	ip = (int *) get_property(np, "#address-cells", 0);
@@ -1298,141 +1339,210 @@
 	return mem_start;
 }
 
-/* This routine walks the interrupt tree for a given device node and gather 
- * all necessary informations according to the draft interrupt mapping
- * for CHRP. The current version was only tested on Apple "Core99" machines
- * and may not handle cascaded controllers correctly.
+/*
+ * Find the interrupt parent of a node.
+ */
+static struct device_node *intr_parent(struct device_node *p)
+{
+	phandle *parp;
+
+	parp = (phandle *) get_property(p, "interrupt-parent", NULL);
+	if (parp == NULL)
+		return p->parent;
+	p = find_phandle(*parp);
+	if (p != NULL)
+		return p;
+	/*
+	 * On a powermac booted with BootX, we don't get to know the
+	 * phandles for any nodes, so find_phandle will return NULL.
+	 * Fortunately these machines only have one interrupt controller
+	 * so there isn't in fact any ambiguity.  -- paulus
+	 */
+	if (num_interrupt_controllers == 1)
+		p = dflt_interrupt_controller;
+	return p;
+}
+
+/*
+ * Find out the size of each entry of the interrupts property
+ * for a node.
  */
-__init
-static unsigned long
-finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+static int
+prom_n_intr_cells(struct device_node *np)
 {
-	/* Finish this node */
-	unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;
-	phandle *parent;
-	struct device_node *node, *parent_node;
-	int l, isize, ipsize, asize, map_size, regpsize;
-
-	/* Currently, we don't look at all nodes with no "interrupts" property */
-	interrupts = (unsigned int *)get_property(np, "interrupts", &l);
-	if (interrupts == NULL)
-		return mem_start;
-	ipsize = l>>2;
+	struct device_node *p;
+	unsigned int *icp;
 
-	reg = (unsigned int *)get_property(np, "reg", &l);
-	regpsize = l>>2;
+	for (p = np; (p = intr_parent(p)) != NULL; ) {
+		icp = (unsigned int *)
+			get_property(p, "#interrupt-cells", NULL);
+		if (icp != NULL)
+			return *icp;
+		if (get_property(p, "interrupt-controller", NULL) != NULL
+		    || get_property(p, "interrupt-map", NULL) != NULL) {
+			printk("oops, node %s doesn't have #interrupt-cells\n",
+			       p->full_name);
+			return 1;
+		}
+	}
+	printk("prom_n_intr_cells failed for %s\n", np->full_name);
+	return 1;
+}
 
-	/* We assume default interrupt cell size is 1 (bugus ?) */
-	isize = 1;
-	node = np;
-	
-	do {
-	    /* We adjust the cell size if the current parent contains an #interrupt-cells
-	     * property */
-	    isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);
-	    if (isizep)
-	    	isize = *isizep;
-
-	    /* We don't do interrupt cascade (ISA) for now, we stop on the first 
-	     * controller found
-	     */
-	    if (get_property(node, "interrupt-controller", &l)) {
-	    	int i,j;
-		int cvt_irq;
-
-		/* XXX on chrp, offset interrupt numbers for the
-		   8259 by 0, those for the openpic by 16 */
-		cvt_irq = _machine == _MACH_chrp
-			&& get_property(node, "interrupt-parent", NULL) == 0;
-	    	np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = ipsize / isize;
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-		    np->intrs[i].line = *interrupts++;
-		    if (cvt_irq)
-			np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
-		    np->intrs[i].sense = 1;
-		    if (isize > 1)
-		        np->intrs[i].sense = *interrupts++;
-		    for (j=2; j<isize; j++)
-		    	interrupts++;
+/*
+ * Map an interrupt from a device up to the platform interrupt
+ * descriptor.
+ */
+static int
+map_interrupt(unsigned int **irq, struct device_node **ictrler,
+	      struct device_node *np, unsigned int *ints, int nintrc)
+{
+	struct device_node *p, *ipar;
+	unsigned int *imap, *imask, *ip;
+	int i, imaplen, match;
+	int newintrc, newaddrc;
+	unsigned int *reg;
+	int naddrc;
+
+	reg = (unsigned int *) get_property(np, "reg", NULL);
+	naddrc = prom_n_addr_cells(np);
+	p = intr_parent(np);
+	while (p != NULL) {
+		if (get_property(p, "interrupt-controller", NULL) != NULL)
+			/* this node is an interrupt controller, stop here */
+			break;
+		imap = (unsigned int *)
+			get_property(p, "interrupt-map", &imaplen);
+		if (imap == NULL) {
+			p = intr_parent(p);
+			continue;
 		}
+		imask = (unsigned int *)
+			get_property(p, "interrupt-map-mask", NULL);
+		if (imask == NULL) {
+			printk("oops, %s has interrupt-map but no mask\n",
+			       p->full_name);
+			return 0;
+		}
+		imaplen /= sizeof(unsigned int);
+		match = 0;
+		ipar = NULL;
+		while (imaplen > 0 && !match) {
+			/* check the child-interrupt field */
+			match = 1;
+			for (i = 0; i < naddrc && match; ++i)
+				match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
+			for (; i < naddrc + nintrc && match; ++i)
+				match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
+			imap += naddrc + nintrc;
+			imaplen -= naddrc + nintrc;
+			/* grab the interrupt parent */
+			ipar = find_phandle((phandle) *imap++);
+			--imaplen;
+			if (ipar == NULL && num_interrupt_controllers == 1)
+				/* cope with BootX not giving us phandles */
+				ipar = dflt_interrupt_controller;
+			if (ipar == NULL) {
+				printk("oops, no int parent %x in map of %s\n",
+				       imap[-1], p->full_name);
+				return 0;
+			}
+			/* find the parent's # addr and intr cells */
+			ip = (unsigned int *)
+				get_property(ipar, "#interrupt-cells", NULL);
+			if (ip == NULL) {
+				printk("oops, no #interrupt-cells on %s\n",
+				       ipar->full_name);
+				return 0;
+			}
+			newintrc = *ip;
+			ip = (unsigned int *)
+				get_property(ipar, "#address-cells", NULL);
+			newaddrc = (ip == NULL)? 0: *ip;
+			imap += newaddrc + newintrc;
+			imaplen -= newaddrc + newintrc;
+		}
+		if (imaplen < 0) {
+			printk("oops, error decoding int-map on %s, len=%d\n",
+			       p->full_name, imaplen);
+			return 0;
+		}
+		if (!match) {
+			printk("oops, no match in %s int-map for %s\n",
+			       p->full_name, np->full_name);
+			return 0;
+		}
+		p = ipar;
+		naddrc = newaddrc;
+		nintrc = newintrc;
+		ints = imap - nintrc;
+		reg = ints - naddrc;
+	}
+	if (p == NULL)
+		printk("hmmm, int tree for %s doesn't have ctrler\n",
+		       np->full_name);
+	*irq = ints;
+	*ictrler = p;
+	return nintrc;
+}
+
+/*
+ * New version of finish_node_interrupts.
+ */
+static unsigned long
+finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+{
+	unsigned int *ints;
+	int intlen, intrcells;
+	int i, j, n, offset;
+	unsigned int *irq;
+	struct device_node *ic;
+
+	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
+	if (ints == NULL)
 		return mem_start;
-	    }
-	    /* We lookup for an interrupt-map. This code can only handle one interrupt
-	     * per device in the map. We also don't handle #address-cells in the parent
-	     * I skip the pci node itself here, may not be necessary but I don't like it's
-	     * reg property.
-	     */
-	    if (np != node)
-	        map = (unsigned int *)get_property(node, "interrupt-map", &l);
-	     else
-	     	map = NULL;
-	    if (map && l) {
-	    	int i, found, temp_isize;
-	        map_size = l>>2;
-	        map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
-	        asizep = (unsigned int *)get_property(node, "#address-cells", &l);
-	        if (asizep && l == sizeof(unsigned int))
-	            asize = *asizep;
-	        else
-	            asize = 0;
-	        found = 0;
-	        while(map_size>0 && !found) {
-	            found = 1;
-	            for (i=0; i<asize; i++) {
-	            	unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;
-	            	if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))
-	           	    found = 0;
-	           	map++;
-	           	map_size--;
-	            }
-	            for (i=0; i<isize; i++) {
-	            	unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;
-	            	if ((mask & *map) != (mask & interrupts[i]))
-	            	    found = 0;
-	            	map++;
-	            	map_size--;
-	            }
-	            parent = *((phandle *)(map));
-	            map+=1; map_size-=1;
-	            parent_node = find_phandle(parent);
-	            temp_isize = isize;
-	            if (parent_node) {
-			isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
-	    		if (isizep)
-	    		    temp_isize = *isizep;
-	            }
-	            if (!found) {
-	            	map += temp_isize;
-	            	map_size-=temp_isize;
-	            }
-	        }
-	        if (found) {
-	            node = parent_node;
-	            reg = NULL;
-	            regpsize = 0;
-	            interrupts = (unsigned int *)map;
-	            ipsize = temp_isize*1;
-		    continue;
-	        }
-	    }
-	    /* We look for an explicit interrupt-parent.
-	     */
-	    parent = (phandle *)get_property(node, "interrupt-parent", &l);
-	    if (parent && (l == sizeof(phandle)) &&
-	    	(parent_node = find_phandle(*parent))) {
-	    	node = parent_node;
-	    	continue;
-	    }
-	    /* Default, get real parent */
-	    node = node->parent;
-	} while(node);
+	intrcells = prom_n_intr_cells(np);
+	intlen /= intrcells * sizeof(unsigned int);
+	np->n_intrs = intlen;
+	np->intrs = (struct interrupt_info *) mem_start;
+	mem_start += intlen * sizeof(struct interrupt_info);
+
+	for (i = 0; i < intlen; ++i) {
+		np->intrs[i].line = 0;
+		np->intrs[i].sense = 1;
+		n = map_interrupt(&irq, &ic, np, ints, intrcells);
+		if (n <= 0)
+			continue;
+		offset = 0;
+		/*
+		 * On a CHRP we have an 8259 which is subordinate to
+		 * the openpic in the interrupt tree, but we want the
+		 * openpic's interrupt numbers offsetted, not the 8259's.
+		 * So we apply the offset if the controller is at the
+		 * root of the interrupt tree, i.e. has no interrupt-parent.
+		 * This doesn't cope with the general case of multiple
+		 * cascaded interrupt controllers, but then neither will
+		 * irq.c at the moment either.  -- paulus
+		 */
+		if (num_interrupt_controllers > 1 && ic != NULL
+		    && get_property(ic, "interrupt-parent", NULL) == NULL)
+			offset = 16;
+		np->intrs[i].line = irq[0] + offset;
+		if (n > 1)
+			np->intrs[i].sense = irq[1];
+		if (n > 2) {
+			printk("hmmm, got %d intr cells for %s:", n,
+			       np->full_name);
+			for (j = 0; j < n; ++j)
+				printk(" %d", irq[j]);
+			printk("\n");
+		}
+		ints += intrcells;
+	}
 
 	return mem_start;
 }
 
-
 /*
  * When BootX makes a copy of the device tree from the MacOS
  * Name Registry, it is in the format we use but all of the pointers
@@ -1475,7 +1585,7 @@
 		ip = (int *) get_property(np, "#address-cells", 0);
 		if (ip != NULL)
 			return *ip;
-	} while(np->parent);
+	} while (np->parent);
 	/* No #address-cells property for the root node, default to 1 */
 	return 1;
 }
@@ -1490,7 +1600,7 @@
 		ip = (int *) get_property(np, "#size-cells", 0);
 		if (ip != NULL)
 			return *ip;
-	} while(np->parent);
+	} while (np->parent);
 	/* No #size-cells property for the root node, default to 1 */
 	return 1;
 }
@@ -1502,8 +1612,7 @@
 {
 	struct address_range *adr;
 	struct pci_reg_property *pci_addrs;
-	int i, l, *ip, ml;
-	struct pci_intr_map *imp;
+	int i, l, *ip;
 
 	pci_addrs = (struct pci_reg_property *)
 		get_property(np, "assigned-addresses", &l);
@@ -1525,44 +1634,6 @@
 	if (use_of_interrupt_tree)
 		return mem_start;
 
-	/*
-	 * If the pci host bridge has an interrupt-map property,
-	 * look for our node in it.
-	 */
-	if (np->parent != 0 && pci_addrs != 0
-	    && (imp = (struct pci_intr_map *)
-		get_property(np->parent, "interrupt-map", &ml)) != 0
-	    && (ip = (int *) get_property(np, "interrupts", &l)) != 0) {
-		unsigned int devfn = pci_addrs[0].addr.a_hi & 0xff00;
-		unsigned int cell_size;
-		struct device_node* np2;
-		/* This is hackish, but is only used for BootX booting */
-		cell_size = sizeof(struct pci_intr_map);
-		np2 = np->parent;
-		while(np2) {
-			if (device_is_compatible(np2, "uni-north")) {
-				cell_size += 4;
-				break;
-			}
-			np2 = np2->parent;
-		}
-		np->n_intrs = 0;
-		np->intrs = (struct interrupt_info *) mem_start;
-		for (i = 0; (ml -= cell_size) >= 0; ++i) {
-			if (imp->addr.a_hi == devfn) {
-				np->intrs[np->n_intrs].line = imp->intr;
-				np->intrs[np->n_intrs].sense = 1; /* FIXME */
-				++np->n_intrs;
-			}
-			imp = (struct pci_intr_map *)(((unsigned int)imp)
-				+ cell_size);
-		}
-		if (np->n_intrs == 0)
-			np->intrs = 0;
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		return mem_start;
-	}
-
 	ip = (int *) get_property(np, "AAPL,interrupts", &l);
 	if (ip == 0 && np->parent)
 		ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
@@ -1677,26 +1748,10 @@
 		ip = (int *) get_property(np, "AAPL,interrupts", &l);
 	if (ip != 0) {
 		np->intrs = (struct interrupt_info *) mem_start;
-		if (_machine == _MACH_Pmac) {
-			/* for the iMac */
-			np->n_intrs = l / sizeof(int);
-			/* Hack for BootX on Core99 */
-			if (keylargo)
-				np->n_intrs = np->n_intrs/2;
-			for (i = 0; i < np->n_intrs; ++i) {
-				np->intrs[i].line = *ip++;
-				if (keylargo)
-					np->intrs[i].sense = *ip++;
-				else
-					np->intrs[i].sense = 1;
-			}
-		} else {
-			/* CHRP machines */
-			np->n_intrs = l / (2 * sizeof(int));
-			for (i = 0; i < np->n_intrs; ++i) {
-				np->intrs[i].line = openpic_to_irq(*ip++);
-				np->intrs[i].sense = *ip++;
-			}
+		np->n_intrs = l / sizeof(int);
+		for (i = 0; i < np->n_intrs; ++i) {
+			np->intrs[i].line = *ip++;
+			np->intrs[i].sense = 1;
 		}
 		mem_start += np->n_intrs * sizeof(struct interrupt_info);
 	}
@@ -1978,13 +2033,12 @@
 {
 	struct property *pp;
 
-	for (pp = np->properties; pp != 0; pp = pp->next) {
+	for (pp = np->properties; pp != 0; pp = pp->next)
 		if (pp->name != NULL && strcmp(pp->name, name) == 0) {
 			if (lenp != 0)
 				*lenp = pp->length;
 			return pp->value;
 		}
-	}
 	return 0;
 }
 
diff -urN linux-2.4.7-pre3/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.4.7-pre3/drivers/block/ll_rw_blk.c	Mon Dec  3 22:54:10 2001
+++ linux/drivers/block/ll_rw_blk.c	Mon Dec  3 22:54:19 2001
@@ -967,6 +967,7 @@
 {
 	mark_buffer_uptodate(bh, uptodate);
 	unlock_buffer(bh);
+	atomic_dec(&bh->b_count);
 }
 
 /**
@@ -1055,6 +1056,7 @@
 			continue;
 
 		/* We have the buffer lock */
+		atomic_inc(&bh->b_count);
 		bh->b_end_io = end_buffer_io_sync;
 
 		switch(rw) {
diff -urN linux-2.4.7-pre3/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- linux-2.4.7-pre3/drivers/block/ps2esdi.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/block/ps2esdi.c	Mon Dec  3 22:54:19 2001
@@ -117,6 +117,7 @@
 static char ps2esdi_valid[MAX_HD];
 static int ps2esdi_sizes[MAX_HD << 6];
 static int ps2esdi_blocksizes[MAX_HD << 6];
+static int ps2esdi_maxsect[MAX_HD << 6];
 static int ps2esdi_drives;
 static struct hd_struct ps2esdi[MAX_HD << 6];
 static u_short io_base;
diff -urN linux-2.4.7-pre3/drivers/char/serial.c linux/drivers/char/serial.c
--- linux-2.4.7-pre3/drivers/char/serial.c	Mon Dec  3 22:54:11 2001
+++ linux/drivers/char/serial.c	Mon Dec  3 22:54:19 2001
@@ -59,8 +59,8 @@
  *
  */
 
-static char *serial_version = "5.05b";
-static char *serial_revdate = "2001-05-03";
+static char *serial_version = "5.05c";
+static char *serial_revdate = "2001-07-08";
 
 /*
  * Serial driver configuration section.  Here are the various options:
@@ -3512,7 +3512,7 @@
 				      struct serial_state *state,
 				      unsigned long flags)
 {
-	unsigned char scratch, scratch2, scratch3;
+	unsigned char scratch, scratch2, scratch3, scratch4;
 
 	/*
 	 * First we check to see if it's an Oxford Semiconductor UART.
@@ -3556,17 +3556,32 @@
 	 * XR16C854.
 	 * 
 	 */
+
+	/* Save the DLL and DLM */
+
 	serial_outp(info, UART_LCR, UART_LCR_DLAB);
+	scratch3 = serial_inp(info, UART_DLL);
+	scratch4 = serial_inp(info, UART_DLM);
+
 	serial_outp(info, UART_DLL, 0);
 	serial_outp(info, UART_DLM, 0);
-	state->revision = serial_inp(info, UART_DLL);
+	scratch2 = serial_inp(info, UART_DLL);
 	scratch = serial_inp(info, UART_DLM);
 	serial_outp(info, UART_LCR, 0);
+
 	if (scratch == 0x10 || scratch == 0x14) {
+		if (scratch == 0x10)
+			state->revision = scratch2;
 		state->type = PORT_16850;
 		return;
 	}
 
+	/* Restore the DLL and DLM */
+
+	serial_outp(info, UART_LCR, UART_LCR_DLAB);
+	serial_outp(info, UART_DLL, scratch3);
+	serial_outp(info, UART_DLM, scratch4);
+	serial_outp(info, UART_LCR, 0);
 	/*
 	 * We distinguish between the '654 and the '650 by counting
 	 * how many bytes are in the FIFO.  I'm using this for now,
@@ -3979,10 +3994,7 @@
  * seems to be mainly needed on card using the PLX which also use I/O
  * mapped memory.
  */
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
 	u8 data, *p, irq_config;
@@ -4046,10 +4058,7 @@
 #define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
 #define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
 
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
        u16 data, *p;
@@ -4078,10 +4087,7 @@
 #define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
 #define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
 
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
        u8 data;
@@ -4102,10 +4108,7 @@
 }
 
 /* Added for EKF Intel i960 serial boards */
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_inteli960ni_fn(struct pci_dev *dev,
 		   struct pci_board *board,
 		   int enable)
@@ -4163,10 +4166,7 @@
 	{ 0, 0 }
 };
 
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
 	int	i, j;
@@ -4187,10 +4187,7 @@
 	return 0;
 }
 
-static int
-#ifndef MODULE
-__devinit
-#endif
+static int __devinit
 pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
 	__set_current_state(TASK_UNINTERRUPTIBLE);
diff -urN linux-2.4.7-pre3/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- linux-2.4.7-pre3/drivers/isdn/eicon/eicon.h	Sat May 19 17:54:14 2001
+++ linux/drivers/isdn/eicon/eicon.h	Mon Dec  3 22:54:19 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.23.6.3 2001/05/17 21:15:33 kai Exp $
+/* $Id: eicon.h,v 1.23.6.4 2001/06/09 15:14:16 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
diff -urN linux-2.4.7-pre3/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- linux-2.4.7-pre3/drivers/isdn/hisax/config.c	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/hisax/config.c	Mon Dec  3 22:54:19 2001
@@ -56,8 +56,8 @@
  *   26 AVM A1 PCMCIA (Fritz)   p0=irq p1=iobase
  *   27 AVM PnP/PCI 		p0=irq p1=iobase (PCI no parameter)
  *   28 Sedlbauer Speed Fax+ 	p0=irq p1=iobase (from isapnp setup)
- *   29 Siemens I-Surf          p0=irq p1=iobase p2=memory (from isapnp setup)   
- *   30 ACER P10                p0=irq p1=iobase (from isapnp setup)   
+ *   29 Siemens I-Surf          p0=irq p1=iobase p2=memory (from isapnp setup)
+ *   30 ACER P10                p0=irq p1=iobase (from isapnp setup)
  *   31 HST Saphir              p0=irq  p1=iobase
  *   32 Telekom A4T             none
  *   33 Scitel Quadro		p0=subcontroller (4*S0, subctrl 1...4)
@@ -73,16 +73,18 @@
  *
  */
 
-const char *CardType[] =
-{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
- "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
- "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
- "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
- "Compaq ISA", "NETjet-S", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
- "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
- "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
- "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
- "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
+const char *CardType[] = {
+	"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3",
+	"Creatix/Teles PnP", "AVM A1", "Elsa ML", "Elsa Quickstep",
+	"Teles PCMCIA",	"ITK ix1-micro Rev.2", "Elsa PCMCIA",
+	"Eicon.Diehl Diva", "ISDNLink",	"TeleInt", "Teles 16.3c",
+	"Sedlbauer Speed Card", "USR Sportster", "ith mic Linux",
+	"Elsa PCI", "Compaq ISA", "NETjet-S", "Teles PCI", 
+	"Sedlbauer Speed Star (PCMCIA)", "AMD 7930", "NICCY", "S0Box",
+	"AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +",
+	"Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T",
+	"Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
+	"HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
 };
 
 void HiSax_closecard(int cardnr);
@@ -90,9 +92,9 @@
 #ifdef CONFIG_HISAX_ELSA
 #define DEFAULT_CARD ISDN_CTYPE_ELSA
 #define DEFAULT_CFG {0,0,0,0}
-int elsa_init_pcmcia(void*, int, int*, int);
+int elsa_init_pcmcia(void *, int, int *, int);
 EXPORT_SYMBOL(elsa_init_pcmcia);
-#endif /* CONFIG_HISAX_ELSA */
+#endif
 
 #ifdef CONFIG_HISAX_AVM_A1
 #undef DEFAULT_CARD
@@ -106,9 +108,9 @@
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
 #define DEFAULT_CFG {11,0x170,0,0}
-int avm_a1_init_pcmcia(void*, int, int*, int);
+int avm_a1_init_pcmcia(void *, int, int *, int);
 EXPORT_SYMBOL(avm_a1_init_pcmcia);
-#endif /* CONFIG_HISAX_AVM_A1_PCMCIA */
+#endif
 
 #ifdef CONFIG_HISAX_FRITZPCI
 #undef DEFAULT_CARD
@@ -178,9 +180,9 @@
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
 #define DEFAULT_CFG {11,0x270,0,0}
-int sedl_init_pcmcia(void*, int, int*, int);
+int sedl_init_pcmcia(void *, int, int *, int);
 EXPORT_SYMBOL(sedl_init_pcmcia);
-#endif /* CONFIG_HISAX_SEDLBAUER */
+#endif
 
 #ifdef CONFIG_HISAX_SPORTSTER
 #undef DEFAULT_CARD
@@ -222,7 +224,7 @@
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_HFC_SX
 #define DEFAULT_CFG {5,0x2E0,0,0}
-int hfc_init_pcmcia(void*, int, int*, int);
+int hfc_init_pcmcia(void *, int, int *, int);
 EXPORT_SYMBOL(hfc_init_pcmcia);
 #endif
 
@@ -255,7 +257,7 @@
 #define DEFAULT_CFG {5,0x250,0,0}
 #endif
 
-#ifdef CONFIG_HISAX_BKM_A4T            
+#ifdef CONFIG_HISAX_BKM_A4T
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_BKM_A4T
@@ -327,8 +329,7 @@
 
 #define EMPTY_CARD	{0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
 
-struct IsdnCard cards[] =
-{
+struct IsdnCard cards[] = {
 	FIRST_CARD,
 	EMPTY_CARD,
 	EMPTY_CARD,
@@ -373,7 +374,7 @@
 #ifdef IO0_IO1
 MODULE_PARM(io0, "1-8i");
 MODULE_PARM(io1, "1-8i");
-#endif /* IO0_IO1 */
+#endif
 #endif /* MODULE */
 
 int nrcards;
@@ -384,8 +385,7 @@
 extern char *lli_revision;
 extern char *tei_revision;
 
-char *
-HiSax_getrev(const char *revision)
+char *HiSax_getrev(const char *revision)
 {
 	char *rev;
 	char *p;
@@ -399,8 +399,7 @@
 	return rev;
 }
 
-void __init
-HiSaxVersion(void)
+void __init HiSaxVersion(void)
 {
 	char tmp[64];
 
@@ -419,26 +418,24 @@
 	strcpy(tmp, l3_revision);
 	printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
 	strcpy(tmp, lli_revision);
-	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n",
+	       HiSax_getrev(tmp));
 	certification_check(1);
 }
 
-void
-HiSax_mod_dec_use_count(void)
+void HiSax_mod_dec_use_count(void)
 {
 	MOD_DEC_USE_COUNT;
 }
 
-void
-HiSax_mod_inc_use_count(void)
+void HiSax_mod_inc_use_count(void)
 {
 	MOD_INC_USE_COUNT;
 }
 
 #ifndef MODULE
 #define MAX_ARG	(HISAX_MAX_CARDS*5)
-static int __init
-HiSax_setup(char *line)
+static int __init HiSax_setup(char *line)
 {
 	int i, j, argc;
 	int ints[MAX_ARG + 1];
@@ -446,7 +443,7 @@
 
 	str = get_options(line, MAX_ARG, ints);
 	argc = ints[0];
-	printk(KERN_DEBUG"HiSax_setup: argc(%d) str(%s)\n", argc, str);
+	printk(KERN_DEBUG "HiSax_setup: argc(%d) str(%s)\n", argc, str);
 	i = 0;
 	j = 1;
 	while (argc && (i < HISAX_MAX_CARDS)) {
@@ -484,7 +481,7 @@
 		strcpy(HiSaxID, "HiSax");
 		HiSax_id = HiSaxID;
 	}
-	return(1);
+	return 1;
 }
 
 __setup("hisax=", HiSax_setup);
@@ -527,7 +524,7 @@
 #endif
 
 #if CARD_DIEHLDIVA
-extern	int  setup_diva(struct IsdnCard *card);
+extern int setup_diva(struct IsdnCard *card);
 #endif
 
 #if CARD_ASUSCOM
@@ -609,43 +606,41 @@
 /*
  * Find card with given driverId
  */
-static inline struct IsdnCardState
-*hisax_findcard(int driverid)
+static inline struct IsdnCardState *hisax_findcard(int driverid)
 {
 	int i;
 
 	for (i = 0; i < nrcards; i++)
 		if (cards[i].cs)
 			if (cards[i].cs->myid == driverid)
-				return (cards[i].cs);
-	return (NULL);
+				return cards[i].cs;
+	return NULL;
 }
 
 /*
  * Find card with given card number
  */
-struct IsdnCardState
-*hisax_get_card(int cardnr)
+struct IsdnCardState *hisax_get_card(int cardnr)
 {
-	if ((cardnr <= nrcards) && (cardnr>0))
-		if (cards[cardnr-1].cs)
-			return (cards[cardnr-1].cs);
-	return (NULL);
+	if ((cardnr <= nrcards) && (cardnr > 0))
+		if (cards[cardnr - 1].cs)
+			return cards[cardnr - 1].cs;
+	return NULL;
 }
 
-int
-HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
+int HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
 {
-	int count,cnt;
+	int count, cnt;
 	u_char *p = buf;
 	struct IsdnCardState *cs = hisax_findcard(id);
 
 	if (cs) {
 		if (len > HISAX_STATUS_BUFSIZE) {
-			printk(KERN_WARNING "HiSax: status overflow readstat %d/%d\n",
-				len, HISAX_STATUS_BUFSIZE);
+			printk(KERN_WARNING
+			       "HiSax: status overflow readstat %d/%d\n",
+			       len, HISAX_STATUS_BUFSIZE);
 		}
-		count = cs->status_end - cs->status_read +1;
+		count = cs->status_end - cs->status_read + 1;
 		if (count >= len)
 			count = len;
 		if (user)
@@ -673,13 +668,12 @@
 		return len;
 	} else {
 		printk(KERN_ERR
-		 "HiSax: if_readstatus called with invalid driverId!\n");
+		       "HiSax: if_readstatus called with invalid driverId!\n");
 		return -ENODEV;
 	}
 }
 
-inline int
-jiftime(char *s, long mark)
+static inline int jiftime(char *s, long mark)
 {
 	s += 8;
 
@@ -697,15 +691,15 @@
 	*s-- = mark % 10 + '0';
 	mark /= 10;
 	*s-- = mark % 10 + '0';
-	return(8);
+	return 8;
 }
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void
-VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args)
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+		      va_list args)
 {
-/* if head == NULL the fmt contains the full info */
+	/* if head == NULL the fmt contains the full info */
 
 	long flags;
 	int count, i;
@@ -729,18 +723,19 @@
 		len = strlen(fmt);
 	}
 	if (!cs) {
-		printk(KERN_WARNING "HiSax: No CardStatus for message %s", p);
+		printk(KERN_WARNING "HiSax: No CardStatus for message %s",
+		       p);
 		restore_flags(flags);
 		return;
 	}
 	if (len > HISAX_STATUS_BUFSIZE) {
 		printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
-			len, HISAX_STATUS_BUFSIZE);
+		       len, HISAX_STATUS_BUFSIZE);
 		restore_flags(flags);
 		return;
 	}
 	count = len;
-	i = cs->status_end - cs->status_write +1;
+	i = cs->status_end - cs->status_write + 1;
 	if (i >= len)
 		i = len;
 	len -= i;
@@ -754,7 +749,7 @@
 		cs->status_write += len;
 	}
 #ifdef KERNELSTACK_DEBUG
-	i = (ulong)&len - current->kernel_stack_page;
+	i = (ulong) & len - current->kernel_stack_page;
 	sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
 		current->kernel_stack_page, i);
 	len = strlen(tmpbuf);
@@ -774,8 +769,7 @@
 	}
 }
 
-void
-HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
 {
 	va_list args;
 
@@ -784,8 +778,7 @@
 	va_end(args);
 }
 
-int
-ll_run(struct IsdnCardState *cs, int addfeatures)
+int ll_run(struct IsdnCardState *cs, int addfeatures)
 {
 	long flags;
 	isdn_ctrl ic;
@@ -800,19 +793,17 @@
 	return 0;
 }
 
-void
-ll_stop(struct IsdnCardState *cs)
+void ll_stop(struct IsdnCardState *cs)
 {
 	isdn_ctrl ic;
 
 	ic.command = ISDN_STAT_STOP;
 	ic.driver = cs->myid;
 	cs->iif.statcallb(&ic);
-//	CallcFreeChan(cs);
+	//      CallcFreeChan(cs);
 }
 
-static void
-ll_unload(struct IsdnCardState *cs)
+static void ll_unload(struct IsdnCardState *cs)
 {
 	isdn_ctrl ic;
 
@@ -827,8 +818,7 @@
 	kfree(cs->dlog);
 }
 
-static void
-closecard(int cardnr)
+static void closecard(int cardnr)
 {
 	struct IsdnCardState *csta = cards[cardnr].cs;
 
@@ -856,56 +846,54 @@
 	ll_unload(csta);
 }
 
-static int __devinit
-init_card(struct IsdnCardState *cs)
+static int __devinit init_card(struct IsdnCardState *cs)
 {
 	int irq_cnt, cnt = 3;
 	long flags;
 
 	if (!cs->irq)
-		return(cs->cardmsg(cs, CARD_INIT, NULL));
+		return cs->cardmsg(cs, CARD_INIT, NULL);
 	save_flags(flags);
 	cli();
 	irq_cnt = kstat_irqs(cs->irq);
-	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
-		irq_cnt);
+	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
+	       cs->irq, irq_cnt);
 	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
-			cs->irq);
+		       cs->irq);
 		restore_flags(flags);
-		return(1);
+		return 1;
 	}
 	while (cnt) {
 		cs->cardmsg(cs, CARD_INIT, NULL);
 		sti();
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		/* Timeout 10ms */
-		schedule_timeout((10*HZ)/1000);
+		schedule_timeout((10 * HZ) / 1000);
 		restore_flags(flags);
-		printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
-			cs->irq, kstat_irqs(cs->irq));
+		printk(KERN_INFO "%s: IRQ %d count %d\n",
+		       CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
 		if (kstat_irqs(cs->irq) == irq_cnt) {
 			printk(KERN_WARNING
 			       "%s: IRQ(%d) getting no interrupts during init %d\n",
 			       CardType[cs->typ], cs->irq, 4 - cnt);
 			if (cnt == 1) {
 				free_irq(cs->irq, cs);
-				return (2);
+				return 2;
 			} else {
 				cs->cardmsg(cs, CARD_RESET, NULL);
 				cnt--;
 			}
 		} else {
 			cs->cardmsg(cs, CARD_TEST, NULL);
-			return(0);
+			return 0;
 		}
 	}
 	restore_flags(flags);
-	return(3);
+	return 3;
 }
 
-static int __devinit
-checkcard(int cardnr, char *id, int *busy_flag)
+static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
 {
 	long flags;
 	int ret = 0;
@@ -923,8 +911,8 @@
 	}
 	memset(cs, 0, sizeof(struct IsdnCardState));
 	card->cs = cs;
-	cs->chanlimit = 2; /* maximum B-channel number */
-	cs->logecho = 0; /* No echo logging */
+	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->logecho = 0;	/* No echo logging */
 	cs->cardnr = cardnr;
 	cs->debug = L1_DEB_WARN;
 	cs->HW_Flags = 0;
@@ -940,14 +928,12 @@
 
 	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
 		printk(KERN_WARNING
-		       "HiSax: Card Type %d out of range\n",
-		       card->typ);
+		       "HiSax: Card Type %d out of range\n", card->typ);
 		goto outf_cs;
 	}
 	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
 		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n",
-		       cardnr + 1);
+		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
 		goto outf_cs;
 	}
 	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
@@ -981,7 +967,7 @@
 		ISDN_FEATURE_P_NI1 |
 #endif
 		0;
-	
+
 	cs->iif.command = HiSax_command;
 	cs->iif.writecmd = NULL;
 	cs->iif.writebuf_skb = HiSax_writebuf_skb;
@@ -1092,12 +1078,12 @@
 		break;
 #endif
 #if CARD_HFC_PCI
-	case ISDN_CTYPE_HFC_PCI: 
+	case ISDN_CTYPE_HFC_PCI:
 		ret = setup_hfcpci(card);
 		break;
 #endif
 #if CARD_HFC_SX
-	case ISDN_CTYPE_HFC_SX: 
+	case ISDN_CTYPE_HFC_SX:
 		ret = setup_hfcsx(card);
 		break;
 #endif
@@ -1126,7 +1112,7 @@
 		ret = setup_testemu(card);
 		break;
 #endif
-#if	CARD_BKM_A4T       
+#if	CARD_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
 		break;
@@ -1163,8 +1149,7 @@
 		goto outf_cs;
 	}
 	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for isac rcvbuf\n");
+		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
 		ll_unload(cs);
 		goto outf_cs;
 	}
@@ -1210,8 +1195,7 @@
 	return ret;
 }
 
-void __devinit
-HiSax_shiftcards(int idx)
+void __devinit HiSax_shiftcards(int idx)
 {
 	int i;
 
@@ -1219,8 +1203,7 @@
 		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
 }
 
-int __devinit
-HiSax_inithardware(int *busy_flag)
+int __devinit HiSax_inithardware(int *busy_flag)
 {
 	int foundcards = 0;
 	int i = 0;
@@ -1254,7 +1237,8 @@
 			foundcards++;
 			i++;
 		} else {
-			printk(KERN_WARNING "HiSax: Card %s not installed !\n",
+			printk(KERN_WARNING
+			       "HiSax: Card %s not installed !\n",
 			       CardType[cards[i].typ]);
 			HiSax_shiftcards(i);
 			nrcards--;
@@ -1263,19 +1247,17 @@
 	return foundcards;
 }
 
-void
-HiSax_closecard(int cardnr)
+void HiSax_closecard(int cardnr)
 {
-	int 	i,last=nrcards - 1;
+	int i, last = nrcards - 1;
 
-	if (cardnr>last)
+	if (cardnr > last)
 		return;
 	if (cards[cardnr].cs) {
 		ll_stop(cards[cardnr].cs);
 		release_tei(cards[cardnr].cs);
-		
 		CallcFreeChan(cards[cardnr].cs);
-		
+
 		closecard(cardnr);
 		if (cards[cardnr].cs->irq)
 			free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
@@ -1283,15 +1265,14 @@
 		cards[cardnr].cs = NULL;
 	}
 	i = cardnr;
-	while (i!=last) {
-		cards[i] = cards[i+1];
+	while (i <= last) {
+		cards[i] = cards[i + 1];
 		i++;
 	}
 	nrcards--;
 }
 
-void
-HiSax_reportcard(int cardnr, int sel)
+void HiSax_reportcard(int cardnr, int sel)
 {
 	struct IsdnCardState *cs = cards[cardnr].cs;
 
@@ -1299,21 +1280,25 @@
 	printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
 	printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
 	printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
-		(ulong) & HiSax_reportcard);
+	       (ulong) & HiSax_reportcard);
 	printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
 	printk(KERN_DEBUG "HiSax: HW_Flags %lx bc0 flg %lx bc1 flg %lx\n",
-		cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
+	       cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
 	printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
-		cs->bcs[0].mode, cs->bcs[0].channel);
+	       cs->bcs[0].mode, cs->bcs[0].channel);
 	printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
-		cs->bcs[1].mode, cs->bcs[1].channel);
+	       cs->bcs[1].mode, cs->bcs[1].channel);
 #ifdef ERROR_STATISTIC
 	printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n",
-		cs->err_rx, cs->err_crc, cs->err_tx);
-	printk(KERN_DEBUG "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
-		cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc, cs->bcs[0].err_tx);
-	printk(KERN_DEBUG "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
-		cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc, cs->bcs[1].err_tx);
+	       cs->err_rx, cs->err_crc, cs->err_tx);
+	printk(KERN_DEBUG
+	       "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
+	       cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc,
+	       cs->bcs[0].err_tx);
+	printk(KERN_DEBUG
+	       "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
+	       cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc,
+	       cs->bcs[1].err_tx);
 	if (sel == 99) {
 		cs->err_rx  = 0;
 		cs->err_crc = 0;
@@ -1333,7 +1318,7 @@
 static int __init HiSax_init(void)
 {
 	int i, retval;
-#ifdef MODULE 
+#ifdef MODULE
 	int j;
 	int nzproto = 0;
 #endif
@@ -1357,7 +1342,7 @@
 
 #ifdef MODULE
 	if (!type[0]) {
-		/* We 'll register drivers later, but init basic functions*/
+		/* We 'll register drivers later, but init basic functions */
 		return 0;
 	}
 #ifdef CONFIG_HISAX_ELSA
@@ -1396,98 +1381,100 @@
 			nzproto++;
 		}
 		switch (type[i]) {
-			case ISDN_CTYPE_16_0:
-				cards[j].para[0] = irq[i];
-				cards[j].para[1] = mem[i];
-				cards[j].para[2] = io[i];
-				break;
+		case ISDN_CTYPE_16_0:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = mem[i];
+			cards[j].para[2] = io[i];
+			break;
 
-			case ISDN_CTYPE_8_0:
-				cards[j].para[0] = irq[i];
-				cards[j].para[1] = mem[i];
-				break;
+		case ISDN_CTYPE_8_0:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = mem[i];
+			break;
 
 #ifdef IO0_IO1
-			case ISDN_CTYPE_PNP:
-			case ISDN_CTYPE_NICCY:
-				cards[j].para[0] = irq[i];
-				cards[j].para[1] = io0[i];
-				cards[j].para[2] = io1[i];
-				break;
-			case ISDN_CTYPE_COMPAQ_ISA:
-				cards[j].para[0] = irq[i];
-				cards[j].para[1] = io0[i];
-				cards[j].para[2] = io1[i];
-				cards[j].para[3] = io[i];
-				break;
-#endif
-			case ISDN_CTYPE_ELSA:
-			case ISDN_CTYPE_HFC_PCI:
-				cards[j].para[0] = io[i];
-				break;
-			case ISDN_CTYPE_16_3:
-			case ISDN_CTYPE_TELESPCMCIA:
-			case ISDN_CTYPE_A1:
-			case ISDN_CTYPE_A1_PCMCIA:
-			case ISDN_CTYPE_ELSA_PNP:
-			case ISDN_CTYPE_ELSA_PCMCIA:
-			case ISDN_CTYPE_IX1MICROR2:
-			case ISDN_CTYPE_DIEHLDIVA:
-			case ISDN_CTYPE_ASUSCOM:
-			case ISDN_CTYPE_TELEINT:
-			case ISDN_CTYPE_SEDLBAUER:
-			case ISDN_CTYPE_SEDLBAUER_PCMCIA:
-			case ISDN_CTYPE_SEDLBAUER_FAX:
-			case ISDN_CTYPE_SPORTSTER:
-			case ISDN_CTYPE_MIC:
-			case ISDN_CTYPE_TELES3C:
-			case ISDN_CTYPE_ACERP10:
-			case ISDN_CTYPE_S0BOX:
-			case ISDN_CTYPE_FRITZPCI:
-			case ISDN_CTYPE_HSTSAPHIR:
-			case ISDN_CTYPE_GAZEL:
-		        case ISDN_CTYPE_HFC_SX:
-		        case ISDN_CTYPE_HFC_SP_PCMCIA:
-				cards[j].para[0] = irq[i];
-				cards[j].para[1] = io[i];
-				break;
-			case ISDN_CTYPE_ISURF:
+		case ISDN_CTYPE_PNP:
+		case ISDN_CTYPE_NICCY:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = io0[i];
+			cards[j].para[2] = io1[i];
+			break;
+		case ISDN_CTYPE_COMPAQ_ISA:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = io0[i];
+			cards[j].para[2] = io1[i];
+			cards[j].para[3] = io[i];
+			break;
+#endif
+		case ISDN_CTYPE_ELSA:
+		case ISDN_CTYPE_HFC_PCI:
+			cards[j].para[0] = io[i];
+			break;
+		case ISDN_CTYPE_16_3:
+		case ISDN_CTYPE_TELESPCMCIA:
+		case ISDN_CTYPE_A1:
+		case ISDN_CTYPE_A1_PCMCIA:
+		case ISDN_CTYPE_ELSA_PNP:
+		case ISDN_CTYPE_ELSA_PCMCIA:
+		case ISDN_CTYPE_IX1MICROR2:
+		case ISDN_CTYPE_DIEHLDIVA:
+		case ISDN_CTYPE_ASUSCOM:
+		case ISDN_CTYPE_TELEINT:
+		case ISDN_CTYPE_SEDLBAUER:
+		case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+		case ISDN_CTYPE_SEDLBAUER_FAX:
+		case ISDN_CTYPE_SPORTSTER:
+		case ISDN_CTYPE_MIC:
+		case ISDN_CTYPE_TELES3C:
+		case ISDN_CTYPE_ACERP10:
+		case ISDN_CTYPE_S0BOX:
+		case ISDN_CTYPE_FRITZPCI:
+		case ISDN_CTYPE_HSTSAPHIR:
+		case ISDN_CTYPE_GAZEL:
+		case ISDN_CTYPE_HFC_SX:
+		case ISDN_CTYPE_HFC_SP_PCMCIA:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = io[i];
+			break;
+		case ISDN_CTYPE_ISURF:
+			cards[j].para[0] = irq[i];
+			cards[j].para[1] = io[i];
+			cards[j].para[2] = mem[i];
+			break;
+		case ISDN_CTYPE_ELSA_PCI:
+		case ISDN_CTYPE_NETJET_S:
+		case ISDN_CTYPE_AMD7930:
+		case ISDN_CTYPE_TELESPCI:
+		case ISDN_CTYPE_W6692:
+		case ISDN_CTYPE_NETJET_U:
+			break;
+		case ISDN_CTYPE_BKM_A4T:
+			break;
+		case ISDN_CTYPE_SCT_QUADRO:
+			if (irq[i]) {
 				cards[j].para[0] = irq[i];
-				cards[j].para[1] = io[i];
-				cards[j].para[2] = mem[i];
-				break;
-			case ISDN_CTYPE_ELSA_PCI:
-			case ISDN_CTYPE_NETJET_S:
-			case ISDN_CTYPE_AMD7930:
-			case ISDN_CTYPE_TELESPCI:
-			case ISDN_CTYPE_W6692:
-			case ISDN_CTYPE_NETJET_U:
-				break;
-			case ISDN_CTYPE_BKM_A4T:
-	  			break;
-			case ISDN_CTYPE_SCT_QUADRO:
-				if (irq[i]) {
-					cards[j].para[0] = irq[i];
-				} else {
-				        /* QUADRO is a 4 BRI card */
-					cards[j++].para[0] = 1;
-					cards[j].typ = ISDN_CTYPE_SCT_QUADRO; 
-					cards[j].protocol = protocol[i];
-					cards[j++].para[0] = 2;
-					cards[j].typ = ISDN_CTYPE_SCT_QUADRO; 
-					cards[j].protocol = protocol[i];
-					cards[j++].para[0] = 3;
-					cards[j].typ = ISDN_CTYPE_SCT_QUADRO; 
-					cards[j].protocol = protocol[i];
-					cards[j].para[0] = 4;
-				}
-				break;
+			} else {
+				/* QUADRO is a 4 BRI card */
+				cards[j++].para[0] = 1;
+				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+				cards[j].protocol = protocol[i];
+				cards[j++].para[0] = 2;
+				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+				cards[j].protocol = protocol[i];
+				cards[j++].para[0] = 3;
+				cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+				cards[j].protocol = protocol[i];
+				cards[j].para[0] = 4;
+			}
+			break;
 		}
 		j++;
 	}
 	if (!nzproto) {
-		printk(KERN_WARNING "HiSax: Warning - no protocol specified\n");
-		printk(KERN_WARNING "HiSax: using protocol %s\n", DEFAULT_PROTO_NAME);
+		printk(KERN_WARNING
+		       "HiSax: Warning - no protocol specified\n");
+		printk(KERN_WARNING "HiSax: using protocol %s\n",
+		       DEFAULT_PROTO_NAME);
 	}
 #endif
 	if (!HiSax_id)
@@ -1505,7 +1492,7 @@
 		retval = -EIO;
 		goto out_isdnl1;
 	}
-	
+
 	return 0;
 
  out_isdnl1:
@@ -1524,12 +1511,12 @@
 
 static void __exit HiSax_exit(void)
 {
-	int cardnr = nrcards -1;
+	int cardnr = nrcards - 1;
 	long flags;
 
 	save_flags(flags);
 	cli();
-	while(cardnr>=0)
+	while (cardnr >= 0)
 		HiSax_closecard(cardnr--);
 	Isdnl1Free();
 	TeiFree();
@@ -1549,7 +1536,7 @@
 	nrcards = 0;
 	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
-	   */
+	*/
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
@@ -1559,7 +1546,7 @@
 		}
 	}
 	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int)pcm_iob;
+	cards[0].para[1] = (int) pcm_iob;
 	cards[0].protocol = prot;
 	cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA;
 
@@ -1576,7 +1563,7 @@
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
 #endif
-	return (0);
+	return 0;
 }
 #endif
 
@@ -1590,7 +1577,7 @@
 	nrcards = 0;
 	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
-	   */
+	*/
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
@@ -1601,7 +1588,7 @@
 		}
 	}
 	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int)pcm_iob;
+	cards[0].para[1] = (int) pcm_iob;
 	cards[0].protocol = prot;
 	cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA;
 	nzproto = 1;
@@ -1619,7 +1606,7 @@
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
 #endif
-	return (0);
+	return 0;
 }
 #endif
 
@@ -1633,7 +1620,7 @@
 	nrcards = 0;
 	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
-	   */
+	*/
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
@@ -1644,7 +1631,7 @@
 		}
 	}
 	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int)pcm_iob;
+	cards[0].para[1] = (int) pcm_iob;
 	cards[0].protocol = prot;
 	cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
 	nzproto = 1;
@@ -1662,7 +1649,7 @@
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
 #endif
-	return (0);
+	return 0;
 }
 #endif
 
@@ -1676,7 +1663,7 @@
 	nrcards = 0;
 	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
-	   */
+	*/
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
@@ -1687,7 +1674,7 @@
 		}
 	}
 	cards[0].para[0] = pcm_irq;
-	cards[0].para[1] = (int)pcm_iob;
+	cards[0].para[1] = (int) pcm_iob;
 	cards[0].protocol = prot;
 	cards[0].typ = ISDN_CTYPE_A1_PCMCIA;
 	nzproto = 1;
@@ -1705,11 +1692,12 @@
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
 #endif
-	return (0);
+	return 0;
 }
 #endif
 
-int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag,
+				struct IsdnCard *card)
 {
 	u_char ids[16];
 	int ret = -1;
@@ -1720,11 +1708,11 @@
 	else
 		sprintf(ids, "HiSax");
 	if (!checkcard(nrcards, ids, busy_flag)) {
-		return(-1);
+		return -1;
 	}
 	ret = nrcards;
 	nrcards++;
-	return (ret);
+	return ret;
 }
 
 #include <linux/pci.h>
diff -urN linux-2.4.7-pre3/drivers/isdn/hisax/md linux/drivers/isdn/hisax/md
--- linux-2.4.7-pre3/drivers/isdn/hisax/md	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/hisax/md	Wed Dec 31 16:00:00 1969
@@ -1,12 +0,0 @@
-6f9433a8b696076562562d090e3c420f  isac.c
-13c3eed869f5139f44c563e3a8fea1f5  isdnl1.c
-addcff863b0ff1e366c0f2ae9fa6e81e  isdnl2.c
-7076deb94a363945c21ea27aca4a720a  isdnl3.c
-51c603829b6cc4f8421f744ad657ceff  tei.c
-669050ab5079f02887ed0239d86e5474  callc.c
-e592db58630c1f1029cc064110108156  cert.c
-fadeb3b85bb23bc1ac48470c0848d6fa  l3dss1.c
-cf7dec9fac6283716904d26b99188476  l3_1tr6.c
-65d9e5471bc129624f858ebcf0743525  elsa.c
-b4cf8a4dceed9ea6dcba65a85b4eecc7  diva.c
-99e67bea8f6945fa0d4e0aded5bf0fa0  sedlbauer.c
diff -urN linux-2.4.7-pre3/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.4.7-pre3/drivers/isdn/isdn_tty.c	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/isdn_tty.c	Mon Dec  3 22:54:19 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.94.6.2 2001/06/09 15:14:15 kai Exp $
+/* $Id: isdn_tty.c,v 1.94.6.3 2001/07/03 14:48:25 kai Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -66,7 +66,7 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.94.6.2 $";
+char *isdn_tty_revision = "$Revision: 1.94.6.3 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -1420,8 +1420,7 @@
 	status = info->lsr;
 	restore_flags(flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	put_user(result, (uint *) value);
-	return 0;
+	return put_user(result, (uint *) value);
 }
 
 
@@ -1444,8 +1443,7 @@
 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	put_user(result, (uint *) value);
-	return 0;
+	return put_user(result, (uint *) value);
 }
 
 static int
@@ -1454,7 +1452,8 @@
 	uint arg;
 	int pre_dtr;
 
-	get_user(arg, (uint *) value);
+	if (get_user(arg, (uint *) value))
+		return -EFAULT;
 	switch (cmd) {
 		case TIOCMBIS:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
@@ -1522,7 +1521,6 @@
 	       uint cmd, ulong arg)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
-	int error;
 	int retval;
 
 	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl"))
@@ -1552,19 +1550,13 @@
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
 #endif
-			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
-			if (error)
-				return error;
-			put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
-			return 0;
+			return put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
 		case TIOCSSOFTCAR:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
 #endif
-			error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
-			if (error)
-				return error;
-			get_user(arg, (ulong *) arg);
+			if (get_user(arg, (ulong *) arg))
+				return -EFAULT;
 			tty->termios->c_cflag =
 			    ((tty->termios->c_cflag & ~CLOCAL) |
 			     (arg ? CLOCAL : 0));
@@ -1573,26 +1565,16 @@
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
-			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-			if (error)
-				return error;
 			return isdn_tty_get_modem_info(info, (uint *) arg);
 		case TIOCMBIS:
 		case TIOCMBIC:
 		case TIOCMSET:
-			error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
-			if (error)
-				return error;
 			return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
 		case TIOCSERGETLSR:	/* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
 #endif
-			error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-			if (error)
-				return error;
-			else
-				return isdn_tty_get_lsr_info(info, (uint *) arg);
+			return isdn_tty_get_lsr_info(info, (uint *) arg);
 		default:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 			printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
diff -urN linux-2.4.7-pre3/drivers/message/fusion/Config.in linux/drivers/message/fusion/Config.in
--- linux-2.4.7-pre3/drivers/message/fusion/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/Config.in	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,39 @@
+mainmenu_option next_comment
+comment 'Fusion MPT device support'
+
+dep_tristate "Fusion MPT (base + ScsiHost) drivers" CONFIG_FUSION $CONFIG_SCSI $CONFIG_BLK_DEV_SD
+
+if [ "$CONFIG_FUSION" = "y" -o "$CONFIG_FUSION" = "m" ]; then
+
+  if [ "$CONFIG_BLK_DEV_SD" = "y" -a "$CONFIG_FUSION" = "y" ]; then
+    define_bool CONFIG_FUSION_BOOT y
+    comment "(ability to boot linux kernel from Fusion device is ENABLED!)"
+  else
+    define_bool CONFIG_FUSION_BOOT n
+    comment "(ability to boot linux kernel from Fusion device is DISABLED!)"
+  fi
+
+  if [ "$CONFIG_MODULES" = "y" ]; then
+    #  How can we force these options to module or nothing?
+    dep_tristate "  Enhanced SCSI error reporting" CONFIG_FUSION_ISENSE $CONFIG_FUSION m
+    dep_tristate "  Fusion MPT misc device (ioctl) driver" CONFIG_FUSION_CTL $CONFIG_FUSION m
+  fi
+
+  dep_tristate "  Fusion MPT LAN driver" CONFIG_FUSION_LAN $CONFIG_FUSION $CONFIG_NET
+  if [ "$CONFIG_FUSION_LAN" != "n" ]; then
+    define_bool CONFIG_NET_FC y
+  fi
+
+else
+
+  define_bool CONFIG_FUSION_BOOT n
+  # These <should> be define_tristate, but we leave them define_bool
+  # for backward compatibility with pre-linux-2.2.15 kernels.
+  # (Bugzilla:fibrebugs, #384)
+  define_bool CONFIG_FUSION_ISENSE n
+  define_bool CONFIG_FUSION_CTL n
+  define_bool CONFIG_FUSION_LAN n
+
+fi
+
+endmenu
diff -urN linux-2.4.7-pre3/drivers/message/fusion/Makefile linux/drivers/message/fusion/Makefile
--- linux-2.4.7-pre3/drivers/message/fusion/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/Makefile	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,72 @@
+#
+# Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now inherited from the
+# parent makefile.
+#
+# Note 3! If you want to turn on various debug defines for an extended period of
+# time but don't want them lingering around in the Makefile when you pass it on 
+# to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
+
+#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
+
+#  Architecture-specific...
+#			# intel
+#EXTRA_CFLAGS += -g
+#			# sparc64
+#EXTRA_CFLAGS += -gstabs+
+
+EXTRA_CFLAGS += -I. ${MPT_CFLAGS}
+
+# Fusion MPT drivers; recognized debug defines...
+#  MPT general:
+#EXTRA_CFLAGS += -DDEBUG
+#EXTRA_CFLAGS += -DMPT_DEBUG
+#EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
+#EXTRA_CFLAGS += -DMPT_DEBUG_SPINLOCK
+# driver/module specifics...
+#  For mptbase:
+#CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE
+#CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ
+#  For {mptscsih, mptctl}:
+#CFLAGS_mptscsih.o += -DMPT_SCSI_USE_NEW_EH
+#CFLAGS_mptscsih.o += -DMPT_SCSI_CACHE_AUTOSENSE
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_SG
+#CFLAGS_mptctl.o += -DMPT_DEBUG_SG
+#  For mptlan:
+#CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG
+#  For isense:
+
+#  EXP...
+##mptscsih-objs	:= scsihost.o scsiherr.o
+
+#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
+
+O_TARGET := fusion.o
+
+export-objs	:= mptbase.o mptscsih.o mptlan.o mptctl.o isense.o
+
+# ? what's list-multi for?
+#list-multi	:= fusion.o mptscsih.o
+
+obj-$(CONFIG_FUSION)		+= mptbase.o mptscsih.o
+obj-$(CONFIG_FUSION_ISENSE)	+= isense.o
+obj-$(CONFIG_FUSION_CTL)	+= mptctl.o
+obj-$(CONFIG_FUSION_LAN)	+= mptlan.o
+
+O_OBJS		:= $(filter-out		$(export-objs), $(obj-y))
+OX_OBJS		:= $(filter		$(export-objs), $(obj-y))
+M_OBJS		:= $(sort $(filter-out	$(export-objs), $(obj-m)))
+MX_OBJS		:= $(sort $(filter	$(export-objs), $(obj-m)))
+
+include $(TOPDIR)/Rules.make
+
+
+#  EXP...
+## Fusion MPT extra's...
+##mptscsih.o: $(mptscsih-objs)
+##	$(LD) -r -o $@ $(mptscsih-objs)
diff -urN linux-2.4.7-pre3/drivers/message/fusion/ascq_tbl.c linux/drivers/message/fusion/ascq_tbl.c
--- linux-2.4.7-pre3/drivers/message/fusion/ascq_tbl.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/ascq_tbl.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,2416 @@
+#ifndef SCSI_ASCQ_TBL_C_INCLUDED
+#define SCSI_ASCQ_TBL_C_INCLUDED
+
+/* AuToMaGiCaLlY generated from: "t10.org/asc-num.txt"
+ *******************************************************************************
+ * File: ASC-NUM.TXT
+ * 
+ * SCSI ASC/ASCQ Assignments
+ * Numeric Sorted Listing
+ * as of  5/18/00
+ * 
+ *          D - DIRECT ACCESS DEVICE (SBC-2)                   device column key
+ *          .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
+ *          . L - PRINTER DEVICE (SSC)                           blank = reserved
+ *          .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
+ *          .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2)
+ *          .  . R - CD DEVICE (MMC)
+ *          .  .  S - SCANNER DEVICE (SCSI-2)
+ *          .  .  .O - OPTICAL MEMORY DEVICE (SBC-2)
+ *          .  .  . M - MEDIA CHANGER DEVICE (SMC)
+ *          .  .  .  C - COMMUNICATION DEVICE (SCSI-2)
+ *          .  .  .  .A - STORAGE ARRAY DEVICE (SCC)
+ *          .  .  .  . E - ENCLOSURE SERVICES DEVICE (SES)
+ *          .  .  .  .  B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
+ *          .  .  .  .  .K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
+ * ASC/ASCQ DTLPWRSOMCAEBK  Description
+ * -------  --------------  ----------------------------------------------------
+ */
+
+static char SenseDevTypes001[] = "DTLPWRSOMCAEBK";
+static char SenseDevTypes002[] = ".T............";
+static char SenseDevTypes003[] = ".T....S.......";
+static char SenseDevTypes004[] = ".TL...S.......";
+static char SenseDevTypes005[] = ".....R........";
+static char SenseDevTypes006[] = "DTL.WRSOM.AEBK";
+static char SenseDevTypes007[] = "D...W..O....BK";
+static char SenseDevTypes008[] = "D...WR.OM...BK";
+static char SenseDevTypes009[] = "DTL.W.SO....BK";
+static char SenseDevTypes010[] = "DTL..R.O....B.";
+static char SenseDevTypes011[] = "DT..W..OMCA.BK";
+static char SenseDevTypes012[] = "..............";
+static char SenseDevTypes013[] = "DTL.WRSOMCAEBK";
+static char SenseDevTypes014[] = "DTL.WRSOM...BK";
+static char SenseDevTypes015[] = "DT...R.OM...BK";
+static char SenseDevTypes016[] = "DTLPWRSO.C...K";
+static char SenseDevTypes017[] = "DT..WR.O....B.";
+static char SenseDevTypes018[] = "....WR.O.....K";
+static char SenseDevTypes019[] = "....WR.O......";
+static char SenseDevTypes020[] = ".T...RS.......";
+static char SenseDevTypes021[] = ".............K";
+static char SenseDevTypes022[] = "DT..W..O....B.";
+static char SenseDevTypes023[] = "DT..WRSO....BK";
+static char SenseDevTypes024[] = "DT..W.SO....BK";
+static char SenseDevTypes025[] = "....WR.O....B.";
+static char SenseDevTypes026[] = "....W..O....B.";
+static char SenseDevTypes027[] = "DT.....O....BK";
+static char SenseDevTypes028[] = "DTL.WRSO....BK";
+static char SenseDevTypes029[] = "DT..WR.O....BK";
+static char SenseDevTypes030[] = "DT..W..O....BK";
+static char SenseDevTypes031[] = "D...WR.O....BK";
+static char SenseDevTypes032[] = "D......O.....K";
+static char SenseDevTypes033[] = "D......O....BK";
+static char SenseDevTypes034[] = "DT..WR.OM...BK";
+static char SenseDevTypes035[] = "D.............";
+static char SenseDevTypes036[] = "DTLPWRSOMCAE.K";
+static char SenseDevTypes037[] = "DTLPWRSOMCA.BK";
+static char SenseDevTypes038[] = ".T...R........";
+static char SenseDevTypes039[] = "DT..WR.OM...B.";
+static char SenseDevTypes040[] = "DTL.WRSOMCAE.K";
+static char SenseDevTypes041[] = "DTLPWRSOMCAE..";
+static char SenseDevTypes042[] = "......S.......";
+static char SenseDevTypes043[] = "............B.";
+static char SenseDevTypes044[] = "DTLPWRSO.CA..K";
+static char SenseDevTypes045[] = "DT...R.......K";
+static char SenseDevTypes046[] = "D.L..R.O....B.";
+static char SenseDevTypes047[] = "..L...........";
+static char SenseDevTypes048[] = ".TL...........";
+static char SenseDevTypes049[] = "DTLPWRSOMC..BK";
+static char SenseDevTypes050[] = "DT..WR.OMCAEBK";
+static char SenseDevTypes051[] = "DT..WR.OMCAEB.";
+static char SenseDevTypes052[] = ".T...R.O......";
+static char SenseDevTypes053[] = "...P..........";
+static char SenseDevTypes054[] = "DTLPWRSOM.AE.K";
+static char SenseDevTypes055[] = "DTLPWRSOM.AE..";
+static char SenseDevTypes056[] = ".......O......";
+static char SenseDevTypes057[] = "DTLPWRSOM...BK";
+static char SenseDevTypes058[] = "DT..WR.O..A.BK";
+static char SenseDevTypes059[] = "DTLPWRSOM....K";
+static char SenseDevTypes060[] = "D......O......";
+static char SenseDevTypes061[] = ".....R......B.";
+static char SenseDevTypes062[] = "D...........B.";
+static char SenseDevTypes063[] = "............BK";
+static char SenseDevTypes064[] = "..........A...";
+
+static ASCQ_Table_t ASCQ_Table[] = {
+  {
+    0x00, 0x00,
+    SenseDevTypes001,
+    "NO ADDITIONAL SENSE INFORMATION"
+  },
+  {
+    0x00, 0x01,
+    SenseDevTypes002,
+    "FILEMARK DETECTED"
+  },
+  {
+    0x00, 0x02,
+    SenseDevTypes003,
+    "END-OF-PARTITION/MEDIUM DETECTED"
+  },
+  {
+    0x00, 0x03,
+    SenseDevTypes002,
+    "SETMARK DETECTED"
+  },
+  {
+    0x00, 0x04,
+    SenseDevTypes003,
+    "BEGINNING-OF-PARTITION/MEDIUM DETECTED"
+  },
+  {
+    0x00, 0x05,
+    SenseDevTypes004,
+    "END-OF-DATA DETECTED"
+  },
+  {
+    0x00, 0x06,
+    SenseDevTypes001,
+    "I/O PROCESS TERMINATED"
+  },
+  {
+    0x00, 0x11,
+    SenseDevTypes005,
+    "AUDIO PLAY OPERATION IN PROGRESS"
+  },
+  {
+    0x00, 0x12,
+    SenseDevTypes005,
+    "AUDIO PLAY OPERATION PAUSED"
+  },
+  {
+    0x00, 0x13,
+    SenseDevTypes005,
+    "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"
+  },
+  {
+    0x00, 0x14,
+    SenseDevTypes005,
+    "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"
+  },
+  {
+    0x00, 0x15,
+    SenseDevTypes005,
+    "NO CURRENT AUDIO STATUS TO RETURN"
+  },
+  {
+    0x00, 0x16,
+    SenseDevTypes001,
+    "OPERATION IN PROGRESS"
+  },
+  {
+    0x00, 0x17,
+    SenseDevTypes006,
+    "CLEANING REQUESTED"
+  },
+  {
+    0x01, 0x00,
+    SenseDevTypes007,
+    "NO INDEX/SECTOR SIGNAL"
+  },
+  {
+    0x02, 0x00,
+    SenseDevTypes008,
+    "NO SEEK COMPLETE"
+  },
+  {
+    0x03, 0x00,
+    SenseDevTypes009,
+    "PERIPHERAL DEVICE WRITE FAULT"
+  },
+  {
+    0x03, 0x01,
+    SenseDevTypes002,
+    "NO WRITE CURRENT"
+  },
+  {
+    0x03, 0x02,
+    SenseDevTypes002,
+    "EXCESSIVE WRITE ERRORS"
+  },
+  {
+    0x04, 0x00,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"
+  },
+  {
+    0x04, 0x01,
+    SenseDevTypes001,
+    "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"
+  },
+  {
+    0x04, 0x02,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
+  },
+  {
+    0x04, 0x03,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"
+  },
+  {
+    0x04, 0x04,
+    SenseDevTypes010,
+    "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"
+  },
+  {
+    0x04, 0x05,
+    SenseDevTypes011,
+    "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"
+  },
+  {
+    0x04, 0x06,
+    SenseDevTypes011,
+    "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"
+  },
+  {
+    0x04, 0x07,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"
+  },
+  {
+    0x04, 0x08,
+    SenseDevTypes005,
+    "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"
+  },
+  {
+    0x04, 0x09,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS"
+  },
+  {
+    0x04, 0x10,
+    SenseDevTypes012,
+    "auxiliary memory code 2 (99-148) [proposed]"
+  },
+  {
+    0x05, 0x00,
+    SenseDevTypes013,
+    "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"
+  },
+  {
+    0x06, 0x00,
+    SenseDevTypes008,
+    "NO REFERENCE POSITION FOUND"
+  },
+  {
+    0x07, 0x00,
+    SenseDevTypes014,
+    "MULTIPLE PERIPHERAL DEVICES SELECTED"
+  },
+  {
+    0x08, 0x00,
+    SenseDevTypes013,
+    "LOGICAL UNIT COMMUNICATION FAILURE"
+  },
+  {
+    0x08, 0x01,
+    SenseDevTypes013,
+    "LOGICAL UNIT COMMUNICATION TIME-OUT"
+  },
+  {
+    0x08, 0x02,
+    SenseDevTypes013,
+    "LOGICAL UNIT COMMUNICATION PARITY ERROR"
+  },
+  {
+    0x08, 0x03,
+    SenseDevTypes015,
+    "LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)"
+  },
+  {
+    0x08, 0x04,
+    SenseDevTypes016,
+    "UNREACHABLE COPY TARGET"
+  },
+  {
+    0x09, 0x00,
+    SenseDevTypes017,
+    "TRACK FOLLOWING ERROR"
+  },
+  {
+    0x09, 0x01,
+    SenseDevTypes018,
+    "TRACKING SERVO FAILURE"
+  },
+  {
+    0x09, 0x02,
+    SenseDevTypes018,
+    "FOCUS SERVO FAILURE"
+  },
+  {
+    0x09, 0x03,
+    SenseDevTypes019,
+    "SPINDLE SERVO FAILURE"
+  },
+  {
+    0x09, 0x04,
+    SenseDevTypes017,
+    "HEAD SELECT FAULT"
+  },
+  {
+    0x0A, 0x00,
+    SenseDevTypes001,
+    "ERROR LOG OVERFLOW"
+  },
+  {
+    0x0B, 0x00,
+    SenseDevTypes001,
+    "WARNING"
+  },
+  {
+    0x0B, 0x01,
+    SenseDevTypes001,
+    "WARNING - SPECIFIED TEMPERATURE EXCEEDED"
+  },
+  {
+    0x0B, 0x02,
+    SenseDevTypes001,
+    "WARNING - ENCLOSURE DEGRADED"
+  },
+  {
+    0x0C, 0x00,
+    SenseDevTypes020,
+    "WRITE ERROR"
+  },
+  {
+    0x0C, 0x01,
+    SenseDevTypes021,
+    "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"
+  },
+  {
+    0x0C, 0x02,
+    SenseDevTypes007,
+    "WRITE ERROR - AUTO REALLOCATION FAILED"
+  },
+  {
+    0x0C, 0x03,
+    SenseDevTypes007,
+    "WRITE ERROR - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x0C, 0x04,
+    SenseDevTypes022,
+    "COMPRESSION CHECK MISCOMPARE ERROR"
+  },
+  {
+    0x0C, 0x05,
+    SenseDevTypes022,
+    "DATA EXPANSION OCCURRED DURING COMPRESSION"
+  },
+  {
+    0x0C, 0x06,
+    SenseDevTypes022,
+    "BLOCK NOT COMPRESSIBLE"
+  },
+  {
+    0x0C, 0x07,
+    SenseDevTypes005,
+    "WRITE ERROR - RECOVERY NEEDED"
+  },
+  {
+    0x0C, 0x08,
+    SenseDevTypes005,
+    "WRITE ERROR - RECOVERY FAILED"
+  },
+  {
+    0x0C, 0x09,
+    SenseDevTypes005,
+    "WRITE ERROR - LOSS OF STREAMING"
+  },
+  {
+    0x0C, 0x0A,
+    SenseDevTypes005,
+    "WRITE ERROR - PADDING BLOCKS ADDED"
+  },
+  {
+    0x0C, 0x0B,
+    SenseDevTypes012,
+    "auxiliary memory code 4 (99-148) [proposed]"
+  },
+  {
+    0x10, 0x00,
+    SenseDevTypes007,
+    "ID CRC OR ECC ERROR"
+  },
+  {
+    0x11, 0x00,
+    SenseDevTypes023,
+    "UNRECOVERED READ ERROR"
+  },
+  {
+    0x11, 0x01,
+    SenseDevTypes023,
+    "READ RETRIES EXHAUSTED"
+  },
+  {
+    0x11, 0x02,
+    SenseDevTypes023,
+    "ERROR TOO LONG TO CORRECT"
+  },
+  {
+    0x11, 0x03,
+    SenseDevTypes024,
+    "MULTIPLE READ ERRORS"
+  },
+  {
+    0x11, 0x04,
+    SenseDevTypes007,
+    "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"
+  },
+  {
+    0x11, 0x05,
+    SenseDevTypes025,
+    "L-EC UNCORRECTABLE ERROR"
+  },
+  {
+    0x11, 0x06,
+    SenseDevTypes025,
+    "CIRC UNRECOVERED ERROR"
+  },
+  {
+    0x11, 0x07,
+    SenseDevTypes026,
+    "DATA RE-SYNCHRONIZATION ERROR"
+  },
+  {
+    0x11, 0x08,
+    SenseDevTypes002,
+    "INCOMPLETE BLOCK READ"
+  },
+  {
+    0x11, 0x09,
+    SenseDevTypes002,
+    "NO GAP FOUND"
+  },
+  {
+    0x11, 0x0A,
+    SenseDevTypes027,
+    "MISCORRECTED ERROR"
+  },
+  {
+    0x11, 0x0B,
+    SenseDevTypes007,
+    "UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x11, 0x0C,
+    SenseDevTypes007,
+    "UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA"
+  },
+  {
+    0x11, 0x0D,
+    SenseDevTypes017,
+    "DE-COMPRESSION CRC ERROR"
+  },
+  {
+    0x11, 0x0E,
+    SenseDevTypes017,
+    "CANNOT DECOMPRESS USING DECLARED ALGORITHM"
+  },
+  {
+    0x11, 0x0F,
+    SenseDevTypes005,
+    "ERROR READING UPC/EAN NUMBER"
+  },
+  {
+    0x11, 0x10,
+    SenseDevTypes005,
+    "ERROR READING ISRC NUMBER"
+  },
+  {
+    0x11, 0x11,
+    SenseDevTypes005,
+    "READ ERROR - LOSS OF STREAMING"
+  },
+  {
+    0x11, 0x12,
+    SenseDevTypes012,
+    "auxiliary memory code 3 (99-148) [proposed]"
+  },
+  {
+    0x12, 0x00,
+    SenseDevTypes007,
+    "ADDRESS MARK NOT FOUND FOR ID FIELD"
+  },
+  {
+    0x13, 0x00,
+    SenseDevTypes007,
+    "ADDRESS MARK NOT FOUND FOR DATA FIELD"
+  },
+  {
+    0x14, 0x00,
+    SenseDevTypes028,
+    "RECORDED ENTITY NOT FOUND"
+  },
+  {
+    0x14, 0x01,
+    SenseDevTypes029,
+    "RECORD NOT FOUND"
+  },
+  {
+    0x14, 0x02,
+    SenseDevTypes002,
+    "FILEMARK OR SETMARK NOT FOUND"
+  },
+  {
+    0x14, 0x03,
+    SenseDevTypes002,
+    "END-OF-DATA NOT FOUND"
+  },
+  {
+    0x14, 0x04,
+    SenseDevTypes002,
+    "BLOCK SEQUENCE ERROR"
+  },
+  {
+    0x14, 0x05,
+    SenseDevTypes030,
+    "RECORD NOT FOUND - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x14, 0x06,
+    SenseDevTypes030,
+    "RECORD NOT FOUND - DATA AUTO-REALLOCATED"
+  },
+  {
+    0x15, 0x00,
+    SenseDevTypes014,
+    "RANDOM POSITIONING ERROR"
+  },
+  {
+    0x15, 0x01,
+    SenseDevTypes014,
+    "MECHANICAL POSITIONING ERROR"
+  },
+  {
+    0x15, 0x02,
+    SenseDevTypes029,
+    "POSITIONING ERROR DETECTED BY READ OF MEDIUM"
+  },
+  {
+    0x16, 0x00,
+    SenseDevTypes007,
+    "DATA SYNCHRONIZATION MARK ERROR"
+  },
+  {
+    0x16, 0x01,
+    SenseDevTypes007,
+    "DATA SYNC ERROR - DATA REWRITTEN"
+  },
+  {
+    0x16, 0x02,
+    SenseDevTypes007,
+    "DATA SYNC ERROR - RECOMMEND REWRITE"
+  },
+  {
+    0x16, 0x03,
+    SenseDevTypes007,
+    "DATA SYNC ERROR - DATA AUTO-REALLOCATED"
+  },
+  {
+    0x16, 0x04,
+    SenseDevTypes007,
+    "DATA SYNC ERROR - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x17, 0x00,
+    SenseDevTypes023,
+    "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"
+  },
+  {
+    0x17, 0x01,
+    SenseDevTypes023,
+    "RECOVERED DATA WITH RETRIES"
+  },
+  {
+    0x17, 0x02,
+    SenseDevTypes029,
+    "RECOVERED DATA WITH POSITIVE HEAD OFFSET"
+  },
+  {
+    0x17, 0x03,
+    SenseDevTypes029,
+    "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"
+  },
+  {
+    0x17, 0x04,
+    SenseDevTypes025,
+    "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"
+  },
+  {
+    0x17, 0x05,
+    SenseDevTypes031,
+    "RECOVERED DATA USING PREVIOUS SECTOR ID"
+  },
+  {
+    0x17, 0x06,
+    SenseDevTypes007,
+    "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"
+  },
+  {
+    0x17, 0x07,
+    SenseDevTypes031,
+    "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x17, 0x08,
+    SenseDevTypes031,
+    "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE"
+  },
+  {
+    0x17, 0x09,
+    SenseDevTypes031,
+    "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"
+  },
+  {
+    0x18, 0x00,
+    SenseDevTypes029,
+    "RECOVERED DATA WITH ERROR CORRECTION APPLIED"
+  },
+  {
+    0x18, 0x01,
+    SenseDevTypes031,
+    "RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED"
+  },
+  {
+    0x18, 0x02,
+    SenseDevTypes031,
+    "RECOVERED DATA - DATA AUTO-REALLOCATED"
+  },
+  {
+    0x18, 0x03,
+    SenseDevTypes005,
+    "RECOVERED DATA WITH CIRC"
+  },
+  {
+    0x18, 0x04,
+    SenseDevTypes005,
+    "RECOVERED DATA WITH L-EC"
+  },
+  {
+    0x18, 0x05,
+    SenseDevTypes031,
+    "RECOVERED DATA - RECOMMEND REASSIGNMENT"
+  },
+  {
+    0x18, 0x06,
+    SenseDevTypes031,
+    "RECOVERED DATA - RECOMMEND REWRITE"
+  },
+  {
+    0x18, 0x07,
+    SenseDevTypes007,
+    "RECOVERED DATA WITH ECC - DATA REWRITTEN"
+  },
+  {
+    0x19, 0x00,
+    SenseDevTypes032,
+    "DEFECT LIST ERROR"
+  },
+  {
+    0x19, 0x01,
+    SenseDevTypes032,
+    "DEFECT LIST NOT AVAILABLE"
+  },
+  {
+    0x19, 0x02,
+    SenseDevTypes032,
+    "DEFECT LIST ERROR IN PRIMARY LIST"
+  },
+  {
+    0x19, 0x03,
+    SenseDevTypes032,
+    "DEFECT LIST ERROR IN GROWN LIST"
+  },
+  {
+    0x1A, 0x00,
+    SenseDevTypes001,
+    "PARAMETER LIST LENGTH ERROR"
+  },
+  {
+    0x1B, 0x00,
+    SenseDevTypes001,
+    "SYNCHRONOUS DATA TRANSFER ERROR"
+  },
+  {
+    0x1C, 0x00,
+    SenseDevTypes033,
+    "DEFECT LIST NOT FOUND"
+  },
+  {
+    0x1C, 0x01,
+    SenseDevTypes033,
+    "PRIMARY DEFECT LIST NOT FOUND"
+  },
+  {
+    0x1C, 0x02,
+    SenseDevTypes033,
+    "GROWN DEFECT LIST NOT FOUND"
+  },
+  {
+    0x1D, 0x00,
+    SenseDevTypes029,
+    "MISCOMPARE DURING VERIFY OPERATION"
+  },
+  {
+    0x1E, 0x00,
+    SenseDevTypes007,
+    "RECOVERED ID WITH ECC CORRECTION"
+  },
+  {
+    0x1F, 0x00,
+    SenseDevTypes032,
+    "PARTIAL DEFECT LIST TRANSFER"
+  },
+  {
+    0x20, 0x00,
+    SenseDevTypes001,
+    "INVALID COMMAND OPERATION CODE"
+  },
+  {
+    0x20, 0x01,
+    SenseDevTypes012,
+    "access controls code 1 (99-314) [proposed]"
+  },
+  {
+    0x20, 0x02,
+    SenseDevTypes012,
+    "access controls code 2 (99-314) [proposed]"
+  },
+  {
+    0x20, 0x03,
+    SenseDevTypes012,
+    "access controls code 3 (99-314) [proposed]"
+  },
+  {
+    0x21, 0x00,
+    SenseDevTypes034,
+    "LOGICAL BLOCK ADDRESS OUT OF RANGE"
+  },
+  {
+    0x21, 0x01,
+    SenseDevTypes034,
+    "INVALID ELEMENT ADDRESS"
+  },
+  {
+    0x22, 0x00,
+    SenseDevTypes035,
+    "ILLEGAL FUNCTION (USE 20 00, 24 00, OR 26 00)"
+  },
+  {
+    0x24, 0x00,
+    SenseDevTypes001,
+    "INVALID FIELD IN CDB"
+  },
+  {
+    0x24, 0x01,
+    SenseDevTypes001,
+    "CDB DECRYPTION ERROR"
+  },
+  {
+    0x25, 0x00,
+    SenseDevTypes001,
+    "LOGICAL UNIT NOT SUPPORTED"
+  },
+  {
+    0x26, 0x00,
+    SenseDevTypes001,
+    "INVALID FIELD IN PARAMETER LIST"
+  },
+  {
+    0x26, 0x01,
+    SenseDevTypes001,
+    "PARAMETER NOT SUPPORTED"
+  },
+  {
+    0x26, 0x02,
+    SenseDevTypes001,
+    "PARAMETER VALUE INVALID"
+  },
+  {
+    0x26, 0x03,
+    SenseDevTypes036,
+    "THRESHOLD PARAMETERS NOT SUPPORTED"
+  },
+  {
+    0x26, 0x04,
+    SenseDevTypes001,
+    "INVALID RELEASE OF PERSISTENT RESERVATION"
+  },
+  {
+    0x26, 0x05,
+    SenseDevTypes037,
+    "DATA DECRYPTION ERROR"
+  },
+  {
+    0x26, 0x06,
+    SenseDevTypes016,
+    "TOO MANY TARGET DESCRIPTORS"
+  },
+  {
+    0x26, 0x07,
+    SenseDevTypes016,
+    "UNSUPPORTED TARGET DESCRIPTOR TYPE CODE"
+  },
+  {
+    0x26, 0x08,
+    SenseDevTypes016,
+    "TOO MANY SEGMENT DESCRIPTORS"
+  },
+  {
+    0x26, 0x09,
+    SenseDevTypes016,
+    "UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE"
+  },
+  {
+    0x26, 0x0A,
+    SenseDevTypes016,
+    "UNEXPECTED INEXACT SEGMENT"
+  },
+  {
+    0x26, 0x0B,
+    SenseDevTypes016,
+    "INLINE DATA LENGTH EXCEEDED"
+  },
+  {
+    0x26, 0x0C,
+    SenseDevTypes016,
+    "INVALID OPERATION FOR COPY SOURCE OR DESTINATION"
+  },
+  {
+    0x26, 0x0D,
+    SenseDevTypes016,
+    "COPY SEGMENT GRANULARITY VIOLATION"
+  },
+  {
+    0x27, 0x00,
+    SenseDevTypes029,
+    "WRITE PROTECTED"
+  },
+  {
+    0x27, 0x01,
+    SenseDevTypes029,
+    "HARDWARE WRITE PROTECTED"
+  },
+  {
+    0x27, 0x02,
+    SenseDevTypes029,
+    "LOGICAL UNIT SOFTWARE WRITE PROTECTED"
+  },
+  {
+    0x27, 0x03,
+    SenseDevTypes038,
+    "ASSOCIATED WRITE PROTECT"
+  },
+  {
+    0x27, 0x04,
+    SenseDevTypes038,
+    "PERSISTENT WRITE PROTECT"
+  },
+  {
+    0x27, 0x05,
+    SenseDevTypes038,
+    "PERMANENT WRITE PROTECT"
+  },
+  {
+    0x28, 0x00,
+    SenseDevTypes001,
+    "NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED"
+  },
+  {
+    0x28, 0x01,
+    SenseDevTypes039,
+    "IMPORT OR EXPORT ELEMENT ACCESSED"
+  },
+  {
+    0x29, 0x00,
+    SenseDevTypes001,
+    "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
+  },
+  {
+    0x29, 0x01,
+    SenseDevTypes001,
+    "POWER ON OCCURRED"
+  },
+  {
+    0x29, 0x02,
+    SenseDevTypes001,
+    "SCSI BUS RESET OCCURRED"
+  },
+  {
+    0x29, 0x03,
+    SenseDevTypes001,
+    "BUS DEVICE RESET FUNCTION OCCURRED"
+  },
+  {
+    0x29, 0x04,
+    SenseDevTypes001,
+    "DEVICE INTERNAL RESET"
+  },
+  {
+    0x29, 0x05,
+    SenseDevTypes001,
+    "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED"
+  },
+  {
+    0x29, 0x06,
+    SenseDevTypes001,
+    "TRANSCEIVER MODE CHANGED TO LVD"
+  },
+  {
+    0x2A, 0x00,
+    SenseDevTypes013,
+    "PARAMETERS CHANGED"
+  },
+  {
+    0x2A, 0x01,
+    SenseDevTypes013,
+    "MODE PARAMETERS CHANGED"
+  },
+  {
+    0x2A, 0x02,
+    SenseDevTypes040,
+    "LOG PARAMETERS CHANGED"
+  },
+  {
+    0x2A, 0x03,
+    SenseDevTypes036,
+    "RESERVATIONS PREEMPTED"
+  },
+  {
+    0x2A, 0x04,
+    SenseDevTypes041,
+    "RESERVATIONS RELEASED"
+  },
+  {
+    0x2A, 0x05,
+    SenseDevTypes041,
+    "REGISTRATIONS PREEMPTED"
+  },
+  {
+    0x2B, 0x00,
+    SenseDevTypes016,
+    "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"
+  },
+  {
+    0x2C, 0x00,
+    SenseDevTypes001,
+    "COMMAND SEQUENCE ERROR"
+  },
+  {
+    0x2C, 0x01,
+    SenseDevTypes042,
+    "TOO MANY WINDOWS SPECIFIED"
+  },
+  {
+    0x2C, 0x02,
+    SenseDevTypes042,
+    "INVALID COMBINATION OF WINDOWS SPECIFIED"
+  },
+  {
+    0x2C, 0x03,
+    SenseDevTypes005,
+    "CURRENT PROGRAM AREA IS NOT EMPTY"
+  },
+  {
+    0x2C, 0x04,
+    SenseDevTypes005,
+    "CURRENT PROGRAM AREA IS EMPTY"
+  },
+  {
+    0x2C, 0x05,
+    SenseDevTypes043,
+    "ILLEGAL POWER CONDITION REQUEST"
+  },
+  {
+    0x2D, 0x00,
+    SenseDevTypes002,
+    "OVERWRITE ERROR ON UPDATE IN PLACE"
+  },
+  {
+    0x2E, 0x00,
+    SenseDevTypes044,
+    "ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR"
+  },
+  {
+    0x2E, 0x01,
+    SenseDevTypes044,
+    "THIRD PARTY DEVICE FAILURE"
+  },
+  {
+    0x2E, 0x02,
+    SenseDevTypes044,
+    "COPY TARGET DEVICE NOT REACHABLE"
+  },
+  {
+    0x2E, 0x03,
+    SenseDevTypes044,
+    "INCORRECT COPY TARGET DEVICE TYPE"
+  },
+  {
+    0x2E, 0x04,
+    SenseDevTypes044,
+    "COPY TARGET DEVICE DATA UNDERRUN"
+  },
+  {
+    0x2E, 0x05,
+    SenseDevTypes044,
+    "COPY TARGET DEVICE DATA OVERRUN"
+  },
+  {
+    0x2F, 0x00,
+    SenseDevTypes001,
+    "COMMANDS CLEARED BY ANOTHER INITIATOR"
+  },
+  {
+    0x30, 0x00,
+    SenseDevTypes034,
+    "INCOMPATIBLE MEDIUM INSTALLED"
+  },
+  {
+    0x30, 0x01,
+    SenseDevTypes029,
+    "CANNOT READ MEDIUM - UNKNOWN FORMAT"
+  },
+  {
+    0x30, 0x02,
+    SenseDevTypes029,
+    "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"
+  },
+  {
+    0x30, 0x03,
+    SenseDevTypes045,
+    "CLEANING CARTRIDGE INSTALLED"
+  },
+  {
+    0x30, 0x04,
+    SenseDevTypes029,
+    "CANNOT WRITE MEDIUM - UNKNOWN FORMAT"
+  },
+  {
+    0x30, 0x05,
+    SenseDevTypes029,
+    "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"
+  },
+  {
+    0x30, 0x06,
+    SenseDevTypes017,
+    "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"
+  },
+  {
+    0x30, 0x07,
+    SenseDevTypes006,
+    "CLEANING FAILURE"
+  },
+  {
+    0x30, 0x08,
+    SenseDevTypes005,
+    "CANNOT WRITE - APPLICATION CODE MISMATCH"
+  },
+  {
+    0x30, 0x09,
+    SenseDevTypes005,
+    "CURRENT SESSION NOT FIXATED FOR APPEND"
+  },
+  {
+    0x31, 0x00,
+    SenseDevTypes029,
+    "MEDIUM FORMAT CORRUPTED"
+  },
+  {
+    0x31, 0x01,
+    SenseDevTypes046,
+    "FORMAT COMMAND FAILED"
+  },
+  {
+    0x32, 0x00,
+    SenseDevTypes007,
+    "NO DEFECT SPARE LOCATION AVAILABLE"
+  },
+  {
+    0x32, 0x01,
+    SenseDevTypes007,
+    "DEFECT LIST UPDATE FAILURE"
+  },
+  {
+    0x33, 0x00,
+    SenseDevTypes002,
+    "TAPE LENGTH ERROR"
+  },
+  {
+    0x34, 0x00,
+    SenseDevTypes001,
+    "ENCLOSURE FAILURE"
+  },
+  {
+    0x35, 0x00,
+    SenseDevTypes001,
+    "ENCLOSURE SERVICES FAILURE"
+  },
+  {
+    0x35, 0x01,
+    SenseDevTypes001,
+    "UNSUPPORTED ENCLOSURE FUNCTION"
+  },
+  {
+    0x35, 0x02,
+    SenseDevTypes001,
+    "ENCLOSURE SERVICES UNAVAILABLE"
+  },
+  {
+    0x35, 0x03,
+    SenseDevTypes001,
+    "ENCLOSURE SERVICES TRANSFER FAILURE"
+  },
+  {
+    0x35, 0x04,
+    SenseDevTypes001,
+    "ENCLOSURE SERVICES TRANSFER REFUSED"
+  },
+  {
+    0x36, 0x00,
+    SenseDevTypes047,
+    "RIBBON, INK, OR TONER FAILURE"
+  },
+  {
+    0x37, 0x00,
+    SenseDevTypes013,
+    "ROUNDED PARAMETER"
+  },
+  {
+    0x38, 0x00,
+    SenseDevTypes043,
+    "EVENT STATUS NOTIFICATION"
+  },
+  {
+    0x38, 0x02,
+    SenseDevTypes043,
+    "ESN - POWER MANAGEMENT CLASS EVENT"
+  },
+  {
+    0x38, 0x04,
+    SenseDevTypes043,
+    "ESN - MEDIA CLASS EVENT"
+  },
+  {
+    0x38, 0x06,
+    SenseDevTypes043,
+    "ESN - DEVICE BUSY CLASS EVENT"
+  },
+  {
+    0x39, 0x00,
+    SenseDevTypes040,
+    "SAVING PARAMETERS NOT SUPPORTED"
+  },
+  {
+    0x3A, 0x00,
+    SenseDevTypes014,
+    "MEDIUM NOT PRESENT"
+  },
+  {
+    0x3A, 0x01,
+    SenseDevTypes034,
+    "MEDIUM NOT PRESENT - TRAY CLOSED"
+  },
+  {
+    0x3A, 0x02,
+    SenseDevTypes034,
+    "MEDIUM NOT PRESENT - TRAY OPEN"
+  },
+  {
+    0x3A, 0x03,
+    SenseDevTypes039,
+    "MEDIUM NOT PRESENT - LOADABLE"
+  },
+  {
+    0x3A, 0x04,
+    SenseDevTypes039,
+    "MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE"
+  },
+  {
+    0x3B, 0x00,
+    SenseDevTypes048,
+    "SEQUENTIAL POSITIONING ERROR"
+  },
+  {
+    0x3B, 0x01,
+    SenseDevTypes002,
+    "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"
+  },
+  {
+    0x3B, 0x02,
+    SenseDevTypes002,
+    "TAPE POSITION ERROR AT END-OF-MEDIUM"
+  },
+  {
+    0x3B, 0x03,
+    SenseDevTypes047,
+    "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"
+  },
+  {
+    0x3B, 0x04,
+    SenseDevTypes047,
+    "SLEW FAILURE"
+  },
+  {
+    0x3B, 0x05,
+    SenseDevTypes047,
+    "PAPER JAM"
+  },
+  {
+    0x3B, 0x06,
+    SenseDevTypes047,
+    "FAILED TO SENSE TOP-OF-FORM"
+  },
+  {
+    0x3B, 0x07,
+    SenseDevTypes047,
+    "FAILED TO SENSE BOTTOM-OF-FORM"
+  },
+  {
+    0x3B, 0x08,
+    SenseDevTypes002,
+    "REPOSITION ERROR"
+  },
+  {
+    0x3B, 0x09,
+    SenseDevTypes042,
+    "READ PAST END OF MEDIUM"
+  },
+  {
+    0x3B, 0x0A,
+    SenseDevTypes042,
+    "READ PAST BEGINNING OF MEDIUM"
+  },
+  {
+    0x3B, 0x0B,
+    SenseDevTypes042,
+    "POSITION PAST END OF MEDIUM"
+  },
+  {
+    0x3B, 0x0C,
+    SenseDevTypes003,
+    "POSITION PAST BEGINNING OF MEDIUM"
+  },
+  {
+    0x3B, 0x0D,
+    SenseDevTypes034,
+    "MEDIUM DESTINATION ELEMENT FULL"
+  },
+  {
+    0x3B, 0x0E,
+    SenseDevTypes034,
+    "MEDIUM SOURCE ELEMENT EMPTY"
+  },
+  {
+    0x3B, 0x0F,
+    SenseDevTypes005,
+    "END OF MEDIUM REACHED"
+  },
+  {
+    0x3B, 0x11,
+    SenseDevTypes034,
+    "MEDIUM MAGAZINE NOT ACCESSIBLE"
+  },
+  {
+    0x3B, 0x12,
+    SenseDevTypes034,
+    "MEDIUM MAGAZINE REMOVED"
+  },
+  {
+    0x3B, 0x13,
+    SenseDevTypes034,
+    "MEDIUM MAGAZINE INSERTED"
+  },
+  {
+    0x3B, 0x14,
+    SenseDevTypes034,
+    "MEDIUM MAGAZINE LOCKED"
+  },
+  {
+    0x3B, 0x15,
+    SenseDevTypes034,
+    "MEDIUM MAGAZINE UNLOCKED"
+  },
+  {
+    0x3B, 0x16,
+    SenseDevTypes005,
+    "MECHANICAL POSITIONING OR CHANGER ERROR"
+  },
+  {
+    0x3D, 0x00,
+    SenseDevTypes036,
+    "INVALID BITS IN IDENTIFY MESSAGE"
+  },
+  {
+    0x3E, 0x00,
+    SenseDevTypes001,
+    "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"
+  },
+  {
+    0x3E, 0x01,
+    SenseDevTypes001,
+    "LOGICAL UNIT FAILURE"
+  },
+  {
+    0x3E, 0x02,
+    SenseDevTypes001,
+    "TIMEOUT ON LOGICAL UNIT"
+  },
+  {
+    0x3E, 0x03,
+    SenseDevTypes001,
+    "LOGICAL UNIT FAILED SELF-TEST"
+  },
+  {
+    0x3E, 0x04,
+    SenseDevTypes001,
+    "LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG"
+  },
+  {
+    0x3F, 0x00,
+    SenseDevTypes001,
+    "TARGET OPERATING CONDITIONS HAVE CHANGED"
+  },
+  {
+    0x3F, 0x01,
+    SenseDevTypes001,
+    "MICROCODE HAS BEEN CHANGED"
+  },
+  {
+    0x3F, 0x02,
+    SenseDevTypes049,
+    "CHANGED OPERATING DEFINITION"
+  },
+  {
+    0x3F, 0x03,
+    SenseDevTypes001,
+    "INQUIRY DATA HAS CHANGED"
+  },
+  {
+    0x3F, 0x04,
+    SenseDevTypes050,
+    "COMPONENT DEVICE ATTACHED"
+  },
+  {
+    0x3F, 0x05,
+    SenseDevTypes050,
+    "DEVICE IDENTIFIER CHANGED"
+  },
+  {
+    0x3F, 0x06,
+    SenseDevTypes051,
+    "REDUNDANCY GROUP CREATED OR MODIFIED"
+  },
+  {
+    0x3F, 0x07,
+    SenseDevTypes051,
+    "REDUNDANCY GROUP DELETED"
+  },
+  {
+    0x3F, 0x08,
+    SenseDevTypes051,
+    "SPARE CREATED OR MODIFIED"
+  },
+  {
+    0x3F, 0x09,
+    SenseDevTypes051,
+    "SPARE DELETED"
+  },
+  {
+    0x3F, 0x0A,
+    SenseDevTypes050,
+    "VOLUME SET CREATED OR MODIFIED"
+  },
+  {
+    0x3F, 0x0B,
+    SenseDevTypes050,
+    "VOLUME SET DELETED"
+  },
+  {
+    0x3F, 0x0C,
+    SenseDevTypes050,
+    "VOLUME SET DEASSIGNED"
+  },
+  {
+    0x3F, 0x0D,
+    SenseDevTypes050,
+    "VOLUME SET REASSIGNED"
+  },
+  {
+    0x3F, 0x0E,
+    SenseDevTypes041,
+    "REPORTED LUNS DATA HAS CHANGED"
+  },
+  {
+    0x3F, 0x0F,
+    SenseDevTypes001,
+    "ECHO BUFFER OVERWRITTEN"
+  },
+  {
+    0x3F, 0x10,
+    SenseDevTypes039,
+    "MEDIUM LOADABLE"
+  },
+  {
+    0x3F, 0x11,
+    SenseDevTypes039,
+    "MEDIUM AUXILIARY MEMORY ACCESSIBLE"
+  },
+  {
+    0x40, 0x00,
+    SenseDevTypes035,
+    "RAM FAILURE (SHOULD USE 40 NN)"
+  },
+  {
+    0x40, 0xFF,
+    SenseDevTypes001,
+    "DIAGNOSTIC FAILURE ON COMPONENT NN (80H-FFH)"
+  },
+  {
+    0x41, 0x00,
+    SenseDevTypes035,
+    "DATA PATH FAILURE (SHOULD USE 40 NN)"
+  },
+  {
+    0x42, 0x00,
+    SenseDevTypes035,
+    "POWER-ON OR SELF-TEST FAILURE (SHOULD USE 40 NN)"
+  },
+  {
+    0x43, 0x00,
+    SenseDevTypes001,
+    "MESSAGE ERROR"
+  },
+  {
+    0x44, 0x00,
+    SenseDevTypes001,
+    "INTERNAL TARGET FAILURE"
+  },
+  {
+    0x45, 0x00,
+    SenseDevTypes001,
+    "SELECT OR RESELECT FAILURE"
+  },
+  {
+    0x46, 0x00,
+    SenseDevTypes049,
+    "UNSUCCESSFUL SOFT RESET"
+  },
+  {
+    0x47, 0x00,
+    SenseDevTypes001,
+    "SCSI PARITY ERROR"
+  },
+  {
+    0x47, 0x01,
+    SenseDevTypes001,
+    "DATA PHASE CRC ERROR DETECTED"
+  },
+  {
+    0x47, 0x02,
+    SenseDevTypes001,
+    "SCSI PARITY ERROR DETECTED DURING ST DATA PHASE"
+  },
+  {
+    0x47, 0x03,
+    SenseDevTypes001,
+    "INFORMATION UNIT CRC ERROR DETECTED"
+  },
+  {
+    0x47, 0x04,
+    SenseDevTypes001,
+    "ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED"
+  },
+  {
+    0x48, 0x00,
+    SenseDevTypes001,
+    "INITIATOR DETECTED ERROR MESSAGE RECEIVED"
+  },
+  {
+    0x49, 0x00,
+    SenseDevTypes001,
+    "INVALID MESSAGE ERROR"
+  },
+  {
+    0x4A, 0x00,
+    SenseDevTypes001,
+    "COMMAND PHASE ERROR"
+  },
+  {
+    0x4B, 0x00,
+    SenseDevTypes001,
+    "DATA PHASE ERROR"
+  },
+  {
+    0x4C, 0x00,
+    SenseDevTypes001,
+    "LOGICAL UNIT FAILED SELF-CONFIGURATION"
+  },
+  {
+    0x4D, 0xFF,
+    SenseDevTypes001,
+    "TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG)"
+  },
+  {
+    0x4E, 0x00,
+    SenseDevTypes001,
+    "OVERLAPPED COMMANDS ATTEMPTED"
+  },
+  {
+    0x50, 0x00,
+    SenseDevTypes002,
+    "WRITE APPEND ERROR"
+  },
+  {
+    0x50, 0x01,
+    SenseDevTypes002,
+    "WRITE APPEND POSITION ERROR"
+  },
+  {
+    0x50, 0x02,
+    SenseDevTypes002,
+    "POSITION ERROR RELATED TO TIMING"
+  },
+  {
+    0x51, 0x00,
+    SenseDevTypes052,
+    "ERASE FAILURE"
+  },
+  {
+    0x52, 0x00,
+    SenseDevTypes002,
+    "CARTRIDGE FAULT"
+  },
+  {
+    0x53, 0x00,
+    SenseDevTypes014,
+    "MEDIA LOAD OR EJECT FAILED"
+  },
+  {
+    0x53, 0x01,
+    SenseDevTypes002,
+    "UNLOAD TAPE FAILURE"
+  },
+  {
+    0x53, 0x02,
+    SenseDevTypes034,
+    "MEDIUM REMOVAL PREVENTED"
+  },
+  {
+    0x54, 0x00,
+    SenseDevTypes053,
+    "SCSI TO HOST SYSTEM INTERFACE FAILURE"
+  },
+  {
+    0x55, 0x00,
+    SenseDevTypes053,
+    "SYSTEM RESOURCE FAILURE"
+  },
+  {
+    0x55, 0x01,
+    SenseDevTypes033,
+    "SYSTEM BUFFER FULL"
+  },
+  {
+    0x55, 0x02,
+    SenseDevTypes054,
+    "INSUFFICIENT RESERVATION RESOURCES"
+  },
+  {
+    0x55, 0x03,
+    SenseDevTypes041,
+    "INSUFFICIENT RESOURCES"
+  },
+  {
+    0x55, 0x04,
+    SenseDevTypes055,
+    "INSUFFICIENT REGISTRATION RESOURCES"
+  },
+  {
+    0x55, 0x05,
+    SenseDevTypes012,
+    "access controls code 4 (99-314) [proposed]"
+  },
+  {
+    0x55, 0x06,
+    SenseDevTypes012,
+    "auxiliary memory code 1 (99-148) [proposed]"
+  },
+  {
+    0x57, 0x00,
+    SenseDevTypes005,
+    "UNABLE TO RECOVER TABLE-OF-CONTENTS"
+  },
+  {
+    0x58, 0x00,
+    SenseDevTypes056,
+    "GENERATION DOES NOT EXIST"
+  },
+  {
+    0x59, 0x00,
+    SenseDevTypes056,
+    "UPDATED BLOCK READ"
+  },
+  {
+    0x5A, 0x00,
+    SenseDevTypes057,
+    "OPERATOR REQUEST OR STATE CHANGE INPUT"
+  },
+  {
+    0x5A, 0x01,
+    SenseDevTypes034,
+    "OPERATOR MEDIUM REMOVAL REQUEST"
+  },
+  {
+    0x5A, 0x02,
+    SenseDevTypes058,
+    "OPERATOR SELECTED WRITE PROTECT"
+  },
+  {
+    0x5A, 0x03,
+    SenseDevTypes058,
+    "OPERATOR SELECTED WRITE PERMIT"
+  },
+  {
+    0x5B, 0x00,
+    SenseDevTypes059,
+    "LOG EXCEPTION"
+  },
+  {
+    0x5B, 0x01,
+    SenseDevTypes059,
+    "THRESHOLD CONDITION MET"
+  },
+  {
+    0x5B, 0x02,
+    SenseDevTypes059,
+    "LOG COUNTER AT MAXIMUM"
+  },
+  {
+    0x5B, 0x03,
+    SenseDevTypes059,
+    "LOG LIST CODES EXHAUSTED"
+  },
+  {
+    0x5C, 0x00,
+    SenseDevTypes060,
+    "RPL STATUS CHANGE"
+  },
+  {
+    0x5C, 0x01,
+    SenseDevTypes060,
+    "SPINDLES SYNCHRONIZED"
+  },
+  {
+    0x5C, 0x02,
+    SenseDevTypes060,
+    "SPINDLES NOT SYNCHRONIZED"
+  },
+  {
+    0x5D, 0x00,
+    SenseDevTypes001,
+    "FAILURE PREDICTION THRESHOLD EXCEEDED"
+  },
+  {
+    0x5D, 0x01,
+    SenseDevTypes061,
+    "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED"
+  },
+  {
+    0x5D, 0x02,
+    SenseDevTypes005,
+    "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED"
+  },
+  {
+    0x5D, 0x10,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x11,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x12,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x13,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x14,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x15,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x16,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x17,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x18,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x19,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x1A,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x1B,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x1C,
+    SenseDevTypes062,
+    "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0x20,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x21,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x22,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x23,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x24,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x25,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x26,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x27,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x28,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x29,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x2A,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x2B,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x2C,
+    SenseDevTypes062,
+    "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0x30,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x31,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x32,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x33,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x34,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x35,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x36,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x37,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x38,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x39,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x3A,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x3B,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x3C,
+    SenseDevTypes062,
+    "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0x40,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x41,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x42,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x43,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x44,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x45,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x46,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x47,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x48,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x49,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x4A,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x4B,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x4C,
+    SenseDevTypes062,
+    "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0x50,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x51,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x52,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x53,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x54,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x55,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x56,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x57,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x58,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x59,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x5A,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x5B,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x5C,
+    SenseDevTypes062,
+    "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0x60,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
+  },
+  {
+    0x5D, 0x61,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x62,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x63,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
+  },
+  {
+    0x5D, 0x64,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
+  },
+  {
+    0x5D, 0x65,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x66,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
+  },
+  {
+    0x5D, 0x67,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS"
+  },
+  {
+    0x5D, 0x68,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED"
+  },
+  {
+    0x5D, 0x69,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
+  },
+  {
+    0x5D, 0x6A,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"
+  },
+  {
+    0x5D, 0x6B,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"
+  },
+  {
+    0x5D, 0x6C,
+    SenseDevTypes062,
+    "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
+  },
+  {
+    0x5D, 0xFF,
+    SenseDevTypes001,
+    "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"
+  },
+  {
+    0x5E, 0x00,
+    SenseDevTypes044,
+    "LOW POWER CONDITION ON"
+  },
+  {
+    0x5E, 0x01,
+    SenseDevTypes044,
+    "IDLE CONDITION ACTIVATED BY TIMER"
+  },
+  {
+    0x5E, 0x02,
+    SenseDevTypes044,
+    "STANDBY CONDITION ACTIVATED BY TIMER"
+  },
+  {
+    0x5E, 0x03,
+    SenseDevTypes044,
+    "IDLE CONDITION ACTIVATED BY COMMAND"
+  },
+  {
+    0x5E, 0x04,
+    SenseDevTypes044,
+    "STANDBY CONDITION ACTIVATED BY COMMAND"
+  },
+  {
+    0x5E, 0x41,
+    SenseDevTypes043,
+    "POWER STATE CHANGE TO ACTIVE"
+  },
+  {
+    0x5E, 0x42,
+    SenseDevTypes043,
+    "POWER STATE CHANGE TO IDLE"
+  },
+  {
+    0x5E, 0x43,
+    SenseDevTypes043,
+    "POWER STATE CHANGE TO STANDBY"
+  },
+  {
+    0x5E, 0x45,
+    SenseDevTypes043,
+    "POWER STATE CHANGE TO SLEEP"
+  },
+  {
+    0x5E, 0x47,
+    SenseDevTypes063,
+    "POWER STATE CHANGE TO DEVICE CONTROL"
+  },
+  {
+    0x60, 0x00,
+    SenseDevTypes042,
+    "LAMP FAILURE"
+  },
+  {
+    0x61, 0x00,
+    SenseDevTypes042,
+    "VIDEO ACQUISITION ERROR"
+  },
+  {
+    0x61, 0x01,
+    SenseDevTypes042,
+    "UNABLE TO ACQUIRE VIDEO"
+  },
+  {
+    0x61, 0x02,
+    SenseDevTypes042,
+    "OUT OF FOCUS"
+  },
+  {
+    0x62, 0x00,
+    SenseDevTypes042,
+    "SCAN HEAD POSITIONING ERROR"
+  },
+  {
+    0x63, 0x00,
+    SenseDevTypes005,
+    "END OF USER AREA ENCOUNTERED ON THIS TRACK"
+  },
+  {
+    0x63, 0x01,
+    SenseDevTypes005,
+    "PACKET DOES NOT FIT IN AVAILABLE SPACE"
+  },
+  {
+    0x64, 0x00,
+    SenseDevTypes005,
+    "ILLEGAL MODE FOR THIS TRACK"
+  },
+  {
+    0x64, 0x01,
+    SenseDevTypes005,
+    "INVALID PACKET SIZE"
+  },
+  {
+    0x65, 0x00,
+    SenseDevTypes001,
+    "VOLTAGE FAULT"
+  },
+  {
+    0x66, 0x00,
+    SenseDevTypes042,
+    "AUTOMATIC DOCUMENT FEEDER COVER UP"
+  },
+  {
+    0x66, 0x01,
+    SenseDevTypes042,
+    "AUTOMATIC DOCUMENT FEEDER LIFT UP"
+  },
+  {
+    0x66, 0x02,
+    SenseDevTypes042,
+    "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"
+  },
+  {
+    0x66, 0x03,
+    SenseDevTypes042,
+    "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"
+  },
+  {
+    0x67, 0x00,
+    SenseDevTypes064,
+    "CONFIGURATION FAILURE"
+  },
+  {
+    0x67, 0x01,
+    SenseDevTypes064,
+    "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"
+  },
+  {
+    0x67, 0x02,
+    SenseDevTypes064,
+    "ADD LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x03,
+    SenseDevTypes064,
+    "MODIFICATION OF LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x04,
+    SenseDevTypes064,
+    "EXCHANGE OF LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x05,
+    SenseDevTypes064,
+    "REMOVE OF LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x06,
+    SenseDevTypes064,
+    "ATTACHMENT OF LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x07,
+    SenseDevTypes064,
+    "CREATION OF LOGICAL UNIT FAILED"
+  },
+  {
+    0x67, 0x08,
+    SenseDevTypes064,
+    "ASSIGN FAILURE OCCURRED"
+  },
+  {
+    0x67, 0x09,
+    SenseDevTypes064,
+    "MULTIPLY ASSIGNED LOGICAL UNIT"
+  },
+  {
+    0x68, 0x00,
+    SenseDevTypes064,
+    "LOGICAL UNIT NOT CONFIGURED"
+  },
+  {
+    0x69, 0x00,
+    SenseDevTypes064,
+    "DATA LOSS ON LOGICAL UNIT"
+  },
+  {
+    0x69, 0x01,
+    SenseDevTypes064,
+    "MULTIPLE LOGICAL UNIT FAILURES"
+  },
+  {
+    0x69, 0x02,
+    SenseDevTypes064,
+    "PARITY/DATA MISMATCH"
+  },
+  {
+    0x6A, 0x00,
+    SenseDevTypes064,
+    "INFORMATIONAL, REFER TO LOG"
+  },
+  {
+    0x6B, 0x00,
+    SenseDevTypes064,
+    "STATE CHANGE HAS OCCURRED"
+  },
+  {
+    0x6B, 0x01,
+    SenseDevTypes064,
+    "REDUNDANCY LEVEL GOT BETTER"
+  },
+  {
+    0x6B, 0x02,
+    SenseDevTypes064,
+    "REDUNDANCY LEVEL GOT WORSE"
+  },
+  {
+    0x6C, 0x00,
+    SenseDevTypes064,
+    "REBUILD FAILURE OCCURRED"
+  },
+  {
+    0x6D, 0x00,
+    SenseDevTypes064,
+    "RECALCULATE FAILURE OCCURRED"
+  },
+  {
+    0x6E, 0x00,
+    SenseDevTypes064,
+    "COMMAND TO LOGICAL UNIT FAILED"
+  },
+  {
+    0x6F, 0x00,
+    SenseDevTypes005,
+    "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"
+  },
+  {
+    0x6F, 0x01,
+    SenseDevTypes005,
+    "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"
+  },
+  {
+    0x6F, 0x02,
+    SenseDevTypes005,
+    "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"
+  },
+  {
+    0x6F, 0x03,
+    SenseDevTypes005,
+    "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"
+  },
+  {
+    0x6F, 0x04,
+    SenseDevTypes005,
+    "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"
+  },
+  {
+    0x6F, 0x05,
+    SenseDevTypes005,
+    "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"
+  },
+  {
+    0x70, 0xFF,
+    SenseDevTypes002,
+    "DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF NN"
+  },
+  {
+    0x71, 0x00,
+    SenseDevTypes002,
+    "DECOMPRESSION EXCEPTION LONG ALGORITHM ID"
+  },
+  {
+    0x72, 0x00,
+    SenseDevTypes005,
+    "SESSION FIXATION ERROR"
+  },
+  {
+    0x72, 0x01,
+    SenseDevTypes005,
+    "SESSION FIXATION ERROR WRITING LEAD-IN"
+  },
+  {
+    0x72, 0x02,
+    SenseDevTypes005,
+    "SESSION FIXATION ERROR WRITING LEAD-OUT"
+  },
+  {
+    0x72, 0x03,
+    SenseDevTypes005,
+    "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"
+  },
+  {
+    0x72, 0x04,
+    SenseDevTypes005,
+    "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"
+  },
+  {
+    0x72, 0x05,
+    SenseDevTypes005,
+    "NO MORE TRACK RESERVATIONS ALLOWED"
+  },
+  {
+    0x73, 0x00,
+    SenseDevTypes005,
+    "CD CONTROL ERROR"
+  },
+  {
+    0x73, 0x01,
+    SenseDevTypes005,
+    "POWER CALIBRATION AREA ALMOST FULL"
+  },
+  {
+    0x73, 0x02,
+    SenseDevTypes005,
+    "POWER CALIBRATION AREA IS FULL"
+  },
+  {
+    0x73, 0x03,
+    SenseDevTypes005,
+    "POWER CALIBRATION AREA ERROR"
+  },
+  {
+    0x73, 0x04,
+    SenseDevTypes005,
+    "PROGRAM MEMORY AREA UPDATE FAILURE"
+  },
+  {
+    0x73, 0x05,
+    SenseDevTypes005,
+    "PROGRAM MEMORY AREA IS FULL"
+  },
+  {
+    0x73, 0x06,
+    SenseDevTypes005,
+    "RMA/PMA IS FULL"
+  },
+};
+
+static int ASCQ_TableSize = 463;
+
+
+#endif
diff -urN linux-2.4.7-pre3/drivers/message/fusion/ascq_tbl.sh linux/drivers/message/fusion/ascq_tbl.sh
--- linux-2.4.7-pre3/drivers/message/fusion/ascq_tbl.sh	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/ascq_tbl.sh	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+#  ascq_tbl.sh - Translate SCSI t10.org's "asc-num.txt" file of
+#                SCSI Additional Sense Code & Qualifiers (ASC/ASCQ's)
+#                into something useful in C, creating "ascq_tbl.c" file.
+#
+#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
+
+PREF_INFILE="t10.org/asc-num.txt"	# From SCSI t10.org
+PREF_OUTFILE="ascq_tbl.c"
+
+#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
+
+xlate_ascq() {
+	cat | awk '
+	BEGIN {
+		DQ = "\042";
+		OUTFILE = "'"${PREF_OUTFILE}"'";
+		TRUE = 1;
+		FALSE = 0;
+		#debug = TRUE;
+
+		#  read and discard all lines up to and including the one that begins
+		#  with the "magic token" of "-------  --------------  ---"...
+		headers_gone = FALSE;
+		while (!headers_gone) {
+			if (getline <= 0)
+				exit 1;
+			header_line[++hdrs] = $0;
+			if (debug)
+				printf("header_line[%d] = :%s:\n", ++hdrs, $0);
+			if ($0 ~ /^-------  --------------  ---/) {
+				headers_gone = TRUE;
+			}
+		}
+		outcount = 0;
+	}
+
+	(NF > 1) {
+		++outcount;
+		if (debug)
+			printf( "DBG: %s\n", $0 );
+		ASC[outcount] = substr($0,1,2);
+		ASCQ[outcount] = substr($0,5,2);
+		devtypes = substr($0,10,14);
+		gsub(/ /, ".", devtypes);
+		DESCRIP[outcount] = substr($0,26);
+
+		if (!(devtypes in DevTypesVoodoo)) {
+			DevTypesVoodoo[devtypes] = ++voodoo;
+			DevTypesIdx[voodoo] = devtypes;
+		}
+		DEVTYPES[outcount] = DevTypesVoodoo[devtypes];
+
+		#  Handle 0xNN exception stuff...
+		if (ASCQ[outcount] == "NN" || ASCQ[outcount] == "nn")
+			ASCQ[outcount] = "FF";
+	}
+
+	END {
+		printf("#ifndef SCSI_ASCQ_TBL_C_INCLUDED\n") > OUTFILE;
+		printf("#define SCSI_ASCQ_TBL_C_INCLUDED\n") >> OUTFILE;
+
+		printf("\n/* AuToMaGiCaLlY generated from: %s'"${FIN}"'%s\n", DQ, DQ) >> OUTFILE;
+		printf(" *******************************************************************************\n") >> OUTFILE;
+		for (i=1; i<=hdrs; i++) {
+			printf(" * %s\n", header_line[i]) >> OUTFILE;
+		}
+		printf(" */\n") >> OUTFILE;
+
+		printf("\n") >> OUTFILE;
+		for (i=1; i<=voodoo; i++) {
+			printf("static char SenseDevTypes%03d[] = %s%s%s;\n", i, DQ, DevTypesIdx[i], DQ) >> OUTFILE;
+		}
+
+		printf("\nstatic ASCQ_Table_t ASCQ_Table[] = {\n") >> OUTFILE;
+		for (i=1; i<=outcount; i++) {
+			printf("  {\n") >> OUTFILE; 
+			printf("    0x%s, 0x%s,\n", ASC[i], ASCQ[i]) >> OUTFILE;
+			printf("    SenseDevTypes%03d,\n", DEVTYPES[i]) >> OUTFILE;
+			printf("    %s%s%s\n", DQ, DESCRIP[i], DQ) >> OUTFILE;
+			printf("  },\n") >> OUTFILE;
+		}
+		printf( "};\n\n" ) >> OUTFILE;
+
+		printf( "static int ASCQ_TableSize = %d;\n\n", outcount ) >> OUTFILE;
+		printf( "Total of %d ASC/ASCQ records generated\n", outcount );
+		printf("\n#endif\n") >> OUTFILE;
+		close(OUTFILE);
+	}'
+	return
+}
+
+#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
+
+# main()
+if [ $# -lt 1 ]; then
+	echo "INFO: No input filename supplied - using: $PREF_INFILE" >&2
+	FIN=$PREF_INFILE
+else
+	FIN="$1"
+	if [ "$FIN" != "$PREF_INFILE" ]; then
+		echo "INFO: Ok, I'll try chewing on '$FIN' for SCSI ASC/ASCQ combos..." >&2
+	fi
+	shift
+fi
+
+cat $FIN | xlate_ascq
+exit 0
diff -urN linux-2.4.7-pre3/drivers/message/fusion/isense.c linux/drivers/message/fusion/isense.c
--- linux-2.4.7-pre3/drivers/message/fusion/isense.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/isense.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,122 @@
+/*
+ *  linux/drivers/message/fusion/isense.c
+ *      Little linux driver / shim that interfaces with the Fusion MPT
+ *      Linux base driver to provide english readable strings in SCSI
+ *      Error Report logging output.  This module implements SCSI-3
+ *      Opcode lookup and a sorted table of SCSI-3 ASC/ASCQ strings.
+ *
+ *  Copyright (c) 1991-2001 Steven J. Ralston
+ *  Written By: Steven J. Ralston
+ *  (yes I wrote some of the orig. code back in 1991!)
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: isense.c,v 1.28 2001/01/14 23:11:09 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/version.h>
+
+/* Hmmm, avoid undefined spinlock_t on lk-2.2.14-5.0 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#include <asm/spinlock.h>
+#endif
+
+#define MODULEAUTHOR "Steven J. Ralston"
+#define COPYRIGHT "Copyright (c) 2000 " MODULEAUTHOR
+#include "mptbase.h"
+
+#include "isense.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Private data...
+ */
+
+/*
+ *  YIKES!  I don't usually #include C source files, but..
+ *  The following #include's pulls in our needed ASCQ_Table[] array,
+ *  ASCQ_TableSz integer, and ScsiOpcodeString[] array!
+ */
+#include "ascq_tbl.c"
+#include "scsiops.c"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"SCSI-3 Opcodes & ASC/ASCQ Strings"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"isense"
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int __init isense_init(void)
+{
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	/*
+	 *  Install our handler
+	 */
+	if (mpt_register_ascqops_strings(&ASCQ_Table[0], ASCQ_TableSize, ScsiOpcodeString) != 1)
+	{
+		printk(KERN_ERR MYNAM ": ERROR: Can't register with Fusion MPT base driver!\n");
+		return -EBUSY;
+	}
+	printk(KERN_INFO MYNAM ": Registered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
+	return 0;
+}
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void isense_exit(void)
+{
+#ifdef MODULE
+	mpt_deregister_ascqops_strings();
+#endif
+	printk(KERN_INFO MYNAM ": Deregistered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
+}
+
+module_init(isense_init);
+module_exit(isense_exit);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/isense.h linux/drivers/message/fusion/isense.h
--- linux-2.4.7-pre3/drivers/message/fusion/isense.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/isense.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,95 @@
+#ifndef ISENSE_H_INCLUDED
+#define ISENSE_H_INCLUDED
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#ifdef __KERNEL__
+#include <linux/types.h>		/* needed for u8, etc. */
+#include <linux/string.h>		/* needed for strcat   */
+#include <linux/kernel.h>		/* needed for sprintf  */
+#else
+    #ifndef U_STUFF_DEFINED
+    #define U_STUFF_DEFINED
+    typedef unsigned char u8;
+    typedef unsigned short u16;
+    typedef unsigned int u32;
+    #endif
+#endif
+
+#include "scsi3.h"			/* needed for all things SCSI */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Defines and typedefs...
+ */
+
+#ifdef __KERNEL__
+#define PrintF(x) printk x
+#else
+#define PrintF(x) printf x
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define RETRY_STATUS  ((int) 1)
+#define PUT_STATUS    ((int) 0)
+
+/*
+ *    A generic structure to hold info about IO request that caused
+ *    a Request Sense to be performed, and the resulting Sense Data.
+ */
+typedef struct IO_Info
+{
+    char *DevIDStr;   /* String of chars which identifies the device.       */
+    u8   *cdbPtr;     /* Pointer (Virtual/Logical addr) to CDB bytes of
+                           IO request that caused ContAllegianceCond.       */
+    u8   *sensePtr;   /* Pointer (Virtual/Logical addr) to Sense Data
+                           returned by Request Sense operation.             */
+    u8   *dataPtr;    /* Pointer (Virtual/Logical addr) to Data buffer
+                           of IO request caused ContAllegianceCondition.    */
+    u8   *inqPtr;     /* Pointer (Virtual/Logical addr) to Inquiry Data for
+                           IO *Device* that caused ContAllegianceCondition. */
+    u8    SCSIStatus; /* SCSI status byte of IO request that caused
+                           Contingent Allegiance Condition.                 */
+    u8    DoDisplay;  /* Shall we display any messages?                     */
+    u16   rsvd_align1;
+    u32   ComplCode;  /* Four-byte OS-dependent completion code.            */
+    u32   NotifyL;    /* Four-byte OS-dependent notification field.         */
+} IO_Info_t;
+
+/*
+ *  SCSI Additional Sense Code and Additional Sense Code Qualifier table.
+ */
+typedef struct ASCQ_Table
+{
+    u8     ASC;
+    u8     ASCQ;
+    char  *DevTypes;
+    char  *Description;
+} ASCQ_Table_t;
+
+#if 0
+/*
+ *  SCSI Opcodes table.
+ */
+typedef struct SCSI_OPS_Table
+{
+    u8     OpCode;
+    char  *DevTypes;
+    char  *ScsiCmndStr;
+} SCSI_OPS_Table_t;
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Public entry point prototypes
+ */
+
+/* in scsiherr.c, needed by mptscsih.c */
+extern int	 mpt_ScsiHost_ErrorReport(IO_Info_t *ioop);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/linux_compat.h linux/drivers/message/fusion/linux_compat.h
--- linux-2.4.7-pre3/drivers/message/fusion/linux_compat.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/linux_compat.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,199 @@
+/* drivers/message/fusion/linux_compat.h */
+
+#ifndef FUSION_LINUX_COMPAT_H
+#define FUSION_LINUX_COMPAT_H
+/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
+		typedef unsigned int dma_addr_t;
+#	endif
+#else
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42)
+		typedef unsigned int dma_addr_t;
+#	endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
+/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/* This block snipped from lk-2.2.18/include/linux/init.h { */
+/*
+ * Used for initialization calls..
+ */
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+#define __init_call	__attribute__ ((unused,__section__ (".initcall.init")))
+#define __exit_call	__attribute__ ((unused,__section__ (".exitcall.exit")))
+
+extern initcall_t __initcall_start, __initcall_end;
+
+#define __initcall(fn)								\
+	static initcall_t __initcall_##fn __init_call = fn
+#define __exitcall(fn)								\
+	static exitcall_t __exitcall_##fn __exit_call = fn
+
+#ifdef MODULE
+/* 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))); \
+	extern inline __init_module_func_t __init_module_inline(void) \
+	{ return x; }
+#define module_exit(x) \
+	void cleanup_module(void) __attribute__((alias(#x))); \
+	extern inline __cleanup_module_func_t __cleanup_module_inline(void) \
+	{ return x; }
+
+#else 
+#define module_init(x)	__initcall(x);
+#define module_exit(x)	__exitcall(x);
+#endif
+/* } block snipped from lk-2.2.18/include/linux/init.h */
+
+/* Wait queues. */
+#define DECLARE_WAIT_QUEUE_HEAD(name)	\
+	struct wait_queue * (name) = NULL
+#define DECLARE_WAITQUEUE(name, task)	\
+	struct wait_queue (name) = { (task), NULL }
+
+#if defined(__sparc__) && defined(__sparc_v9__)
+/* The sparc64 ioremap implementation is wrong in 2.2.x,
+ * but fixing it would break all of the drivers which
+ * workaround it.  Fixed in 2.3.x onward. -DaveM
+ */
+#define ARCH_IOREMAP(base)	((unsigned long) (base))
+#else
+#define ARCH_IOREMAP(base)	ioremap(base)
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#else		/* LINUX_VERSION_CODE must be >= KERNEL_VERSION(2,2,18) */
+
+/* No ioremap bugs in >2.3.x kernels. */
+#define ARCH_IOREMAP(base)	ioremap(base)
+
+/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif		/* LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) */
+
+
+/* PCI/driver subsystem { */
+#ifndef pci_for_each_dev
+#define pci_for_each_dev(dev)		for((dev)=pci_devices; (dev)!=NULL; (dev)=(dev)->next)
+#define pci_peek_next_dev(dev)		((dev)->next ? (dev)->next : NULL)
+#define DEVICE_COUNT_RESOURCE           6
+#define PCI_BASEADDR_FLAGS(idx)         base_address[idx]
+#define PCI_BASEADDR_START(idx)         base_address[idx] & ~0xFUL
+/*
+ * We have to keep track of the original value using
+ * a temporary, and not by just sticking pdev->base_address[x]
+ * back.  pdev->base_address[x] is an opaque cookie that can
+ * be used by the PCI implementation on a given Linux port
+ * for any purpose. -DaveM
+ */
+#define PCI_BASEADDR_SIZE(__pdev, __idx) \
+({	unsigned int size, tmp; \
+	pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &tmp); \
+	pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), 0xffffffff); \
+	pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &size); \
+	pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), tmp); \
+	(4 - size); \
+})
+#else
+#define pci_peek_next_dev(dev)		((dev) != pci_dev_g(&pci_devices) ? pci_dev_g((dev)->global_list.next) : NULL)
+#define PCI_BASEADDR_FLAGS(idx)         resource[idx].flags
+#define PCI_BASEADDR_START(idx)         resource[idx].start
+#define PCI_BASEADDR_SIZE(dev,idx)      (dev)->resource[idx].end - (dev)->resource[idx].start + 1
+#endif		/* } ifndef pci_for_each_dev */
+
+
+/* procfs compat stuff... */
+#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
+#define CREATE_PROCDIR_ENTRY(x,y)  create_proc_entry(x, S_IFDIR, y)
+/* This is a macro so we don't need to pull all the procfs
+ * headers into this file. -DaveM
+ */
+#define create_proc_read_entry(name, mode, base, __read_proc, __data) \
+({      struct proc_dir_entry *__res=create_proc_entry(name,mode,base); \
+        if (__res) { \
+                __res->read_proc=(__read_proc); \
+                __res->data=(__data); \
+        } \
+        __res; \
+})
+#else
+#define CREATE_PROCDIR_ENTRY(x,y)  proc_mkdir(x, y)
+#endif
+#endif
+
+/* Compatability for the 2.3.x PCI DMA API. */
+#ifndef PCI_DMA_BIDIRECTIONAL
+/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#define PCI_DMA_BIDIRECTIONAL	0
+#define PCI_DMA_TODEVICE	1
+#define PCI_DMA_FROMDEVICE	2
+#define PCI_DMA_NONE		3
+
+#ifdef __KERNEL__
+#include <asm/page.h>
+/* Pure 2^n version of get_order */
+static __inline__ int __get_order(unsigned long size)
+{
+	int order;
+
+	size = (size-1) >> (PAGE_SHIFT-1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+#endif
+
+#define pci_alloc_consistent(hwdev, size, dma_handle) \
+({	void *__ret = (void *)__get_free_pages(GFP_ATOMIC, __get_order(size)); \
+	if (__ret != NULL) { \
+		memset(__ret, 0, size); \
+		*(dma_handle) = virt_to_bus(__ret); \
+	} \
+	__ret; \
+})
+
+#define pci_free_consistent(hwdev, size, vaddr, dma_handle) \
+	free_pages((unsigned long)vaddr, __get_order(size))
+
+#define pci_map_single(hwdev, ptr, size, direction) \
+	virt_to_bus(ptr);
+
+#define pci_unmap_single(hwdev, dma_addr, size, direction) \
+	do { /* Nothing to do */ } while (0)
+
+#define pci_map_sg(hwdev, sg, nents, direction)	(nents)
+#define pci_unmap_sg(hwdev, sg, nents, direction) \
+	do { /* Nothing to do */ } while(0)
+
+#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
+#define sg_dma_len(sg)		((sg)->length)
+
+/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif /* PCI_DMA_BIDIRECTIONAL */
+
+/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif /* _LINUX_COMPAT_H */
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/fc_log.h linux/drivers/message/fusion/lsi/fc_log.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/fc_log.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/fc_log.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ *  NAME:           fc_log.h
+ *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
+ *  DESCRIPTION:    Contains the enumerated list of values that may be returned
+ *                  in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ *  CREATION DATE:  6/02/2000
+ *  ID:             $Id: fc_log.h,v 4.2 2001/03/01 18:28:59 fibre Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ *          a = The type of log info as per the MPI spec. Since these codes are
+ *              all for Fibre Channel this value will always be 2.
+ *          b = Specifies a subclass of the firmware where
+ *                  0 = FCP Initiator
+ *                  1 = FCP Target
+ *                  2 = LAN
+ *                  3 = MPI Message Layer
+ *                  4 = FC Link
+ *                  5 = Context Manager
+ *                  6 = Invalid Field Offset
+ *                  7 = State Change Info
+ *                  all others are reserved for future use
+ *          c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ *       codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+    MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* bad start of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* bad end of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Receiver hardware detected overrun */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */
+
+    MPI_IOCLOGINFO_FC_TARGET_BASE                   = 0x21000000,
+    MPI_IOCLOGINFO_FC_TARGET_NO_PDISC               = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+    MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN               = 0x21000002, /* not sent because we are not logged in to the remote node */
+    MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP     = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP     = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA      = 0x21000005, /* Data In, Auto Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP     = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP     = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP     = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA      = 0x21000009, /* Data In, No Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP     = 0x2100000a, /* Manual Response not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3             = 0x2100000b, /* not sent because remote node does not support Class 3 */
+    MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID        = 0x2100000c, /* not sent because login to remote node not validated */
+    MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND          = 0x2100000e, /* cleared from the outbound after a logout */
+    MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN    = 0x2100000f, /* cleared waiting for data after a logout */
+
+    MPI_IOCLOGINFO_FC_LAN_BASE                      = 0x22000000,
+    MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING         = 0x22000001, /* Transaction Context Sgl Missing */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE         = 0x22000002, /* Transaction Context found before an EOB */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET        = 0x22000003, /* Transaction Context value has reserved bits set */
+    MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG            = 0x22000004, /* Invalid SGL Flags */
+
+    MPI_IOCLOGINFO_FC_MSG_BASE                      = 0x23000000,
+
+    MPI_IOCLOGINFO_FC_LINK_BASE                     = 0x24000000,
+    MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT        = 0x24000001, /* Loop initialization timed out */
+    MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED      = 0x24000002, /* Another system controller already initialized the loop */
+    MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED     = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+
+    MPI_IOCLOGINFO_FC_CTX_BASE                      = 0x25000000,
+
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET     = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid. */
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET      = 0x26ffffff,
+
+    MPI_IOCLOGINFO_FC_STATE_CHANGE                  = 0x27000000  /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi.h linux/drivers/message/fusion/lsi/mpi.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,643 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI.H
+ *          Title:  MPI Message independent structures and definitions
+ *  Creation Date:  July 27, 2000
+ *
+ *    MPI Version:  01.01.06
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition.
+ *  06-06-00  01.00.01  Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR.
+ *  06-22-00  01.00.02  Added MPI_IOCSTATUS_LAN_ definitions.
+ *                      Removed LAN_SUSPEND function definition.
+ *                      Added MPI_MSGFLAGS_CONTINUATION_REPLY definition.
+ *  06-30-00  01.00.03  Added MPI_CONTEXT_REPLY_TYPE_LAN definition.
+ *                      Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros.
+ *  07-27-00  01.00.04  Added MPI_FAULT_ definitions.
+ *                      Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions.
+ *                      Added MPI_IOCSTATUS_INTERNAL_ERROR definition.
+ *                      Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH.
+ *  11-02-00  01.01.01  Original release for post 1.0 work.
+ *  12-04-00  01.01.02  Added new function codes.
+ *  01-09-01  01.01.03  Added more definitions to the system interface section
+ *                      Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT.
+ *  01-25-01  01.01.04  Changed MPI_VERSION_MINOR from 0x00 to 0x01.
+ *  02-20-01  01.01.05  Started using MPI_POINTER.
+ *                      Fixed value for MPI_DIAG_RW_ENABLE.
+ *                      Added defines for MPI_DIAG_PREVENT_IOC_BOOT and
+ *                      MPI_DIAG_CLEAR_FLASH_BAD_SIG.
+ *                      Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines.
+ *  02-27-01  01.01.06  Removed MPI_HOST_INDEX_REGISTER define.
+ *                      Added function codes for RAID.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_H
+#define MPI_H
+
+
+/*****************************************************************************
+*
+*        M P I    V e r s i o n    D e f i n i t i o n s
+*
+*****************************************************************************/
+
+#define MPI_VERSION_MAJOR                   (0x01)
+#define MPI_VERSION_MINOR                   (0x01)
+#define MPI_VERSION            ((MPI_VERSION_MAJOR << 8) | MPI_VERSION_MINOR)
+
+/* Note: The major versions of 0xe0 through 0xff are reserved */
+
+/*****************************************************************************
+*
+*        I O C    S t a t e    D e f i n i t i o n s
+*
+*****************************************************************************/
+
+#define MPI_IOC_STATE_RESET                 (0x00000000)
+#define MPI_IOC_STATE_READY                 (0x10000000)
+#define MPI_IOC_STATE_OPERATIONAL           (0x20000000)
+#define MPI_IOC_STATE_FAULT                 (0x40000000)
+
+#define MPI_IOC_STATE_MASK                  (0xF0000000)
+#define MPI_IOC_STATE_SHIFT                 (28)
+
+/* Fault state codes (product independent range 0x8000-0xFFFF) */
+
+#define MPI_FAULT_REQUEST_MESSAGE_PCI_PARITY_ERROR  (0x8111)
+#define MPI_FAULT_REQUEST_MESSAGE_PCI_BUS_FAULT     (0x8112)
+#define MPI_FAULT_REPLY_MESSAGE_PCI_PARITY_ERROR    (0x8113)
+#define MPI_FAULT_REPLY_MESSAGE_PCI_BUS_FAULT       (0x8114)
+#define MPI_FAULT_DATA_SEND_PCI_PARITY_ERROR        (0x8115)
+#define MPI_FAULT_DATA_SEND_PCI_BUS_FAULT           (0x8116)
+#define MPI_FAULT_DATA_RECEIVE_PCI_PARITY_ERROR     (0x8117)
+#define MPI_FAULT_DATA_RECEIVE_PCI_BUS_FAULT        (0x8118)
+
+
+/*****************************************************************************
+*
+*        P C I    S y s t e m    I n t e r f a c e    R e g i s t e r s
+*
+*****************************************************************************/
+
+/* S y s t e m    D o o r b e l l */
+#define MPI_DOORBELL_OFFSET                 (0x00000000)
+#define MPI_DOORBELL_ACTIVE                 (0x08000000)
+#define MPI_DOORBELL_ACTIVE_SHIFT           (27)
+#define MPI_DOORBELL_WHO_INIT_MASK          (0x07000000)
+#define MPI_DOORBELL_WHO_INIT_SHIFT         (24)
+#define MPI_DOORBELL_FUNCTION_MASK          (0xFF000000)
+#define MPI_DOORBELL_FUNCTION_SHIFT         (24)
+#define MPI_DOORBELL_ADD_DWORDS_MASK        (0x00FF0000)
+#define MPI_DOORBELL_ADD_DWORDS_SHIFT       (16)
+#define MPI_DOORBELL_DATA_MASK              (0x0000FFFF)
+
+
+#define MPI_WRITE_SEQUENCE_OFFSET           (0x00000004)
+#define MPI_WRSEQ_KEY_VALUE_MASK            (0x0000000F)
+#define MPI_WRSEQ_1ST_KEY_VALUE             (0x04)
+#define MPI_WRSEQ_2ND_KEY_VALUE             (0x0B)
+#define MPI_WRSEQ_3RD_KEY_VALUE             (0x02)
+#define MPI_WRSEQ_4TH_KEY_VALUE             (0x07)
+#define MPI_WRSEQ_5TH_KEY_VALUE             (0x0D)
+
+#define MPI_DIAGNOSTIC_OFFSET               (0x00000008)
+#define MPI_DIAG_CLEAR_FLASH_BAD_SIG        (0x00000400)
+#define MPI_DIAG_PREVENT_IOC_BOOT           (0x00000200)
+#define MPI_DIAG_DRWE                       (0x00000080)
+#define MPI_DIAG_FLASH_BAD_SIG              (0x00000040)
+#define MPI_DIAG_RESET_HISTORY              (0x00000020)
+#define MPI_DIAG_RW_ENABLE                  (0x00000010)
+#define MPI_DIAG_RESET_ADAPTER              (0x00000004)
+#define MPI_DIAG_DISABLE_ARM                (0x00000002)
+#define MPI_DIAG_MEM_ENABLE                 (0x00000001)
+
+#define MPI_TEST_BASE_ADDRESS_OFFSET        (0x0000000C)
+
+#define MPI_DIAG_RW_DATA_OFFSET             (0x00000010)
+
+#define MPI_DIAG_RW_ADDRESS_OFFSET          (0x00000014)
+
+#define MPI_HOST_INTERRUPT_STATUS_OFFSET    (0x00000030)
+#define MPI_HIS_IOP_DOORBELL_STATUS         (0x80000000)
+#define MPI_HIS_REPLY_MESSAGE_INTERRUPT     (0x00000008)
+#define MPI_HIS_DOORBELL_INTERRUPT          (0x00000001)
+
+#define MPI_HOST_INTERRUPT_MASK_OFFSET      (0x00000034)
+#define MPI_HIM_RIM                         (0x00000008)
+#define MPI_HIM_DIM                         (0x00000001)
+
+#define MPI_REQUEST_QUEUE_OFFSET            (0x00000040)
+#define MPI_REQUEST_POST_FIFO_OFFSET        (0x00000040)
+
+#define MPI_REPLY_QUEUE_OFFSET              (0x00000044)
+#define MPI_REPLY_POST_FIFO_OFFSET          (0x00000044)
+#define MPI_REPLY_FREE_FIFO_OFFSET          (0x00000044)
+
+
+
+/*****************************************************************************
+*
+*        M e s s a g e    F r a m e    D e s c r i p t o r s
+*
+*****************************************************************************/
+
+#define MPI_REQ_MF_DESCRIPTOR_NB_MASK       (0x00000003)
+#define MPI_REQ_MF_DESCRIPTOR_F_BIT         (0x00000004)
+#define MPI_REQ_MF_DESCRIPTOR_ADDRESS_MASK  (0xFFFFFFF8)
+
+#define MPI_ADDRESS_REPLY_A_BIT             (0x80000000)
+#define MPI_ADDRESS_REPLY_ADDRESS_MASK      (0x7FFFFFFF)
+
+#define MPI_CONTEXT_REPLY_A_BIT             (0x80000000)
+#define MPI_CONTEXT_REPLY_TYPE_MASK         (0x60000000)
+#define MPI_CONTEXT_REPLY_TYPE_SCSI_INIT    (0x00)
+#define MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET  (0x01)
+#define MPI_CONTEXT_REPLY_TYPE_LAN          (0x02)
+#define MPI_CONTEXT_REPLY_TYPE_SHIFT        (29)
+#define MPI_CONTEXT_REPLY_CONTEXT_MASK      (0x1FFFFFFF)
+
+
+/****************************************************************************/
+/* Context Reply macros                                                     */
+/****************************************************************************/
+
+#define MPI_GET_CONTEXT_REPLY_TYPE(x)  (((x) & MPI_CONTEXT_REPLY_TYPE_MASK) \
+                                          >> MPI_CONTEXT_REPLY_TYPE_SHIFT)
+
+#define MPI_SET_CONTEXT_REPLY_TYPE(x, typ)                                  \
+            ((x) = ((x) & ~MPI_CONTEXT_REPLY_TYPE_MASK) |                   \
+                            (((typ) << MPI_CONTEXT_REPLY_TYPE_SHIFT) &      \
+                                        MPI_CONTEXT_REPLY_TYPE_MASK))
+
+
+/*****************************************************************************
+*
+*        M e s s a g e    F u n c t i o n s
+*              0x80 -> 0x8F reserved for private message use per product
+*
+*
+*****************************************************************************/
+
+#define MPI_FUNCTION_SCSI_IO_REQUEST                (0x00)
+#define MPI_FUNCTION_SCSI_TASK_MGMT                 (0x01)
+#define MPI_FUNCTION_IOC_INIT                       (0x02)
+#define MPI_FUNCTION_IOC_FACTS                      (0x03)
+#define MPI_FUNCTION_CONFIG                         (0x04)
+#define MPI_FUNCTION_PORT_FACTS                     (0x05)
+#define MPI_FUNCTION_PORT_ENABLE                    (0x06)
+#define MPI_FUNCTION_EVENT_NOTIFICATION             (0x07)
+#define MPI_FUNCTION_EVENT_ACK                      (0x08)
+#define MPI_FUNCTION_FW_DOWNLOAD                    (0x09)
+#define MPI_FUNCTION_TARGET_CMD_BUFFER_POST         (0x0A)
+#define MPI_FUNCTION_TARGET_ASSIST                  (0x0B)
+#define MPI_FUNCTION_TARGET_STATUS_SEND             (0x0C)
+#define MPI_FUNCTION_TARGET_MODE_ABORT              (0x0D)
+#define MPI_FUNCTION_TARGET_FC_BUF_POST_LINK_SRVC   (0x0E) /* obsolete name */
+#define MPI_FUNCTION_TARGET_FC_RSP_LINK_SRVC        (0x0F) /* obsolete name */
+#define MPI_FUNCTION_TARGET_FC_EX_SEND_LINK_SRVC    (0x10) /* obsolete name */
+#define MPI_FUNCTION_TARGET_FC_ABORT                (0x11) /* obsolete name */
+#define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST          (0x0E)
+#define MPI_FUNCTION_FC_LINK_SRVC_RSP               (0x0F)
+#define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND           (0x10)
+#define MPI_FUNCTION_FC_ABORT                       (0x11)
+#define MPI_FUNCTION_FW_UPLOAD                      (0x12)
+#define MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND       (0x13)
+#define MPI_FUNCTION_FC_PRIMITIVE_SEND              (0x14)
+
+#define MPI_FUNCTION_RAID_VOLUME                    (0x15)
+#define MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH       (0x16)
+
+#define MPI_FUNCTION_LAN_SEND                       (0x20)
+#define MPI_FUNCTION_LAN_RECEIVE                    (0x21)
+#define MPI_FUNCTION_LAN_RESET                      (0x22)
+
+#define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET         (0x40)
+#define MPI_FUNCTION_IO_UNIT_RESET                  (0x41)
+#define MPI_FUNCTION_HANDSHAKE                      (0x42)
+#define MPI_FUNCTION_REPLY_FRAME_REMOVAL            (0x43)
+
+
+
+/*****************************************************************************
+*
+*        S c a t t e r    G a t h e r    E l e m e n t s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Simple element structures                                               */
+/****************************************************************************/
+
+typedef struct _SGE_SIMPLE32
+{
+    U32                     FlagsLength;
+    U32                     Address;
+} SGE_SIMPLE32, MPI_POINTER PTR_SGE_SIMPLE32,
+  SGESimple32_t, MPI_POINTER pSGESimple32_t;
+
+typedef struct _SGE_SIMPLE64
+{
+    U32                     FlagsLength;
+    U64                     Address;
+} SGE_SIMPLE64, MPI_POINTER PTR_SGE_SIMPLE64,
+  SGESimple64_t, MPI_POINTER pSGESimple64_t;
+
+typedef struct _SGE_SIMPLE_UNION
+{
+    U32                     FlagsLength;
+    union
+    {
+        U32                 Address32;
+        U64                 Address64;
+    }u;
+} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t,
+  SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION;
+
+/****************************************************************************/
+/*  Chain element structures                                                */
+/****************************************************************************/
+
+typedef struct _SGE_CHAIN32
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    U32                     Address;
+} SGE_CHAIN32, MPI_POINTER PTR_SGE_CHAIN32,
+  SGEChain32_t, MPI_POINTER pSGEChain32_t;
+
+typedef struct _SGE_CHAIN64
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    U64                     Address;
+} SGE_CHAIN64, MPI_POINTER PTR_SGE_CHAIN64,
+  SGEChain64_t, MPI_POINTER pSGEChain64_t;
+
+typedef struct _SGE_CHAIN_UNION
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    union
+    {
+        U32                 Address32;
+        U64                 Address64;
+    }u;
+} SGE_CHAIN_UNION, MPI_POINTER PTR_SGE_CHAIN_UNION,
+  SGEChainUnion_t, MPI_POINTER pSGEChainUnion_t;
+
+/****************************************************************************/
+/*  Transaction Context element                                             */
+/****************************************************************************/
+
+typedef struct _SGE_TRANSACTION32
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[1];
+    U32                     TransactionDetails[1];
+} SGE_TRANSACTION32, MPI_POINTER PTR_SGE_TRANSACTION32,
+  SGETransaction32_t, MPI_POINTER pSGETransaction32_t;
+
+typedef struct _SGE_TRANSACTION64
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[2];
+    U32                     TransactionDetails[1];
+} SGE_TRANSACTION64, MPI_POINTER PTR_SGE_TRANSACTION64,
+  SGETransaction64_t, MPI_POINTER pSGETransaction64_t;
+
+typedef struct _SGE_TRANSACTION96
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[3];
+    U32                     TransactionDetails[1];
+} SGE_TRANSACTION96, MPI_POINTER PTR_SGE_TRANSACTION96,
+  SGETransaction96_t, MPI_POINTER pSGETransaction96_t;
+
+typedef struct _SGE_TRANSACTION128
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[4];
+    U32                     TransactionDetails[1];
+} SGE_TRANSACTION128, MPI_POINTER PTR_SGE_TRANSACTION128,
+  SGETransaction_t128, MPI_POINTER pSGETransaction_t128;
+
+typedef struct _SGE_TRANSACTION_UNION
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    union
+    {
+        U32                 TransactionContext32[1];
+        U32                 TransactionContext64[2];
+        U32                 TransactionContext96[3];
+        U32                 TransactionContext128[4];
+    }u;
+    U32                     TransactionDetails[1];
+} SGE_TRANSACTION_UNION, MPI_POINTER PTR_SGE_TRANSACTION_UNION,
+  SGETransactionUnion_t, MPI_POINTER pSGETransactionUnion_t;
+
+
+/****************************************************************************/
+/*  SGE IO types union  for IO SGL's                                        */
+/****************************************************************************/
+
+typedef struct _SGE_IO_UNION
+{
+    union
+    {
+        SGE_SIMPLE_UNION    Simple;
+        SGE_CHAIN_UNION     Chain;
+    } u;
+} SGE_IO_UNION, MPI_POINTER PTR_SGE_IO_UNION,
+  SGEIOUnion_t, MPI_POINTER pSGEIOUnion_t;
+
+/****************************************************************************/
+/*  SGE union for SGL's with Simple and Transaction elements                */
+/****************************************************************************/
+
+typedef struct _SGE_TRANS_SIMPLE_UNION
+{
+    union
+    {
+        SGE_SIMPLE_UNION        Simple;
+        SGE_TRANSACTION_UNION   Transaction;
+    } u;
+} SGE_TRANS_SIMPLE_UNION, MPI_POINTER PTR_SGE_TRANS_SIMPLE_UNION,
+  SGETransSimpleUnion_t, MPI_POINTER pSGETransSimpleUnion_t;
+
+/****************************************************************************/
+/*  All SGE types union                                                     */
+/****************************************************************************/
+
+typedef struct _SGE_MPI_UNION
+{
+    union
+    {
+        SGE_SIMPLE_UNION        Simple;
+        SGE_CHAIN_UNION         Chain;
+        SGE_TRANSACTION_UNION   Transaction;
+    } u;
+} SGE_MPI_UNION, MPI_POINTER PTR_SGE_MPI_UNION,
+  MPI_SGE_UNION_t, MPI_POINTER pMPI_SGE_UNION_t,
+  SGEAllUnion_t, MPI_POINTER pSGEAllUnion_t;
+
+
+/****************************************************************************/
+/*  SGE field definition and masks                                          */
+/****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI_SGE_FLAGS_LAST_ELEMENT              (0x80)
+#define MPI_SGE_FLAGS_END_OF_BUFFER             (0x40)
+#define MPI_SGE_FLAGS_ELEMENT_TYPE_MASK         (0x30)
+#define MPI_SGE_FLAGS_LOCAL_ADDRESS             (0x08)
+#define MPI_SGE_FLAGS_DIRECTION                 (0x04)
+#define MPI_SGE_FLAGS_ADDRESS_SIZE              (0x02)
+#define MPI_SGE_FLAGS_END_OF_LIST               (0x01)
+
+#define MPI_SGE_FLAGS_SHIFT                     (24)
+
+#define MPI_SGE_LENGTH_MASK                     (0x00FFFFFF)
+#define MPI_SGE_CHAIN_LENGTH_MASK               (0x0000FFFF)
+
+/* Element Type */
+
+#define MPI_SGE_FLAGS_TRANSACTION_ELEMENT       (0x00)
+#define MPI_SGE_FLAGS_SIMPLE_ELEMENT            (0x10)
+#define MPI_SGE_FLAGS_CHAIN_ELEMENT             (0x30)
+#define MPI_SGE_FLAGS_ELEMENT_MASK              (0x30)
+
+/* Address location */
+
+#define MPI_SGE_FLAGS_SYSTEM_ADDRESS            (0x00)
+
+/* Direction */
+
+#define MPI_SGE_FLAGS_IOC_TO_HOST               (0x00)
+#define MPI_SGE_FLAGS_HOST_TO_IOC               (0x04)
+
+/* Address Size */
+
+#define MPI_SGE_FLAGS_32_BIT_ADDRESSING         (0x00)
+#define MPI_SGE_FLAGS_64_BIT_ADDRESSING         (0x02)
+
+/* Context Size */
+
+#define MPI_SGE_FLAGS_32_BIT_CONTEXT            (0x00)
+#define MPI_SGE_FLAGS_64_BIT_CONTEXT            (0x02)
+#define MPI_SGE_FLAGS_96_BIT_CONTEXT            (0x04)
+#define MPI_SGE_FLAGS_128_BIT_CONTEXT           (0x06)
+
+#define MPI_SGE_CHAIN_OFFSET_MASK               (0x00FF0000)
+#define MPI_SGE_CHAIN_OFFSET_SHIFT              (16)
+
+
+/****************************************************************************/
+/*  SGE operation Macros                                                    */
+/****************************************************************************/
+
+         /* SIMPLE FlagsLength manipulations... */
+#define  MPI_SGE_SET_FLAGS(f)           ((U32)(f) << MPI_SGE_FLAGS_SHIFT)
+#define  MPI_SGE_GET_FLAGS(fl)          (((fl) & ~MPI_SGE_LENGTH_MASK) >> MPI_SGE_FLAGS_SHIFT)
+#define  MPI_SGE_LENGTH(fl)             ((fl) & MPI_SGE_LENGTH_MASK)
+#define  MPI_SGE_CHAIN_LENGTH(fl)       ((fl) & MPI_SGE_CHAIN_LENGTH_MASK)
+
+#define  MPI_SGE_SET_FLAGS_LENGTH(f,l)  (MPI_SGE_SET_FLAGS(f) | MPI_SGE_LENGTH(l))
+
+#define  MPI_pSGE_GET_FLAGS(psg)        MPI_SGE_GET_FLAGS((psg)->FlagsLength)
+#define  MPI_pSGE_GET_LENGTH(psg)       MPI_SGE_LENGTH((psg)->FlagsLength)
+#define  MPI_pSGE_SET_FLAGS_LENGTH(psg,f,l)  (psg)->FlagsLength = MPI_SGE_SET_FLAGS_LENGTH(f,l)
+         /* CAUTION - The following are READ-MODIFY-WRITE! */
+#define  MPI_pSGE_SET_FLAGS(psg,f)      (psg)->FlagsLength |= MPI_SGE_SET_FLAGS(f)
+#define  MPI_pSGE_SET_LENGTH(psg,l)     (psg)->FlagsLength |= MPI_SGE_LENGTH(l)
+
+#define  MPI_GET_CHAIN_OFFSET(x) ((x&MPI_SGE_CHAIN_OFFSET_MASK)>>MPI_SGE_CHAIN_OFFSET_SHIFT)
+
+
+
+/*****************************************************************************
+*
+*        S t a n d a r d    M e s s a g e    S t r u c t u r e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/* Standard message request header for all request messages                 */
+/****************************************************************************/
+
+typedef struct _MSG_REQUEST_HEADER
+{
+    U8                      Reserved[2];      /* function specific */
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];     /* function specific */
+    U8                      MsgFlags;
+    U32                     MsgContext;
+} MSG_REQUEST_HEADER, MPI_POINTER PTR_MSG_REQUEST_HEADER,
+  MPIHeader_t, MPI_POINTER pMPIHeader_t;
+
+
+/****************************************************************************/
+/*  Default Reply                                                           */
+/****************************************************************************/
+
+typedef struct _MSG_DEFAULT_REPLY
+{
+    U8                      Reserved[2];      /* function specific */
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[3];     /* function specific */
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      Reserved2[2];     /* function specific */
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_DEFAULT_REPLY, MPI_POINTER PTR_MSG_DEFAULT_REPLY,
+  MPIDefaultReply_t, MPI_POINTER pMPIDefaultReply_t;
+
+
+/* MsgFlags definition for all replies */
+
+#define MPI_MSGFLAGS_CONTINUATION_REPLY         (0x80)
+
+
+/*****************************************************************************
+*
+*               I O C    S t a t u s   V a l u e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Common IOCStatus values for all replies                                 */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_SUCCESS                  (0x0000)
+#define MPI_IOCSTATUS_INVALID_FUNCTION         (0x0001)
+#define MPI_IOCSTATUS_BUSY                     (0x0002)
+#define MPI_IOCSTATUS_INVALID_SGL              (0x0003)
+#define MPI_IOCSTATUS_INTERNAL_ERROR           (0x0004)
+#define MPI_IOCSTATUS_RESERVED                 (0x0005)
+#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES   (0x0006)
+#define MPI_IOCSTATUS_INVALID_FIELD            (0x0007)
+#define MPI_IOCSTATUS_INVALID_STATE            (0x0008)
+
+/****************************************************************************/
+/*  Config IOCStatus values                                                 */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION    (0x0020)
+#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE      (0x0021)
+#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE      (0x0022)
+#define MPI_IOCSTATUS_CONFIG_INVALID_DATA      (0x0023)
+#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS       (0x0024)
+#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT       (0x0025)
+
+/****************************************************************************/
+/*  SCSIIO Reply (SPI & FCP) initiator values                               */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR     (0x0040)
+#define MPI_IOCSTATUS_SCSI_INVALID_BUS         (0x0041)
+#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID    (0x0042)
+#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE    (0x0043)
+#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN        (0x0044)
+#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN       (0x0045)
+#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR       (0x0046)
+#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR      (0x0047)
+#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED     (0x0048)
+#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH   (0x0049)
+#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED    (0x004A)
+#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED      (0x004B)
+#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED      (0x004C)
+
+/****************************************************************************/
+/*  SCSI (SPI & FCP) target values                                          */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_TARGET_PRIORITY_IO         (0x0060)
+#define MPI_IOCSTATUS_TARGET_INVALID_PORT        (0x0061)
+#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX    (0x0062)
+#define MPI_IOCSTATUS_TARGET_ABORTED             (0x0063)
+#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE   (0x0064)
+#define MPI_IOCSTATUS_TARGET_NO_CONNECTION       (0x0065)
+#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
+#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT   (0x006B)
+
+/****************************************************************************/
+/*  Additional FCP target values                                            */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_TARGET_FC_ABORTED         (0x0066)    /* obsolete */
+#define MPI_IOCSTATUS_TARGET_FC_RX_ID_INVALID   (0x0067)    /* obsolete */
+#define MPI_IOCSTATUS_TARGET_FC_DID_INVALID     (0x0068)    /* obsolete */
+#define MPI_IOCSTATUS_TARGET_FC_NODE_LOGGED_OUT (0x0069)    /* obsolete */
+
+/****************************************************************************/
+/*  Fibre Channel Direct Access values                                      */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_FC_ABORTED                (0x0066)
+#define MPI_IOCSTATUS_FC_RX_ID_INVALID          (0x0067)
+#define MPI_IOCSTATUS_FC_DID_INVALID            (0x0068)
+#define MPI_IOCSTATUS_FC_NODE_LOGGED_OUT        (0x0069)
+
+/****************************************************************************/
+/*  LAN values                                                              */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND      (0x0080)
+#define MPI_IOCSTATUS_LAN_DEVICE_FAILURE        (0x0081)
+#define MPI_IOCSTATUS_LAN_TRANSMIT_ERROR        (0x0082)
+#define MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED      (0x0083)
+#define MPI_IOCSTATUS_LAN_RECEIVE_ERROR         (0x0084)
+#define MPI_IOCSTATUS_LAN_RECEIVE_ABORTED       (0x0085)
+#define MPI_IOCSTATUS_LAN_PARTIAL_PACKET        (0x0086)
+#define MPI_IOCSTATUS_LAN_CANCELED              (0x0087)
+
+
+/****************************************************************************/
+/*  IOCStatus flag to indicate that log info is available                   */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE   (0x8000)
+#define MPI_IOCSTATUS_MASK                      (0x7FFF)
+
+/****************************************************************************/
+/*  LogInfo Types                                                           */
+/****************************************************************************/
+
+#define MPI_IOCLOGINFO_TYPE_MASK                (0xF0000000)
+#define MPI_IOCLOGINFO_TYPE_NONE                (0x00)
+#define MPI_IOCLOGINFO_TYPE_SCSI                (0x01)
+#define MPI_IOCLOGINFO_TYPE_FC                  (0x02)
+#define MPI_IOCLOGINFO_LOG_DATA_MASK            (0x0FFFFFFF)
+
+
+#endif
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_cnfg.h linux/drivers/message/fusion/lsi/mpi_cnfg.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_cnfg.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_cnfg.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,971 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_CNFG.H
+ *          Title:  MPI Config message, structures, and Pages
+ *  Creation Date:  July 27, 2000
+ *
+ *    MPI Version:  01.01.09
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-08-00  01.00.02  Added _PAGEVERSION definitions for all pages.
+ *                      Added FcPhLowestVersion, FcPhHighestVersion, Reserved2
+ *                      fields to FC_DEVICE_0 page, updated the page version.
+ *                      Changed _FREE_RUNNING_CLOCK to _PACING_TRANSFERS in
+ *                      SCSI_PORT_0, SCSI_DEVICE_0 and SCSI_DEVICE_1 pages
+ *                      and updated the page versions.
+ *                      Added _RESPONSE_ID_MASK definition to SCSI_PORT_1
+ *                      page and updated the page version.
+ *                      Added Information field and _INFO_PARAMS_NEGOTIATED
+ *                      definitionto SCSI_DEVICE_0 page.
+ *  06-22-00  01.00.03  Removed batch controls from LAN_0 page and updated the
+ *                      page version.
+ *                      Added BucketsRemaining to LAN_1 page, redefined the
+ *                      state values, and updated the page version.
+ *                      Revised bus width definitions in SCSI_PORT_0,
+ *                      SCSI_DEVICE_0 and SCSI_DEVICE_1 pages.
+ *  06-30-00  01.00.04  Added MaxReplySize to LAN_1 page and updated the page
+ *                      version.
+ *                      Moved FC_DEVICE_0 PageAddress description to spec.
+ *  07-27-00  01.00.05  Corrected the SubsystemVendorID and SubsystemID field
+ *                      widths in IOC_0 page and updated the page version.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *                      Added Manufacturing pages, IO Unit Page 2, SCSI SPI
+ *                      Port Page 2, FC Port Page 4, FC Port Page 5
+ *  11-15-00  01.01.02  Interim changes to match proposals
+ *  12-04-00  01.01.03  Config page changes to match MPI rev 1.00.01.
+ *  12-05-00  01.01.04  Modified config page actions.
+ *  01-09-01  01.01.05  Added defines for page address formats.
+ *                      Data size for Manufacturing pages 2 and 3 no longer
+ *                      defined here.
+ *                      Io Unit Page 2 size is fixed at 4 adapters and some
+ *                      flags were changed.
+ *                      SCSI Port Page 2 Device Settings modified.
+ *                      New fields added to FC Port Page 0 and some flags
+ *                      cleaned up.
+ *                      Removed impedance flash from FC Port Page 1.
+ *                      Added FC Port pages 6 and 7.
+ *  01-25-01  01.01.06  Added MaxInitiators field to FcPortPage0.
+ *  01-29-01  01.01.07  Changed some defines to make them 32 character unique.
+ *                      Added some LinkType defines for FcPortPage0.
+ *  02-20-01  01.01.08  Started using MPI_POINTER.
+ *  02-27-01  01.01.09  Replaced MPI_CONFIG_PAGETYPE_SCSI_LUN with
+ *                      MPI_CONFIG_PAGETYPE_RAID_VOLUME.
+ *                      Added definitions and structures for IOC Page 2 and
+ *                      RAID Volume Page 2.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_CNFG_H
+#define MPI_CNFG_H
+
+
+/*****************************************************************************
+*
+*       C o n f i g    M e s s a g e    a n d    S t r u c t u r e s
+*
+*****************************************************************************/
+
+typedef struct _CONFIG_PAGE_HEADER
+{
+    U8                      PageVersion;
+    U8                      PageLength;
+    U8                      PageNumber;
+    U8                      PageType;
+} fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER,
+  ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t;
+
+typedef union _CONFIG_PAGE_HEADER_UNION
+{
+   ConfigPageHeader_t  Struct;
+   U8                  Bytes[4];
+   U16                 Word16[2];
+   U32                 Word32;
+} ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion,
+  fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
+
+
+/****************************************************************************/
+/*  PageType field values                                                   */
+/****************************************************************************/
+#define MPI_CONFIG_PAGEATTR_READ_ONLY               (0x00)
+#define MPI_CONFIG_PAGEATTR_CHANGEABLE              (0x10)
+#define MPI_CONFIG_PAGEATTR_PERSISTENT              (0x20)
+#define MPI_CONFIG_PAGEATTR_MASK                    (0xF0)
+
+#define MPI_CONFIG_PAGETYPE_IO_UNIT                 (0x00)
+#define MPI_CONFIG_PAGETYPE_IOC                     (0x01)
+#define MPI_CONFIG_PAGETYPE_BIOS                    (0x02)
+#define MPI_CONFIG_PAGETYPE_SCSI_PORT               (0x03)
+#define MPI_CONFIG_PAGETYPE_SCSI_DEVICE             (0x04)
+#define MPI_CONFIG_PAGETYPE_FC_PORT                 (0x05)
+#define MPI_CONFIG_PAGETYPE_FC_DEVICE               (0x06)
+#define MPI_CONFIG_PAGETYPE_LAN                     (0x07)
+#define MPI_CONFIG_PAGETYPE_RAID_VOLUME             (0x08)
+#define MPI_CONFIG_PAGETYPE_MANUFACTURING           (0x09)
+#define MPI_CONFIG_PAGETYPE_MASK                    (0x0F)
+
+#define MPI_CONFIG_TYPENUM_MASK                     (0x0FFF)
+
+
+/****************************************************************************
+ *  PageAddres field values
+ ****************************************************************************/
+#define MPI_SCSI_PORT_PGAD_PORT_MASK                (0x000000FF)
+
+#define MPI_SCSI_DEVICE_TARGET_ID_MASK              (0x000000FF)
+#define MPI_SCSI_DEVICE_TARGET_ID_SHIFT             (0)
+#define MPI_SCSI_DEVICE_BUS_MASK                    (0x0000FF00)
+#define MPI_SCSI_DEVICE_BUS_SHIFT                   (8)
+
+#define MPI_SCSI_LUN_TARGET_ID_MASK                 (0x000000FF)
+#define MPI_SCSI_LUN_TARGET_ID_SHIFT                (0)
+#define MPI_SCSI_LUN_BUS_MASK                       (0x0000FF00)
+#define MPI_SCSI_LUN_BUS_SHIFT                      (8)
+#define MPI_SCSI_LUN_LUN_MASK                       (0x00FF0000)
+#define MPI_SCSI_LUN_LUN_SHIFT                      (16)
+
+#define MPI_FC_PORT_PGAD_PORT_MASK                  (0xF0000000)
+#define MPI_FC_PORT_PGAD_PORT_SHIFT                 (28)
+#define MPI_FC_PORT_PGAD_FORM_MASK                  (0x0F000000)
+#define MPI_FC_PORT_PGAD_FORM_INDEX                 (0x01000000)
+#define MPI_FC_PORT_PGAD_INDEX_MASK                 (0x0000FFFF)
+#define MPI_FC_PORT_PGAD_INDEX_SHIFT                (0)
+
+#define MPI_FC_DEVICE_PGAD_PORT_MASK                (0xF0000000)
+#define MPI_FC_DEVICE_PGAD_PORT_SHIFT               (28)
+#define MPI_FC_DEVICE_PGAD_FORM_MASK                (0x0F000000)
+#define MPI_FC_DEVICE_PGAD_FORM_NEXT_DID            (0x00000000)
+#define MPI_FC_DEVICE_PGAD_ND_PORT_MASK             (0xF0000000)
+#define MPI_FC_DEVICE_PGAD_ND_PORT_SHIFT            (28)
+#define MPI_FC_DEVICE_PGAD_ND_DID_MASK              (0x00FFFFFF)
+#define MPI_FC_DEVICE_PGAD_ND_DID_SHIFT             (0)
+#define MPI_FC_DEVICE_PGAD_FORM_BUS_TID             (0x01000000)
+#define MPI_FC_DEVICE_PGAD_BT_BUS_MASK              (0x0000FF00)
+#define MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT             (8)
+#define MPI_FC_DEVICE_PGAD_BT_TID_MASK              (0x000000FF)
+#define MPI_FC_DEVICE_PGAD_BT_TID_SHIFT             (0)
+
+
+/****************************************************************************/
+/*  Config Request Message                                                          */
+/****************************************************************************/
+typedef struct _MSG_CONFIG
+{
+    U8                      Action;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      Reserved2[8];
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     PageAddress;
+    SGE_IO_UNION            PageBufferSGE;
+} MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG,
+  Config_t, MPI_POINTER pConfig_t;
+
+
+/****************************************************************************/
+/*  Action field values                                                     */
+/****************************************************************************/
+#define MPI_CONFIG_ACTION_PAGE_HEADER               (0x00)
+/*#define MPI_CONFIG_ACTION_PAGE_READ                 (0x01) *//* obsolete */
+#define MPI_CONFIG_ACTION_PAGE_READ_CURRENT         (0x01)
+/*#define MPI_CONFIG_ACTION_PAGE_WRITE                (0x02) *//* obsolete */
+#define MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT        (0x02)
+#define MPI_CONFIG_ACTION_PAGE_DEFAULT              (0x03)
+/*#define MPI_CONFIG_ACTION_PAGE_WRITE_COMMIT         (0x04) */ /* obsolete */
+#define MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM          (0x04)
+#define MPI_CONFIG_ACTION_PAGE_READ_DEFAULT         (0x05)
+#define MPI_CONFIG_ACTION_PAGE_READ_NVRAM           (0x06)
+
+
+/* Config Reply Message */
+typedef struct _MSG_CONFIG_REPLY
+{
+    U8                      Action;
+    U8                      Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      Reserved2[2];
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+   fCONFIG_PAGE_HEADER      Header;
+} MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY,
+  ConfigReply_t, MPI_POINTER pConfigReply_t;
+
+
+
+/*****************************************************************************
+*
+*               C o n f i g u r a t i o n    P a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Manufacturing Config pages                                              */
+/****************************************************************************/
+#define MPI_MANUFACTPAGE_DEVICEID_FC909             (0x0621)
+#define MPI_MANUFACTPAGE_DEVICEID_FC919             (0x0624)
+#define MPI_MANUFACTPAGE_DEVICEID_FC929             (0x0622)
+#define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
+#define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
+#define MPI_MANUFACTPAGE_DEVID_53C1035              (0x0035)
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U8                      ChipName[16];
+    U8                      ChipRevision[8];
+    U8                      BoardName[16];
+    U8                      BoardAssembly[16];
+    U8                      BoardTracerNumber[16];
+
+} fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0,
+  ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t;
+
+#define MPI_MANUFACTURING0_PAGEVERSION                 (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U8                      VPD[256];
+} fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1,
+  ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t;
+
+#define MPI_MANUFACTURING1_PAGEVERSION                 (0x00)
+
+
+typedef struct _MPI_CHIP_REVISION_ID
+{
+    U16 DeviceID;
+    U8  PCIRevisionID;
+    U8  Reserved;
+} MPI_CHIP_REVISION_ID, MPI_POINTER PTR_MPI_CHIP_REVISION_ID,
+  MpiChipRevisionId_t, MPI_POINTER pMpiChipRevisionId_t;
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_2
+{
+   fCONFIG_PAGE_HEADER                  Header;
+    MPI_CHIP_REVISION_ID                ChipId;
+    U32                                 HwSettings[1];
+} fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2,
+  ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t;
+
+#define MPI_MANUFACTURING2_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_3
+{
+   fCONFIG_PAGE_HEADER                  Header;
+    MPI_CHIP_REVISION_ID                ChipId;
+    U32                                 Info[1];
+} fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3,
+  ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t;
+
+#define MPI_MANUFACTURING3_PAGEVERSION                  (0x00)
+
+
+/****************************************************************************/
+/*  IO Unit Config Pages                                                    */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_IO_UNIT_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U64                     UniqueValue;
+} fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0,
+  IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t;
+
+#define MPI_IOUNITPAGE0_PAGEVERSION                     (0x00)
+
+
+typedef struct _CONFIG_PAGE_IO_UNIT_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Flags;
+} fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
+  IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
+
+#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x00)
+
+#define MPI_IOUNITPAGE1_MULTI_FUNCTION                  (0x00000000)
+#define MPI_IOUNITPAGE1_SINGLE_FUNCTION                 (0x00000001)
+#define MPI_IOUNITPAGE1_MULTI_PATHING                   (0x00000002)
+#define MPI_IOUNITPAGE1_SINGLE_PATHING                  (0x00000000)
+
+#define MPI_IOUNITPAGE1_FORCE_32                        (0x00000080)
+
+
+typedef struct _MPI_ADAPTER_INFO
+{
+    U8      PciBusNumber;
+    U8      PciDeviceAndFunctionNumber;
+    U16     AdapterFlags;
+} MPI_ADAPTER_INFO, MPI_POINTER PTR_MPI_ADAPTER_INFO,
+  MpiAdapterInfo_t, MPI_POINTER pMpiAdapterInfo_t;
+
+#define MPI_ADAPTER_INFO_FLAGS_EMBEDDED                 (0x0001)
+#define MPI_ADAPTER_INFO_FLAGS_INIT_STATUS              (0x0002)
+
+typedef struct _CONFIG_PAGE_IO_UNIT_2
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Flags;
+    U32                     BiosVersion;
+    MPI_ADAPTER_INFO        AdapterOrder[4];
+} fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2,
+  IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t;
+
+#define MPI_IOUNITPAGE2_PAGEVERSION                     (0x00)
+
+#define MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE              (0x00000001)
+#define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR            (0x00000002)
+#define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE            (0x00000004)
+#define MPI_IOUNITPAGE2_FLAGS_COLOR_VIDEO_DISABLE       (0x00000008)
+#define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40          (0x00000010)
+
+
+/****************************************************************************/
+/*  IOC Config Pages                                                        */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_IOC_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     TotalNVStore;
+    U32                     FreeNVStore;
+    U16                     VendorID;
+    U16                     DeviceID;
+    U8                      RevisionID;
+    U8                      Reserved[3];
+    U32                     ClassCode;
+    U16                     SubsystemVendorID;
+    U16                     SubsystemID;
+} fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0,
+  IOCPage0_t, MPI_POINTER pIOCPage0_t;
+
+#define MPI_IOCPAGE0_PAGEVERSION                        (0x01)
+
+typedef struct _CONFIG_PAGE_IOC_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Flags;
+    U32                     CoalescingTimeout;
+    U8                      CoalescingDepth;
+    U8                      Reserved[3];
+} fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
+  IOCPage1_t, MPI_POINTER pIOCPage1_t;
+
+#define MPI_IOCPAGE1_PAGEVERSION                        (0x00)
+
+#define MPI_IOCPAGE1_REPLY_COALESCING                   (0x00000001)
+
+typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL
+{
+    U8                      VolumeTargetID;
+    U8                      VolumeBus;
+    U16                     Reserved;
+    U8                      VolumeVersionMinor;
+    U8                      VolumeVersionMajor;
+    U8                      VolumeRaidType;
+    U8                      Reserved1;
+} fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL,
+  ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t;
+
+typedef struct _CONFIG_PAGE_IOC_2
+{
+   fCONFIG_PAGE_HEADER          Header;
+    U32                         CapabilitiesFlags;
+    U8                          NumActiveVolumes;
+    U8                          MaxVolumes;
+    U16                         Reserved;
+   fCONFIG_PAGE_IOC_2_RAID_VOL  RaidVolume[1];
+} fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
+  IOCPage2_t, MPI_POINTER pIOCPage2_t;
+
+#define MPI_IOCPAGE2_PAGEVERSION                        (0x00)
+
+/* IOC Page 2 Capabilities flags */
+
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_0_SUPPORT           (0x00000001)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_1_SUPPORT           (0x00000002)
+#define MPI_IOCPAGE2_CAP_FLAGS_LSI_MIRROR_SUPPORT       (0x00000004)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT           (0x00000008)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT          (0x00000010)
+
+/* IOC Page 2 Volume RAID Type values */
+
+#define MPI_IOCPAGE2_VOL_TYPE_RAID_0                    (0x00)
+#define MPI_IOCPAGE2_VOL_TYPE_RAID_1                    (0x01)
+#define MPI_IOCPAGE2_VOL_TYPE_LSI_MIRROR                (0x02)
+#define MPI_IOCPAGE2_VOL_TYPE_RAID_5                    (0x05)
+#define MPI_IOCPAGE2_VOL_TYPE_RAID_10                   (0x0A)
+
+
+/****************************************************************************/
+/*  SCSI Port Config Pages                                                  */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_SCSI_PORT_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Capabilities;
+    U32                     PhysicalInterface;
+} fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0,
+  SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t;
+
+#define MPI_SCSIPORTPAGE0_PAGEVERSION                   (0x01)
+
+#define MPI_SCSIPORTPAGE0_CAP_IU                        (0x00000001)
+#define MPI_SCSIPORTPAGE0_CAP_DT                        (0x00000002)
+#define MPI_SCSIPORTPAGE0_CAP_QAS                       (0x00000004)
+#define MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS          (0x00000008)
+#define MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK      (0x0000FF00)
+#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK      (0x00FF0000)
+#define MPI_SCSIPORTPAGE0_CAP_WIDE                      (0x20000000)
+#define MPI_SCSIPORTPAGE0_CAP_AIP                       (0x80000000)
+
+#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK          (0x00000003)
+#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD                (0x01)
+#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE                 (0x02)
+#define MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD                (0x03)
+
+typedef struct _CONFIG_PAGE_SCSI_PORT_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Configuration;
+} fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
+  SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t;
+
+#define MPI_SCSIPORTPAGE1_PAGEVERSION                   (0x01)
+
+#define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK         (0x000000FF)
+#define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK     (0xFFFF0000)
+
+typedef struct _MPI_DEVICE_INFO
+{
+    U8      Timeout;
+    U8      SyncFactor;
+    U16     DeviceFlags;
+} MPI_DEVICE_INFO, MPI_POINTER PTR_MPI_DEVICE_INFO,
+  MpiDeviceInfo_t, MPI_POINTER pMpiDeviceInfo_t;
+
+typedef struct _CONFIG_PAGE_SCSI_PORT_2
+{
+   fCONFIG_PAGE_HEADER  Header;
+    U32                 PortFlags;
+    U32                 PortSettings;
+    MPI_DEVICE_INFO     DeviceSettings[16];
+} fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2,
+  SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t;
+
+#define MPI_SCSIPORTPAGE2_PAGEVERSION                       (0x01)
+
+#define MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW       (0x00000001)
+#define MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE          (0x00000002)
+#define MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET       (0x00000004)
+#define MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS          (0x00000008)
+#define MPI_SCSIPORTPAGE2_PORT_FLAGS_TERMINATION_DISABLE    (0x00000010)
+
+#define MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK                 (0x0000000F)
+#define MPI_SCSIPORTPAGE2_PORT_MASK_INIT_HBA                (0x00000030)
+#define MPI_SCSIPORTPAGE2_PORT_DISABLE_INIT_HBA             (0x00000000)
+#define MPI_SCSIPORTPAGE2_PORT_BIOS_INIT_HBA                (0x00000010)
+#define MPI_SCSIPORTPAGE2_PORT_OS_INIT_HBA                  (0x00000020)
+#define MPI_SCSIPORTPAGE2_PORT_BIOS_OS_INIT_HBA             (0x00000030)
+#define MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA              (0x000000C0)
+#define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK            (0x00000F00)
+#define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS    (0x00003000)
+#define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS         (0x00000000)
+#define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS         (0x00000001)
+#define MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS          (0x00000003)
+
+#define MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE          (0x00000001)
+#define MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE             (0x00000002)
+#define MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE            (0x00000004)
+#define MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE           (0x00000008)
+#define MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE               (0x00000010)
+#define MPI_SCSIPORTPAGE2_DEVICE_BOOT_CHOICE                (0x00000020)
+
+
+/****************************************************************************/
+/*  SCSI Target Device Config Pages                                         */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_SCSI_DEVICE_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     NegotiatedParameters;
+    U32                     Information;
+} fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0,
+  SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t;
+
+#define MPI_SCSIDEVPAGE0_PAGEVERSION                    (0x01)
+
+#define MPI_SCSIDEVPAGE0_NP_IU                          (0x00000001)
+#define MPI_SCSIDEVPAGE0_NP_DT                          (0x00000002)
+#define MPI_SCSIDEVPAGE0_NP_QAS                         (0x00000004)
+#define MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS            (0x00000008)
+#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK        (0x0000FF00)
+#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK        (0x00FF0000)
+#define MPI_SCSIDEVPAGE0_NP_WIDE                        (0x20000000)
+#define MPI_SCSIDEVPAGE0_NP_AIP                         (0x80000000)
+
+#define MPI_SCSIDEVPAGE0_INFO_PARAMS_NEGOTIATED         (0x00000001)
+
+typedef struct _CONFIG_PAGE_SCSI_DEVICE_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     RequestedParameters;
+    U32                     DomainValidation;
+    U32                     Configuration;
+} fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1,
+  SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t;
+
+#define MPI_SCSIDEVPAGE1_PAGEVERSION                    (0x01)
+
+#define MPI_SCSIDEVPAGE1_RP_IU                          (0x00000001)
+#define MPI_SCSIDEVPAGE1_RP_DT                          (0x00000002)
+#define MPI_SCSIDEVPAGE1_RP_QAS                         (0x00000004)
+#define MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS            (0x00000008)
+#define MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK        (0x0000FF00)
+#define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK        (0x00FF0000)
+#define MPI_SCSIDEVPAGE1_RP_WIDE                        (0x20000000)
+#define MPI_SCSIDEVPAGE1_RP_AIP                         (0x80000000)
+
+#define MPI_SCSIDEVPAGE1_DV_LVD_DRIVE_STRENGTH_MASK     (0x00000003)
+#define MPI_SCSIDEVPAGE1_DV_SE_SLEW_RATE_MASK           (0x00000300)
+
+#define MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED               (0x00000001)
+
+/****************************************************************************/
+/*  FC Port Config Pages                                                    */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_FC_PORT_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Flags;
+    U8                      MPIPortNumber;
+    U8                      LinkType;
+    U8                      PortState;
+    U8                      Reserved;
+    U32                     PortIdentifier;
+    U64                     WWNN;
+    U64                     WWPN;
+    U32                     SupportedServiceClass;
+    U32                     SupportedSpeeds;
+    U32                     CurrentSpeed;
+    U32                     MaxFrameSize;
+    U64                     FabricWWNN;
+    U64                     FabricWWPN;
+    U32                     DiscoveredPortsCount;
+    U32                     MaxInitiators;
+} fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0,
+  FCPortPage0_t, MPI_POINTER pFCPortPage0_t;
+
+#define MPI_FCPORTPAGE0_PAGEVERSION                     (0x01)
+
+#define MPI_FCPORTPAGE0_FLAGS_PROT_MASK                 (0x0000000F)
+#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_INIT             (MPI_PORTFACTS_PROTOCOL_INITIATOR)
+#define MPI_FCPORTPAGE0_FLAGS_PROT_FCP_TARG             (MPI_PORTFACTS_PROTOCOL_TARGET)
+#define MPI_FCPORTPAGE0_FLAGS_PROT_LAN                  (MPI_PORTFACTS_PROTOCOL_LAN)
+#define MPI_FCPORTPAGE0_FLAGS_PROT_LOGBUSADDR           (MPI_PORTFACTS_PROTOCOL_LOGBUSADDR)
+
+#define MPI_FCPORTPAGE0_FLAGS_ALIAS_ALPA_SUPPORTED      (0x00000010)
+#define MPI_FCPORTPAGE0_FLAGS_ALIAS_WWN_SUPPORTED       (0x00000020)
+#define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID          (0x00000030)
+
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK          (0x00000700)
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT     (0x00000000)
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP       (0x00000100)
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT      (0x00000200)
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP        (0x00000300)
+#define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT            (0x00000700)
+
+#define MPI_FCPORTPAGE0_LTYPE_RESERVED                  (0x00)
+#define MPI_FCPORTPAGE0_LTYPE_OTHER                     (0x01)
+#define MPI_FCPORTPAGE0_LTYPE_UNKNOWN                   (0x02)
+#define MPI_FCPORTPAGE0_LTYPE_COPPER                    (0x03)
+#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1300               (0x04)
+#define MPI_FCPORTPAGE0_LTYPE_SINGLE_1500               (0x05)
+#define MPI_FCPORTPAGE0_LTYPE_50_LASER_MULTI            (0x06)
+#define MPI_FCPORTPAGE0_LTYPE_50_LED_MULTI              (0x07)
+#define MPI_FCPORTPAGE0_LTYPE_62_LASER_MULTI            (0x08)
+#define MPI_FCPORTPAGE0_LTYPE_62_LED_MULTI              (0x09)
+#define MPI_FCPORTPAGE0_LTYPE_MULTI_LONG_WAVE           (0x0A)
+#define MPI_FCPORTPAGE0_LTYPE_MULTI_SHORT_WAVE          (0x0B)
+#define MPI_FCPORTPAGE0_LTYPE_LASER_SHORT_WAVE          (0x0C)
+#define MPI_FCPORTPAGE0_LTYPE_LED_SHORT_WAVE            (0x0D)
+#define MPI_FCPORTPAGE0_LTYPE_1300_LONG_WAVE            (0x0E)
+#define MPI_FCPORTPAGE0_LTYPE_1500_LONG_WAVE            (0x0F)
+
+#define MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN               (0x01)      /*(SNIA)HBA_PORTSTATE_UNKNOWN       1 Unknown */
+#define MPI_FCPORTPAGE0_PORTSTATE_ONLINE                (0x02)      /*(SNIA)HBA_PORTSTATE_ONLINE        2 Operational */
+#define MPI_FCPORTPAGE0_PORTSTATE_OFFLINE               (0x03)      /*(SNIA)HBA_PORTSTATE_OFFLINE       3 User Offline */
+#define MPI_FCPORTPAGE0_PORTSTATE_BYPASSED              (0x04)      /*(SNIA)HBA_PORTSTATE_BYPASSED      4 Bypassed */
+#define MPI_FCPORTPAGE0_PORTSTATE_DIAGNOST              (0x05)      /*(SNIA)HBA_PORTSTATE_DIAGNOSTICS   5 In diagnostics mode */
+#define MPI_FCPORTPAGE0_PORTSTATE_LINKDOWN              (0x06)      /*(SNIA)HBA_PORTSTATE_LINKDOWN      6 Link Down */
+#define MPI_FCPORTPAGE0_PORTSTATE_ERROR                 (0x07)      /*(SNIA)HBA_PORTSTATE_ERROR         7 Port Error */
+#define MPI_FCPORTPAGE0_PORTSTATE_LOOPBACK              (0x08)      /*(SNIA)HBA_PORTSTATE_LOOPBACK      8 Loopback */
+
+#define MPI_FCPORTPAGE0_SUPPORT_CLASS_1                 (0x00000001)
+#define MPI_FCPORTPAGE0_SUPPORT_CLASS_2                 (0x00000002)
+#define MPI_FCPORTPAGE0_SUPPORT_CLASS_3                 (0x00000004)
+
+#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED             (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1  1 GBit/sec  */
+#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED             (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2  2 GBit/sec  */
+#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED            (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */
+
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT             MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT             MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT            MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_1
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Flags;
+    U64                     NoSEEPROMWWNN;
+    U64                     NoSEEPROMWWPN;
+    U8                      HardALPA;
+    U8                      LinkConfig;
+    U8                      TopologyConfig;
+    U8                      Reserved;
+} fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
+  FCPortPage1_t, MPI_POINTER pFCPortPage1_t;
+
+#define MPI_FCPORTPAGE1_PAGEVERSION                     (0x01)
+
+#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID               (0x00000001)
+#define MPI_FCPORTPAGE1_FLAGS_SORT_BY_WWN               (0x00000000)
+
+#define MPI_FCPORTPAGE1_FLAGS_PROT_MASK                 (0xF0000000)
+#define MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT                (28)
+#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT             ((U32)MPI_PORTFACTS_PROTOCOL_INITIATOR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT)
+#define MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG             ((U32)MPI_PORTFACTS_PROTOCOL_TARGET << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT)
+#define MPI_FCPORTPAGE1_FLAGS_PROT_LAN                  ((U32)MPI_PORTFACTS_PROTOCOL_LAN << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT)
+#define MPI_FCPORTPAGE1_FLAGS_PROT_LOGBUSADDR           ((U32)MPI_PORTFACTS_PROTOCOL_LOGBUSADDR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT)
+
+#define MPI_FCPORTPAGE1_HARD_ALPA_NOT_USED              (0xFF)
+
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK              (0x0F)
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_1GIG              (0x00)
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_2GIG              (0x01)
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_4GIG              (0x02)
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_10GIG             (0x03)
+#define MPI_FCPORTPAGE1_LCONFIG_SPEED_AUTO              (0x0F)
+
+#define MPI_FCPORTPAGE1_TOPOLGY_MASK                    (0x0F)
+#define MPI_FCPORTPAGE1_TOPOLGY_NLPORT                  (0x01)
+#define MPI_FCPORTPAGE1_TOPOLGY_NPORT                   (0x02)
+#define MPI_FCPORTPAGE1_TOPOLGY_AUTO                    (0x0F)
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_2
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U8                      NumberActive;
+    U8                      ALPA[126];
+    U8                      Reserved;
+} fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2,
+  FCPortPage2_t, MPI_POINTER pFCPortPage2_t;
+
+#define MPI_FCPORTPAGE2_PAGEVERSION                     (0x00)
+
+
+typedef struct _FC_PORT_PERSISTENT
+{
+    U64                     WWNN;
+    U64                     WWPN;
+    U8                      TargetID;
+    U8                      Bus;
+    U16                     Flags;
+} FC_PORT_PERSISTENT, MPI_POINTER PTR_FC_PORT_PERSISTENT,
+  PersistentData_t, MPI_POINTER pPersistentData_t;
+
+#define MPI_PERSISTENT_FLAGS_SHIFT                      (16)
+#define MPI_PERSISTENT_FLAGS_ENTRY_VALID                (0x0001)
+#define MPI_PERSISTENT_FLAGS_SCAN_ID                    (0x0002)
+#define MPI_PERSISTENT_FLAGS_SCAN_LUNS                  (0x0004)
+#define MPI_PERSISTENT_FLAGS_BOOT_DEVICE                (0x0008)
+
+typedef struct _CONFIG_PAGE_FC_PORT_3
+{
+   fCONFIG_PAGE_HEADER      Header;
+    FC_PORT_PERSISTENT      Entry[1];
+} fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3,
+  FCPortPage3_t, MPI_POINTER pFCPortPage3_t;
+
+#define MPI_FCPORTPAGE3_PAGEVERSION                     (0x00)
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_4
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     PortFlags;
+    U32                     PortSettings;
+} fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4,
+  FCPortPage4_t, MPI_POINTER pFCPortPage4_t;
+
+#define MPI_FCPORTPAGE4_PAGEVERSION                     (0x00)
+
+#define MPI_FCPORTPAGE4_PORT_FLAGS_ALTERNATE_CHS        (0x00000008)
+
+#define MPI_FCPORTPAGE4_PORT_MASK_INIT_HBA              (0x00000030)
+#define MPI_FCPORTPAGE4_PORT_DISABLE_INIT_HBA           (0x00000000)
+#define MPI_FCPORTPAGE4_PORT_BIOS_INIT_HBA              (0x00000010)
+#define MPI_FCPORTPAGE4_PORT_OS_INIT_HBA                (0x00000020)
+#define MPI_FCPORTPAGE4_PORT_BIOS_OS_INIT_HBA           (0x00000030)
+#define MPI_FCPORTPAGE4_PORT_REMOVABLE_MEDIA            (0x000000C0)
+#define MPI_FCPORTPAGE4_PORT_SPINUP_DELAY_MASK          (0x00000F00)
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO
+{
+    U8      Flags;
+    U8      AliasAlpa;
+    U16     Reserved;
+    U64     AliasWWNN;
+    U64     AliasWWPN;
+} fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
+  FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t;
+
+typedef struct _CONFIG_PAGE_FC_PORT_5
+{
+   fCONFIG_PAGE_HEADER                  Header;
+   fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO    AliasInfo[1];
+} fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5,
+  FCPortPage5_t, MPI_POINTER pFCPortPage5_t;
+
+#define MPI_FCPORTPAGE5_PAGEVERSION                     (0x00)
+
+#define MPI_FCPORTPAGE5_FLAGS_ALIAS_ALPA_VALID          (0x01)
+#define MPI_FCPORTPAGE5_FLAGS_ALIAS_WWN_VALID           (0x02)
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_6
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Reserved;
+    U64                     TimeSinceReset;
+    U64                     TxFrames;
+    U64                     RxFrames;
+    U64                     TxWords;
+    U64                     RxWords;
+    U64                     LipCount;
+    U64                     NosCount;
+    U64                     ErrorFrames;
+    U64                     DumpedFrames;
+    U64                     LinkFailureCount;
+    U64                     LossOfSyncCount;
+    U64                     LossOfSignalCount;
+    U64                     PrimativeSeqErrCount;
+    U64                     InvalidTxWordCount;
+    U64                     InvalidCrcCount;
+    U64                     FcpInitiatorIoCount;
+} fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6,
+  FCPortPage6_t, MPI_POINTER pFCPortPage6_t;
+
+#define MPI_FCPORTPAGE6_PAGEVERSION                     (0x00)
+
+
+typedef struct _CONFIG_PAGE_FC_PORT_7
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U32                     Reserved;
+    U8                      PortSymbolicName[256];
+} fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7,
+  FCPortPage7_t, MPI_POINTER pFCPortPage7_t;
+
+#define MPI_FCPORTPAGE7_PAGEVERSION                     (0x00)
+
+
+/****************************************************************************/
+/*  FC Device Config Pages                                                  */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_FC_DEVICE_0
+{
+   fCONFIG_PAGE_HEADER      Header;
+    U64                     WWNN;
+    U64                     WWPN;
+    U32                     PortIdentifier;
+    U8                      Protocol;
+    U8                      Flags;
+    U16                     BBCredit;
+    U16                     MaxRxFrameSize;
+    U8                      Reserved1;
+    U8                      PortNumber;
+    U8                      FcPhLowestVersion;
+    U8                      FcPhHighestVersion;
+    U8                      CurrentTargetID;
+    U8                      CurrentBus;
+} fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0,
+  FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t;
+
+#define MPI_FC_DEVICE_PAGE0_PAGEVERSION                 (0x02)
+
+#define MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID    (0x01)
+
+#define MPI_FC_DEVICE_PAGE0_PROT_IP                     (0x01)
+#define MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET             (0x02)
+#define MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR          (0x04)
+
+#define MPI_FC_DEVICE_PAGE0_PGAD_PORT_MASK              (MPI_FC_DEVICE_PGAD_PORT_MASK)
+#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_MASK              (MPI_FC_DEVICE_PGAD_FORM_MASK)
+#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_NEXT_DID          (MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
+#define MPI_FC_DEVICE_PAGE0_PGAD_FORM_BUS_TID           (MPI_FC_DEVICE_PGAD_FORM_BUS_TID)
+#define MPI_FC_DEVICE_PAGE0_PGAD_DID_MASK               (MPI_FC_DEVICE_PGAD_ND_DID_MASK)
+#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_MASK               (MPI_FC_DEVICE_PGAD_BT_BUS_MASK)
+#define MPI_FC_DEVICE_PAGE0_PGAD_BUS_SHIFT              (MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT)
+#define MPI_FC_DEVICE_PAGE0_PGAD_TID_MASK               (MPI_FC_DEVICE_PGAD_BT_TID_MASK)
+
+
+/****************************************************************************/
+/*  RAID Volume Config Pages                                                  */
+/****************************************************************************/
+
+typedef struct _RAIDVOL2_EM_PHYS_ID
+{
+    U8                      TargetID;
+    U8                      Bus;
+    U8                      IocNumber;
+    U8                      PhysDiskNumber;
+    U8                      Reserved[8];
+    U8                      PhysicalDiskIdentifier[16];
+    U8                      ProductId[16];
+    U8                      InfoOffset0;
+    U8                      InfoSize0;
+    U8                      InfoOffset1;
+    U8                      InfoSize1;
+    U8                      Info[32];
+} RAIDVOL2_EM_PHYS_ID, MPI_POINTER PTR_RAIDVOL2_EM_PHYS_ID,
+  RaidVol2EmPhysicalID_t, MPI_POINTER pRaidVol2EmPhysicalID_t;
+
+typedef struct _RAIDVOL2_EM_DISK_INFO
+{
+    U32                     DiskStatus;
+    U32                     DeviceSettings;
+    U16                     ErrorCount;
+    U16                     Reserved;
+    U8                      ErrorCdbByte;
+    U8                      ErrorSenseKey;
+    U8                      ErrorASC;
+    U8                      ErrorASCQ;
+    U16                     SmartCount;
+    U8                      SmartASC;
+    U8                      SmartASCQ;
+} RAIDVOL2_EM_DISK_INFO, MPI_POINTER PTR_RAIDVOL2_EM_DISK_INFO,
+  RaidVol2EmDiskInfo_t, MPI_POINTER pRaidVol2EmDiskInfo_t;
+
+/* RAID Volume 2 EM Physical Disk DiskStatus flags */
+
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_PRIMARY              (0x00000001)
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_SECONDARY            (0x00000002)
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_HOT_SPARE            (0x00000004)
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_OUT_OF_SYNC          (0x00000008)
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_OFFLINE              (0x00000010)
+#define MPI_RAIDVOLPAGE2_PHYS_DISK_NOT_RESPONDING       (0x00000020)
+
+typedef struct _RAIDVOL2_EM_PHYSICAL_DISK
+{
+    RAIDVOL2_EM_PHYS_ID     Id;
+    RAIDVOL2_EM_DISK_INFO   Info;
+} RAIDVOL2_EM_PHYSICAL_DISK, MPI_POINTER PTR_RAIDVOL2_EM_PHYSICAL_DISK,
+  RaidVol2EmPhysicalDisk_t, MPI_POINTER pRaidVol2EmPhysicalDisk_t;
+
+#define MPI_RAIDVOLPAGE2_MAX_DISKS                      (3)
+
+typedef struct _CONFIG_PAGE_RAID_VOL_2
+{
+   fCONFIG_PAGE_HEADER          Header;
+    U32                         VolumeStatus;
+    U32                         VolumeSettings;
+    U32                         Reserved;
+    U64                         MaxLba;
+    U32                         BlockSize;
+    U8                          InquirySize;
+    U8                          NumPhysicalDisks;
+    U16                         Reserved1;
+    U8                          InquiryData[56];
+    RAIDVOL2_EM_PHYSICAL_DISK   EMPhysicalDisk[MPI_RAIDVOLPAGE2_MAX_DISKS];
+} fCONFIG_PAGE_RAID_VOL_2, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_2,
+  RaidVolumePage2_t, MPI_POINTER pRaidVolumePage2_t;
+
+#define MPI_RAIDVOLPAGE2_PAGEVERSION                    (0x00)
+
+/* RAID Volume Page 2 VolumeStatus defines */
+
+#define MPI_RAIDVOLPAGE2_STATUS_ENABLED                 (0x00000001)
+#define MPI_RAIDVOLPAGE2_STATUS_QUIESCED                (0x00000002)
+#define MPI_RAIDVOLPAGE2_STATUS_RESYNC_IN_PROGRESS      (0x00000004)
+#define MPI_RAIDVOLPAGE2_STATUS_DEGRADED                (0x00000008)
+
+/* RAID Volume Page 2 VolumeSettings defines */
+
+#define MPI_RAIDVOLPAGE2_SETTING_WRITE_CACHING_ENABLE   (0x00000001)
+#define MPI_RAIDVOLPAGE2_SETTING_OFFLINE_ON_SMART       (0x00000002)
+#define MPI_RAIDVOLPAGE2_SETTING_AUTO_CONFIGURE         (0x00000004)
+
+
+/****************************************************************************/
+/* LAN Config Pages                                                         */
+/****************************************************************************/
+
+typedef struct _CONFIG_PAGE_LAN_0
+{
+    ConfigPageHeader_t      Header;
+    U16                     TxRxModes;
+    U16                     Reserved;
+    U32                     PacketPrePad;
+} fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0,
+  LANPage0_t, MPI_POINTER pLANPage0_t;
+
+#define MPI_LAN_PAGE0_PAGEVERSION                       (0x01)
+
+#define MPI_LAN_PAGE0_RETURN_LOOPBACK                   (0x0000)
+#define MPI_LAN_PAGE0_SUPPRESS_LOOPBACK                 (0x0001)
+#define MPI_LAN_PAGE0_LOOPBACK_MASK                     (0x0001)
+
+typedef struct _CONFIG_PAGE_LAN_1
+{
+    ConfigPageHeader_t      Header;
+    U16                     Reserved;
+    U8                      CurrentDeviceState;
+    U8                      Reserved1;
+    U32                     MinPacketSize;
+    U32                     MaxPacketSize;
+    U32                     HardwareAddressLow;
+    U32                     HardwareAddressHigh;
+    U32                     MaxWireSpeedLow;
+    U32                     MaxWireSpeedHigh;
+    U32                     BucketsRemaining;
+    U32                     MaxReplySize;
+    U32                     NegWireSpeedHigh;
+    U32                     NegWireSpeedLow;
+} fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1,
+  LANPage1_t, MPI_POINTER pLANPage1_t;
+
+#define MPI_LAN_PAGE1_PAGEVERSION                       (0x03)
+
+#define MPI_LAN_PAGE1_DEV_STATE_RESET                   (0x00)
+#define MPI_LAN_PAGE1_DEV_STATE_OPERATIONAL             (0x01)
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_fc.h linux/drivers/message/fusion/lsi/mpi_fc.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_fc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_fc.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,350 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_FC.H
+ *          Title:  MPI Fibre Channel messages and structures
+ *  Creation Date:  June 12, 2000
+ *
+ *    MPI Version:  01.01.05
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-12-00  01.00.02  Added _MSG_FC_ABORT_REPLY structure.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  12-04-00  01.01.02  Added messages for Common Transport Send and
+ *                      Primitive Send.
+ *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
+ *                      and modified the FcPrimitiveSend flags.
+ *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
+ *                      field.
+ *                      Added FC_ABORT_TYPE_CT_SEND_REQUEST and
+ *                      FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request.
+ *                      Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND.
+ *  02-20-01  01.01.05  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_FC_H
+#define MPI_FC_H
+
+
+/*****************************************************************************
+*
+*        F C    T a r g e t    M o d e    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/* Link Service Buffer Post messages                                        */
+/****************************************************************************/
+
+typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REQUEST
+{
+    U8                      BufferPostFlags;    /* 00h */
+    U8                      BufferCount;        /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved;           /* 04h */
+    U8                      Reserved1;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    SGE_TRANS_SIMPLE_UNION  SGL;
+} MSG_LINK_SERVICE_BUFFER_POST_REQUEST,
+ MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REQUEST,
+  LinkServiceBufferPostRequest_t, MPI_POINTER pLinkServiceBufferPostRequest_t;
+
+#define LINK_SERVICE_BUFFER_POST_FLAGS_PORT_MASK (0x01)
+
+typedef struct _WWNFORMAT
+{
+    U32                     PortNameHigh;       /* 00h */
+    U32                     PortNameLow;        /* 04h */
+    U32                     NodeNameHigh;       /* 08h */
+    U32                     NodeNameLow;        /* 0Ch */
+} WWNFORMAT,
+  WwnFormat_t;
+
+/* Link Service Buffer Post Reply */
+typedef struct _MSG_LINK_SERVICE_BUFFER_POST_REPLY
+{
+    U8                      Flags;              /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      PortNumber;         /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved2;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     TransferLength;     /* 14h */
+    U32                     TransactionContext; /* 18h */
+    U32                     Rctl_Did;           /* 1Ch */
+    U32                     Csctl_Sid;          /* 20h */
+    U32                     Type_Fctl;          /* 24h */
+    U16                     SeqCnt;             /* 28h */
+    U8                      Dfctl;              /* 2Ah */
+    U8                      SeqId;              /* 2Bh */
+    U16                     Rxid;               /* 2Ch */
+    U16                     Oxid;               /* 2Eh */
+    U32                     Parameter;          /* 30h */
+    WWNFORMAT               Wwn;                /* 34h */
+} MSG_LINK_SERVICE_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY,
+  LinkServiceBufferPostReply_t, MPI_POINTER pLinkServiceBufferPostReply_t;
+
+#define MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED    (0x80)
+
+#define MPI_FC_DID_MASK                             (0x00FFFFFF)
+#define MPI_FC_DID_SHIFT                            (0)
+#define MPI_FC_RCTL_MASK                            (0xFF000000)
+#define MPI_FC_RCTL_SHIFT                           (24)
+#define MPI_FC_SID_MASK                             (0x00FFFFFF)
+#define MPI_FC_SID_SHIFT                            (0)
+#define MPI_FC_CSCTL_MASK                           (0xFF000000)
+#define MPI_FC_CSCTL_SHIFT                          (24)
+#define MPI_FC_FCTL_MASK                            (0x00FFFFFF)
+#define MPI_FC_FCTL_SHIFT                           (0)
+#define MPI_FC_TYPE_MASK                            (0xFF000000)
+#define MPI_FC_TYPE_SHIFT                           (24)
+
+/* obsolete name for the above */
+#define FCP_TARGET_DID_MASK                         (0x00FFFFFF)
+#define FCP_TARGET_DID_SHIFT                        (0)
+#define FCP_TARGET_RCTL_MASK                        (0xFF000000)
+#define FCP_TARGET_RCTL_SHIFT                       (24)
+#define FCP_TARGET_SID_MASK                         (0x00FFFFFF)
+#define FCP_TARGET_SID_SHIFT                        (0)
+#define FCP_TARGET_CSCTL_MASK                       (0xFF000000)
+#define FCP_TARGET_CSCTL_SHIFT                      (24)
+#define FCP_TARGET_FCTL_MASK                        (0x00FFFFFF)
+#define FCP_TARGET_FCTL_SHIFT                       (0)
+#define FCP_TARGET_TYPE_MASK                        (0xFF000000)
+#define FCP_TARGET_TYPE_SHIFT                       (24)
+
+
+/****************************************************************************/
+/* Link Service Response messages                                           */
+/****************************************************************************/
+
+typedef struct _MSG_LINK_SERVICE_RSP_REQUEST
+{
+    U8                      RspFlags;           /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Rctl_Did;           /* 0Ch */
+    U32                     Csctl_Sid;          /* 10h */
+    U32                     Type_Fctl;          /* 14h */
+    U16                     SeqCnt;             /* 18h */
+    U8                      Dfctl;              /* 1Ah */
+    U8                      SeqId;              /* 1Bh */
+    U16                     Rxid;               /* 1Ch */
+    U16                     Oxid;               /* 1Eh */
+    U32                     Parameter;          /* 20h */
+    SGE_SIMPLE_UNION        SGL;                /* 24h */
+} MSG_LINK_SERVICE_RSP_REQUEST, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REQUEST,
+  LinkServiceRspRequest_t, MPI_POINTER pLinkServiceRspRequest_t;
+
+#define LINK_SERVICE_RSP_FLAGS_IMMEDIATE        (0x80)
+#define LINK_SERVICE_RSP_FLAGS_PORT_MASK        (0x01)
+
+
+/* Link Service Response Reply  */
+typedef struct _MSG_LINK_SERVICE_RSP_REPLY
+{
+    U16                     Reserved;           /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved3;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     InitiatorIndex;     /* 14h */
+} MSG_LINK_SERVICE_RSP_REPLY, MPI_POINTER PTR_MSG_LINK_SERVICE_RSP_REPLY,
+  LinkServiceRspReply_t, MPI_POINTER pLinkServiceRspReply_t;
+
+
+/****************************************************************************/
+/* Extended Link Service Send messages                                      */
+/****************************************************************************/
+
+typedef struct _MSG_EXLINK_SERVICE_SEND_REQUEST
+{
+    U8                      SendFlags;          /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U32                     MsgFlags_Did;       /* 04h */
+    U32                     MsgContext;         /* 08h */
+    U32                     ElsCommandCode;     /* 0Ch */
+    SGE_SIMPLE_UNION        SGL;                /* 10h */
+} MSG_EXLINK_SERVICE_SEND_REQUEST, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REQUEST,
+  ExLinkServiceSendRequest_t, MPI_POINTER pExLinkServiceSendRequest_t;
+
+#define EX_LINK_SERVICE_SEND_DID_MASK           (0x00FFFFFF)
+#define EX_LINK_SERVICE_SEND_DID_SHIFT          (0)
+#define EX_LINK_SERVICE_SEND_MSGFLAGS_MASK      (0xFF000000)
+#define EX_LINK_SERVICE_SEND_MSGFLAGS_SHIFT     (24)
+
+
+/* Extended Link Service Send Reply */
+typedef struct _MSG_EXLINK_SERVICE_SEND_REPLY
+{
+    U16                     Reserved;           /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved3;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     ResponseLength;     /* 14h */
+} MSG_EXLINK_SERVICE_SEND_REPLY, MPI_POINTER PTR_MSG_EXLINK_SERVICE_SEND_REPLY,
+  ExLinkServiceSendReply_t, MPI_POINTER pExLinkServiceSendReply_t;
+
+/****************************************************************************/
+/* FC Abort messages                                                        */
+/****************************************************************************/
+
+typedef struct _MSG_FC_ABORT_REQUEST
+{
+    U8                      AbortFlags;         /* 00h */
+    U8                      AbortType;          /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     TransactionContextToAbort;  /* 0Ch */
+} MSG_FC_ABORT_REQUEST, MPI_POINTER PTR_MSG_FC_ABORT_REQUEST,
+  FcAbortRequest_t, MPI_POINTER pFcAbortRequest_t;
+
+#define FC_ABORT_FLAG_PORT_MASK                 (0x01)
+
+#define FC_ABORT_TYPE_ALL_FC_BUFFERS            (0x00)
+#define FC_ABORT_TYPE_EXACT_FC_BUFFER           (0x01)
+#define FC_ABORT_TYPE_CT_SEND_REQUEST           (0x02)
+#define FC_ABORT_TYPE_EXLINKSEND_REQUEST        (0x03)
+
+/* FC Abort Reply */
+typedef struct _MSG_FC_ABORT_REPLY
+{
+    U16                     Reserved;           /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved3;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+} MSG_FC_ABORT_REPLY, MPI_POINTER PTR_MSG_FC_ABORT_REPLY,
+  FcAbortReply_t, MPI_POINTER pFcAbortReply_t;
+
+
+/****************************************************************************/
+/* FC Common Transport Send messages                                        */
+/****************************************************************************/
+
+typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REQUEST
+{
+    U8                      SendFlags;          /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U32                     MsgFlags_Did;       /* 04h */
+    U32                     MsgContext;         /* 08h */
+    U16                     CTCommandCode;      /* 0Ch */
+    U8                      FsType;             /* 0Eh */
+    U8                      Reserved1;          /* 0Fh */
+    SGE_SIMPLE_UNION        SGL;                /* 10h */
+} MSG_FC_COMMON_TRANSPORT_SEND_REQUEST,
+ MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REQUEST,
+  FcCommonTransportSendRequest_t, MPI_POINTER pFcCommonTransportSendRequest_t;
+
+#define MPI_FC_CT_SEND_DID_MASK                 (0x00FFFFFF)
+#define MPI_FC_CT_SEND_DID_SHIFT                (0)
+#define MPI_FC_CT_SEND_MSGFLAGS_MASK            (0xFF000000)
+#define MPI_FC_CT_SEND_MSGFLAGS_SHIFT           (24)
+
+
+/* FC Common Transport Send Reply */
+typedef struct _MSG_FC_COMMON_TRANSPORT_SEND_REPLY
+{
+    U16                     Reserved;           /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved3;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     ResponseLength;     /* 14h */
+} MSG_FC_COMMON_TRANSPORT_SEND_REPLY, MPI_POINTER PTR_MSG_FC_COMMON_TRANSPORT_SEND_REPLY,
+  FcCommonTransportSendReply_t, MPI_POINTER pFcCommonTransportSendReply_t;
+
+
+/****************************************************************************/
+/* FC Primitive Send messages                                               */
+/****************************************************************************/
+
+typedef struct _MSG_FC_PRIMITIVE_SEND_REQUEST
+{
+    U8                      SendFlags;          /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      FcPrimitive[4];     /* 0Ch */
+} MSG_FC_PRIMITIVE_SEND_REQUEST, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REQUEST,
+  FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t;
+
+#define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK       (0x01)
+#define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND       (0x08)
+#define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE       (0x10)
+#define MPI_FC_PRIM_SEND_FLAGS_SEND_AROUND     (0x20)
+#define MPI_FC_PRIM_SEND_FLAGS_UNTIL_FULL      (0x40)
+#define MPI_FC_PRIM_SEND_FLAGS_FOREVER         (0x80)
+
+/* FC Primitive Send Reply */
+typedef struct _MSG_FC_PRIMITIVE_SEND_REPLY
+{
+    U8                      SendFlags;          /* 00h */
+    U8                      Reserved;           /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved1;          /* 04h */
+    U8                      Reserved2;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved3;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+} MSG_FC_PRIMITIVE_SEND_REPLY, MPI_POINTER PTR_MSG_FC_PRIMITIVE_SEND_REPLY,
+  FcPrimitiveSendReply_t, MPI_POINTER pFcPrimitiveSendReply_t;
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_history.txt linux/drivers/message/fusion/lsi/mpi_history.txt
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_history.txt	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_history.txt	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,237 @@
+
+ ==============================
+ MPI Header File Change History
+ ==============================
+
+ Copyright (c) 2000-2001 LSI Logic Corporation.
+
+ ---------------------------------------
+ Header Set Release Version:    01.01.08
+ Header Set Release Date:       02-27-01
+ ---------------------------------------
+
+ Filename               Current version     Prior version
+ ----------             ---------------     -------------
+ mpi.h                  01.01.06            01.01.05
+ mpi_ioc.h              01.01.05            01.01.04
+ mpi_cnfg.h             01.01.09            01.01.08
+ mpi_init.h             01.01.03            01.01.03
+ mpi_targ.h             01.01.03            01.01.03
+ mpi_fc.h               01.01.05            01.01.05
+ mpi_lan.h              01.01.02            01.01.02
+ mpi_raid.h             01.01.01            none
+ mpi_type.h             01.01.02            01.01.02
+ mpi_history.txt        01.01.08            01.01.07
+
+
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+
+mpi.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition.
+ *  06-06-00  01.00.01  Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR.
+ *  06-22-00  01.00.02  Added MPI_IOCSTATUS_LAN_ definitions.
+ *                      Removed LAN_SUSPEND function definition.
+ *                      Added MPI_MSGFLAGS_CONTINUATION_REPLY definition.
+ *  06-30-00  01.00.03  Added MPI_CONTEXT_REPLY_TYPE_LAN definition.
+ *                      Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros.
+ *  07-27-00  01.00.04  Added MPI_FAULT_ definitions.
+ *                      Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions.
+ *                      Added MPI_IOCSTATUS_INTERNAL_ERROR definition.
+ *                      Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  12-04-00  01.01.02  Added new function codes.
+ *  01-09-01  01.01.03  Added more definitions to the system interface section
+ *                      Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT.
+ *  01-25-01  01.01.04  Changed MPI_VERSION_MINOR from 0x00 to 0x01.
+ *  02-20-01  01.01.05  Started using MPI_POINTER.
+ *                      Added defines for MPI_DIAG_PREVENT_IOC_BOOT and
+ *                      MPI_DIAG_CLEAR_FLASH_BAD_SIG.
+ *                      Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines.
+ *  02-27-01  01.01.06  Removed MPI_HOST_INDEX_REGISTER define.
+ *                      Added function codes for RAID.
+ *  --------------------------------------------------------------------------
+
+mpi_ioc.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added _MSG_IOC_INIT_REPLY structure.
+ *  06-06-00  01.00.01  Added CurReplyFrameSize field to _MSG_IOC_FACTS_REPLY.
+ *  06-12-00  01.00.02  Added _MSG_PORT_ENABLE_REPLY structure.
+ *                      Added _MSG_EVENT_ACK_REPLY structure.
+ *                      Added _MSG_FW_DOWNLOAD_REPLY structure.
+ *                      Added _MSG_TOOLBOX_REPLY structure.
+ *  06-30-00  01.00.03  Added MaxLanBuckets to _PORT_FACT_REPLY structure.
+ *  07-27-00  01.00.04  Added _EVENT_DATA structure definitions for _SCSI,
+ *                      _LINK_STATUS, _LOOP_STATE and _LOGOUT.
+ *  08-11-00  01.00.05  Switched positions of MsgLength and Function fields in
+ *                      _MSG_EVENT_ACK_REPLY structure to match specification.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *                      Added a value for Manufacturer to WhoInit
+ *  12-04-00  01.01.02  Modified IOCFacts reply, added FWUpload messages, and
+ *                      removed toolbox message.
+ *  01-09-01  01.01.03  Added event enabled and disabled defines.
+ *                      Added structures for FwHeader and DataHeader.
+ *                      Added ImageType to FwUpload reply.
+ *  02-20-01  01.01.04  Started using MPI_POINTER.
+ *  02-27-01  01.01.05  Added event for RAID status change and its event data.
+ *                      Added IocNumber field to MSG_IOC_FACTS_REPLY.
+ *  --------------------------------------------------------------------------
+
+mpi_cnfg.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-08-00  01.00.02  Added _PAGEVERSION definitions for all pages.
+ *                      Added FcPhLowestVersion, FcPhHighestVersion, Reserved2
+ *                      fields to FC_DEVICE_0 page, updated the page version.
+ *                      Changed _FREE_RUNNING_CLOCK to _PACING_TRANSFERS in
+ *                      SCSI_PORT_0, SCSI_DEVICE_0 and SCSI_DEVICE_1 pages
+ *                      and updated the page versions.
+ *                      Added _RESPONSE_ID_MASK definition to SCSI_PORT_1
+ *                      page and updated the page version.
+ *                      Added Information field and _INFO_PARAMS_NEGOTIATED
+ *                      definitionto SCSI_DEVICE_0 page.
+ *  06-22-00  01.00.03  Removed batch controls from LAN_0 page and updated the
+ *                      page version.
+ *                      Added BucketsRemaining to LAN_1 page, redefined the
+ *                      state values, and updated the page version.
+ *                      Revised bus width definitions in SCSI_PORT_0,
+ *                      SCSI_DEVICE_0 and SCSI_DEVICE_1 pages.
+ *  06-30-00  01.00.04  Added MaxReplySize to LAN_1 page and updated the page
+ *                      version.
+ *                      Moved FC_DEVICE_0 PageAddress description to spec.
+ *  07-27-00  01.00.05  Corrected the SubsystemVendorID and SubsystemID field
+ *                      widths in IOC_0 page and updated the page version.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *                      Added Manufacturing pages, IO Unit Page 2, SCSI SPI
+ *                      Port Page 2, FC Port Page 4, FC Port Page 5
+ *  12-04-00  01.01.03  Config page changes to match MPI rev 1.00.01.
+ *  12-05-00  01.01.04  Modified config page actions.
+ *  01-09-01  01.01.05  Added defines for page address formats.
+ *                      Data size for Manufacturing pages 2 and 3 no longer
+ *                      defined here.
+ *                      Io Unit Page 2 size is fixed at 4 adapters and some
+ *                      flags were changed.
+ *                      SCSI Port Page 2 Device Settings modified.
+ *                      New fields added to FC Port Page 0 and some flags
+ *                      cleaned up.
+ *                      Removed impedance flash from FC Port Page 1.
+ *                      Added FC Port pages 6 and 7.
+ *  01-25-01  01.01.06  Added MaxInitiators field to FcPortPage0.
+ *  01-29-01  01.01.07  Changed some defines to make them 32 character unique.
+ *                      Added some LinkType defines for FcPortPage0.
+ *  02-20-01  01.01.08  Started using MPI_POINTER.
+ *  02-27-01  01.01.09  Replaced MPI_CONFIG_PAGETYPE_SCSI_LUN with
+ *                      MPI_CONFIG_PAGETYPE_RAID_VOLUME.
+ *                      Added definitions and structures for IOC Page 2 and
+ *                      RAID Volume Page 2.
+ *  --------------------------------------------------------------------------
+
+mpi_init.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added SenseBufferLength to _MSG_SCSI_IO_REPLY.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-08-00  01.00.02  Added MPI_SCSI_RSP_INFO_ definitions.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  12-04-00  01.01.02  Added MPI_SCSIIO_CONTROL_NO_DISCONNECT.
+ *  02-20-01  01.01.03  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+
+mpi_targ.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-22-00  01.00.02  Added _MSG_TARGET_CMD_BUFFER_POST_REPLY structure.
+ *                      Corrected DECSRIPTOR typo to DESCRIPTOR.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *                      Modified target mode to use IoIndex instead of
+ *                      HostIndex and IocIndex. Added Alias.
+ *  01-09-01  01.01.02  Added defines for TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER
+ *                      and TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER.
+ *  02-20-01  01.01.03  Started using MPI_POINTER.
+ *                      Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and
+ *                      MPI_TARGET_FCP_CMD_BUFFER.
+ *  --------------------------------------------------------------------------
+
+mpi_fc.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-12-00  01.00.02  Added _MSG_FC_ABORT_REPLY structure.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  12-04-00  01.01.02  Added messages for Common Transport Send and
+ *                      Primitive Send.
+ *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
+ *                      and modified the FcPrimitiveSend flags.
+ *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
+ *                      field.
+ *                      Added FC_ABORT_TYPE_CT_SEND_REQUEST and
+ *                      FC_ABORT_TYPE_EXLINKSEND_REQUEST for FcAbort request.
+ *                      Added MPI_FC_PRIM_SEND_FLAGS_STOP_SEND.
+ *  02-20-01  01.01.05  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+
+mpi_lan.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added LANStatus field to _MSG_LAN_SEND_REPLY.
+ *                      Added LANStatus field to _MSG_LAN_RECEIVE_POST_REPLY.
+ *                      Moved ListCount field in _MSG_LAN_RECEIVE_POST_REPLY.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-12-00  01.00.02  Added MPI_ to BUCKETSTATUS_ definitions.
+ *  06-22-00  01.00.03  Major changes to match new LAN definition in 1.0 spec.
+ *  06-30-00  01.00.04  Added Context Reply definitions per revised proposal.
+ *                      Changed transaction context usage to bucket/buffer.
+ *  07-05-00  01.00.05  Removed LAN_RECEIVE_POST_BUCKET_CONTEXT_MASK definition
+ *                      to lan private header file
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  02-20-01  01.01.02  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+
+mpi_raid.h
+ *  02-27-01  01.01.01  Original release for this file.
+ *  --------------------------------------------------------------------------
+
+mpi_type.h
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  02-20-01  01.01.02  Added define and ifdef for MPI_POINTER.
+ *  --------------------------------------------------------------------------
+
+mpi_history.txt         Parts list history
+
+Filename    01.01.08   01.01.07   01.01.06   01.01.05   01.01.04
+----------  --------   --------   --------   --------   --------
+mpi.h       01.01.06   01.01.05   01.01.04   01.01.04   01.01.03
+mpi_ioc.h   01.01.05   01.01.04   01.01.03   01.01.03   01.01.03
+mpi_cnfg.h  01.01.09   01.01.08   01.01.07   01.01.06   01.01.05
+mpi_init.h  01.01.03   01.01.03   01.01.02   01.01.02   01.01.02
+mpi_targ.h  01.01.03   01.01.03   01.01.02   01.01.02   01.01.02
+mpi_fc.h    01.01.05   01.01.05   01.01.04   01.01.04   01.01.03
+mpi_lan.h   01.01.02   01.01.02   01.01.01   01.01.01   01.01.01
+mpi_raid.h  01.01.01
+mpi_type.h  01.01.02   01.01.02   01.01.01   01.01.01   01.01.01
+
+Filename    01.01.03   01.01.02   01.01.01   01.00.07   01.00.06   01.00.05
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.01.02   01.01.02   01.01.01   01.00.04   01.00.04   01.00.03
+mpi_ioc.h   01.01.02   01.01.02   01.01.01   01.00.05   01.00.04   01.00.03
+mpi_cnfg.h  01.01.04   01.01.03   01.01.01   01.00.05   01.00.05   01.00.04
+mpi_init.h  01.01.02   01.01.02   01.01.01   01.00.02   01.00.02   01.00.02
+mpi_targ.h  01.01.01   01.01.01   01.01.01   01.00.02   01.00.02   01.00.02
+mpi_fc.h    01.01.02   01.01.02   01.01.01   01.00.02   01.00.02   01.00.02
+mpi_lan.h   01.01.01   01.01.01   01.01.01   01.00.05   01.00.05   01.00.05
+mpi_type.h  01.01.01   01.01.01   01.01.01   01.00.01   01.00.01   01.00.01
+
+Filename     01.00.04   01.00.03   01.00.02   01.00.01   00.10.02   00.10.01
+----------   --------   --------   --------   --------   --------   --------
+mpi.h        01.00.02   01.00.01   01.00.01   01.00.01   00.10.02   00.10.01
+mpi_ioc.h    01.00.02   01.00.02   01.00.01   01.00.01   00.10.02   00.10.01
+mpi_cnfg.h   01.00.03   01.00.02   01.00.02   01.00.01   00.10.01   00.10.01
+mpi_init.h   01.00.02   01.00.02   01.00.02   01.00.01   00.10.02   00.10.01
+mpi_targ.h   01.00.02   01.00.01   01.00.01   01.00.01   00.10.01   00.10.01
+mpi_fc.h     01.00.02   01.00.02   01.00.01   01.00.01   00.10.01   00.10.01
+mpi_lan.h    01.00.03   01.00.02   01.00.01   01.00.01   00.10.02   00.10.01
+mpi_type.h   01.00.01   01.00.01   01.00.01   01.00.01   00.10.01   00.10.01
+
+
+ *  --------------------------------------------------------------------------
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_init.h linux/drivers/message/fusion/lsi/mpi_init.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_init.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_init.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,215 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_INIT.H
+ *          Title:  MPI initiator mode messages and structures
+ *  Creation Date:  June 8, 2000
+ *
+ *    MPI Version:  01.01.03
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added SenseBufferLength to _MSG_SCSI_IO_REPLY.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-08-00  01.00.02  Added MPI_SCSI_RSP_INFO_ definitions.
+ *  11-02-00  01.01.01  Original release for post 1.0 work.
+ *  12-04-00  01.01.02  Added MPI_SCSIIO_CONTROL_NO_DISCONNECT.
+ *  02-20-01  01.01.03  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_INIT_H
+#define MPI_INIT_H
+
+
+/*****************************************************************************
+*
+*               S C S I    I n i t i a t o r    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  SCSI IO messages and assocaited structures                              */
+/****************************************************************************/
+
+typedef struct _MSG_SCSI_IO_REQUEST
+{
+    U8                      TargetID;
+    U8                      Bus;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      CDBLength;
+    U8                      SenseBufferLength;
+    U8                      Reserved;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      LUN[8];
+    U32                     Control;
+    U8                      CDB[16];
+    U32                     DataLength;
+    U32                     SenseBufferLowAddr;
+    SGE_IO_UNION            SGL;
+} MSG_SCSI_IO_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO_REQUEST,
+  SCSIIORequest_t, MPI_POINTER pSCSIIORequest_t;
+
+
+/* SCSIO MsgFlags bits */
+
+#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH          (0x01)
+#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32       (0x00)
+#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64       (0x01)
+#define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION       (0x02)
+#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST       (0x00)
+#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC        (0x02)
+
+/* SCSIIO LUN fields */
+
+#define MPI_SCSIIO_LUN_FIRST_LEVEL_ADDRESSING   (0x0000FFFF)
+#define MPI_SCSIIO_LUN_SECOND_LEVEL_ADDRESSING  (0xFFFF0000)
+#define MPI_SCSIIO_LUN_THIRD_LEVEL_ADDRESSING   (0x0000FFFF)
+#define MPI_SCSIIO_LUN_FOURTH_LEVEL_ADDRESSING  (0xFFFF0000)
+#define MPI_SCSIIO_LUN_LEVEL_1_WORD             (0xFF00)
+#define MPI_SCSIIO_LUN_LEVEL_1_DWORD            (0x0000FF00)
+
+/* SCSIO Control bits */
+
+#define MPI_SCSIIO_CONTROL_DATADIRECTION_MASK   (0x03000000)
+#define MPI_SCSIIO_CONTROL_NODATATRANSFER       (0x00000000)
+#define MPI_SCSIIO_CONTROL_WRITE                (0x01000000)
+#define MPI_SCSIIO_CONTROL_READ                 (0x02000000)
+
+#define MPI_SCSIIO_CONTROL_ADDCDBLEN_MASK       (0x3C000000)
+#define MPI_SCSIIO_CONTROL_ADDCDBLEN_SHIFT      (26)
+
+#define MPI_SCSIIO_CONTROL_TASKATTRIBUTE_MASK   (0x00000700)
+#define MPI_SCSIIO_CONTROL_SIMPLEQ              (0x00000000)
+#define MPI_SCSIIO_CONTROL_HEADOFQ              (0x00000100)
+#define MPI_SCSIIO_CONTROL_ORDEREDQ             (0x00000200)
+#define MPI_SCSIIO_CONTROL_ACAQ                 (0x00000400)
+#define MPI_SCSIIO_CONTROL_UNTAGGED             (0x00000500)
+#define MPI_SCSIIO_CONTROL_NO_DISCONNECT        (0x00000700)
+
+#define MPI_SCSIIO_CONTROL_TASKMANAGE_MASK      (0x00FF0000)
+#define MPI_SCSIIO_CONTROL_OBSOLETE             (0x00800000)
+#define MPI_SCSIIO_CONTROL_CLEAR_ACA_RSV        (0x00400000)
+#define MPI_SCSIIO_CONTROL_TARGET_RESET         (0x00200000)
+#define MPI_SCSIIO_CONTROL_LUN_RESET_RSV        (0x00100000)
+#define MPI_SCSIIO_CONTROL_RESERVED             (0x00080000)
+#define MPI_SCSIIO_CONTROL_CLR_TASK_SET_RSV     (0x00040000)
+#define MPI_SCSIIO_CONTROL_ABORT_TASK_SET       (0x00020000)
+#define MPI_SCSIIO_CONTROL_RESERVED2            (0x00010000)
+
+
+/* SCSIIO reply structure */
+typedef struct _MSG_SCSI_IO_REPLY
+{
+    U8                      TargetID;
+    U8                      Bus;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      CDBLength;
+    U8                      SenseBufferLength;
+    U8                      Reserved;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      SCSIStatus;
+    U8                      SCSIState;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     TransferCount;
+    U32                     SenseCount;
+    U32                     ResponseInfo;
+} MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY,
+  SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t;
+
+
+/* SCSIIO Reply SCSIStatus values (SAM-2 status codes) */
+
+#define MPI_SCSI_STATUS_SUCCESS                 (0x00)
+#define MPI_SCSI_STATUS_CHECK_CONDITION         (0x02)
+#define MPI_SCSI_STATUS_CONDITION_MET           (0x04)
+#define MPI_SCSI_STATUS_BUSY                    (0x08)
+#define MPI_SCSI_STATUS_INTERMEDIATE            (0x10)
+#define MPI_SCSI_STATUS_INTERMEDIATE_CONDMET    (0x14)
+#define MPI_SCSI_STATUS_RESERVATION_CONFLICT    (0x18)
+#define MPI_SCSI_STATUS_COMMAND_TERMINATED      (0x22)
+#define MPI_SCSI_STATUS_TASK_SET_FULL           (0x28)
+#define MPI_SCSI_STATUS_ACA_ACTIVE              (0x30)
+
+
+/* SCSIIO Reply SCSIState values */
+
+#define MPI_SCSI_STATE_AUTOSENSE_VALID          (0x01)
+#define MPI_SCSI_STATE_AUTOSENSE_FAILED         (0x02)
+#define MPI_SCSI_STATE_NO_SCSI_STATUS           (0x04)
+#define MPI_SCSI_STATE_TERMINATED               (0x08)
+#define MPI_SCSI_STATE_RESPONSE_INFO_VALID      (0x10)
+
+/* SCSIIO Reply ResponseInfo values */
+/* (FCP-1 RSP_CODE values and SPI-3 Packetized Failure codes) */
+
+#define MPI_SCSI_RSP_INFO_FUNCTION_COMPLETE     (0x00000000)
+#define MPI_SCSI_RSP_INFO_FCP_BURST_LEN_ERROR   (0x01000000)
+#define MPI_SCSI_RSP_INFO_CMND_FIELDS_INVALID   (0x02000000)
+#define MPI_SCSI_RSP_INFO_FCP_DATA_RO_ERROR     (0x03000000)
+#define MPI_SCSI_RSP_INFO_TASK_MGMT_UNSUPPORTED (0x04000000)
+#define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED      (0x05000000)
+#define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE   (0x06000000)
+
+
+/****************************************************************************/
+/*  SCSI Task Management messages                                           */
+/****************************************************************************/
+
+typedef struct _MSG_SCSI_TASK_MGMT
+{
+    U8                      TargetID;
+    U8                      Bus;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved;
+    U8                      TaskType;
+    U8                      Reserved1;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      LUN[8];
+    U32                     Reserved2[7];
+    U32                     TaskMsgContext;
+} MSG_SCSI_TASK_MGMT, MPI_POINTER PTR_SCSI_TASK_MGMT,
+  SCSITaskMgmt_t, MPI_POINTER pSCSITaskMgmt_t;
+
+/* TaskType values */
+
+#define MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK        (0x00000001)
+#define MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET     (0x00000002)
+#define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET      (0x00000003)
+#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS         (0x00000004)
+
+/* MsgFlags bits */
+#define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION  (0x00000002)
+
+/* SCSI Task Management Reply */
+typedef struct _MSG_SCSI_TASK_MGMT_REPLY
+{
+    U8                      TargetID;
+    U8                      Bus;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved;
+    U8                      TaskType;
+    U8                      Reserved1;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      Reserved2[2];
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     TerminationCount;
+} MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY,
+  SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t;
+
+#endif
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_ioc.h linux/drivers/message/fusion/lsi/mpi_ioc.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_ioc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_ioc.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,583 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_IOC.H
+ *          Title:  MPI IOC, Port, Event, FW Load, and ToolBox messages
+ *  Creation Date:  August 11, 2000
+ *
+ *    MPI Version:  01.01.05
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added _MSG_IOC_INIT_REPLY structure.
+ *  06-06-00  01.00.01  Added CurReplyFrameSize field to _MSG_IOC_FACTS_REPLY.
+ *  06-12-00  01.00.02  Added _MSG_PORT_ENABLE_REPLY structure.
+ *                      Added _MSG_EVENT_ACK_REPLY structure.
+ *                      Added _MSG_FW_DOWNLOAD_REPLY structure.
+ *                      Added _MSG_TOOLBOX_REPLY structure.
+ *  06-30-00  01.00.03  Added MaxLanBuckets to _PORT_FACT_REPLY structure.
+ *  07-27-00  01.00.04  Added _EVENT_DATA structure definitions for _SCSI,
+ *                      _LINK_STATUS, _LOOP_STATE and _LOGOUT.
+ *  08-11-00  01.00.05  Switched positions of MsgLength and Function fields in
+ *                      _MSG_EVENT_ACK_REPLY structure to match specification.
+ *  11-02-00  01.01.01  Original release for post 1.0 work.
+ *                      Added a value for Manufacturer to WhoInit.
+ *  12-04-00  01.01.02  Modified IOCFacts reply, added FWUpload messages, and
+ *                      removed toolbox message.
+ *  01-09-01  01.01.03  Added event enabled and disabled defines.
+ *                      Added structures for FwHeader and DataHeader.
+ *                      Added ImageType to FwUpload reply.
+ *  02-20-01  01.01.04  Started using MPI_POINTER.
+ *  02-27-01  01.01.05  Added event for RAID status change and its event data.
+ *                      Added IocNumber field to MSG_IOC_FACTS_REPLY.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_IOC_H
+#define MPI_IOC_H
+
+
+/*****************************************************************************
+*
+*               I O C    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  IOCInit message                                                         */
+/****************************************************************************/
+
+typedef struct _MSG_IOC_INIT
+{
+    U8                      WhoInit;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Flags;
+    U8                      MaxDevices;
+    U8                      MaxBuses;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     ReplyFrameSize;
+    U8                      Reserved1[2];
+    U32                     HostMfaHighAddr;
+    U32                     SenseBufferHighAddr;
+} MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT,
+  IOCInit_t, MPI_POINTER pIOCInit_t;
+
+typedef struct _MSG_IOC_INIT_REPLY
+{
+    U8                      WhoInit;
+    U8                      Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Flags;
+    U8                      MaxDevices;
+    U8                      MaxBuses;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_IOC_INIT_REPLY, MPI_POINTER PTR_MSG_IOC_INIT_REPLY,
+  IOCInitReply_t, MPI_POINTER pIOCInitReply_t;
+
+/* WhoInit values */
+
+#define MPI_WHOINIT_NO_ONE                      (0x00)
+#define MPI_WHOINIT_SYSTEM_BIOS                 (0x01)
+#define MPI_WHOINIT_ROM_BIOS                    (0x02)
+#define MPI_WHOINIT_PCI_PEER                    (0x03)
+#define MPI_WHOINIT_HOST_DRIVER                 (0x04)
+#define MPI_WHOINIT_MANUFACTURER                (0x05)
+
+
+/****************************************************************************/
+/*  IOC Facts message                                                       */
+/****************************************************************************/
+
+typedef struct _MSG_IOC_FACTS
+{
+    U8                      Reserved[2];
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+} MSG_IOC_FACTS, MPI_POINTER PTR_IOC_FACTS,
+  IOCFacts_t, MPI_POINTER pIOCFacts_t;
+
+/* IOC Facts Reply */
+
+typedef struct _MSG_IOC_FACTS_REPLY
+{
+    U16                     MsgVersion;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved;
+    U8                      IOCNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U8                      MaxChainDepth;
+    U8                      WhoInit;
+    U8                      BlockSize;
+    U8                      Flags;
+    U16                     ReplyQueueDepth;
+    U16                     RequestFrameSize;
+    U16                     FWVersion;
+    U16                     ProductID;
+    U32                     CurrentHostMfaHighAddr;
+    U16                     GlobalCredits;
+    U8                      NumberOfPorts;
+    U8                      EventState;
+    U32                     CurrentSenseBufferHighAddr;
+    U16                     CurReplyFrameSize;
+    U8                      MaxDevices;
+    U8                      MaxBuses;
+    U32                     FWImageSize;
+    U32                     DataImageSize;
+} MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY,
+  IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t;
+
+#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK      (0xFF00)
+#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK      (0x00FF)
+
+#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT     (0x01)
+#define MPI_IOCFACTS_FLAGS_DATA_IMAGE_UPLOAD    (0x02)
+
+#define MPI_IOCFACTS_EVENTSTATE_DISABLED        (0x00)
+#define MPI_IOCFACTS_EVENTSTATE_ENABLED         (0x01)
+
+
+
+/*****************************************************************************
+*
+*               P o r t    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Port Facts message and Reply                                            */
+/****************************************************************************/
+
+typedef struct _MSG_PORT_FACTS
+{
+     U8                     Reserved[2];
+     U8                     ChainOffset;
+     U8                     Function;
+     U8                     Reserved1[2];
+     U8                     PortNumber;
+     U8                     MsgFlags;
+     U32                    MsgContext;
+} MSG_PORT_FACTS, MPI_POINTER PTR_MSG_PORT_FACTS,
+  PortFacts_t, MPI_POINTER pPortFacts_t;
+
+typedef struct _MSG_PORT_FACTS_REPLY
+{
+     U16                    Reserved;
+     U8                     MsgLength;
+     U8                     Function;
+     U16                    Reserved1;
+     U8                     PortNumber;
+     U8                     MsgFlags;
+     U32                    MsgContext;
+     U16                    Reserved2;
+     U16                    IOCStatus;
+     U32                    IOCLogInfo;
+     U8                     Reserved3;
+     U8                     PortType;
+     U16                    MaxDevices;
+     U16                    PortSCSIID;
+     U16                    ProtocolFlags;
+     U16                    MaxPostedCmdBuffers;
+     U16                    MaxPersistentIDs;
+     U16                    MaxLanBuckets;
+     U16                    Reserved4;
+     U32                    Reserved5;
+} MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY,
+  PortFactsReply_t, MPI_POINTER pPortFactsReply_t;
+
+
+/* PortTypes values */
+
+#define MPI_PORTFACTS_PORTTYPE_INACTIVE         (0x00)
+#define MPI_PORTFACTS_PORTTYPE_SCSI             (0x01)
+#define MPI_PORTFACTS_PORTTYPE_FC               (0x10)
+
+/* ProtocolFlags values */
+
+#define MPI_PORTFACTS_PROTOCOL_LOGBUSADDR       (0x01)
+#define MPI_PORTFACTS_PROTOCOL_LAN              (0x02)
+#define MPI_PORTFACTS_PROTOCOL_TARGET           (0x04)
+#define MPI_PORTFACTS_PROTOCOL_INITIATOR        (0x08)
+
+
+/****************************************************************************/
+/*  Port Enable Message                                                     */
+/****************************************************************************/
+
+typedef struct _MSG_PORT_ENABLE
+{
+    U8                      Reserved[2];
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[2];
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+} MSG_PORT_ENABLE, MPI_POINTER PTR_MSG_PORT_ENABLE,
+  PortEnable_t, MPI_POINTER pPortEnable_t;
+
+typedef struct _MSG_PORT_ENABLE_REPLY
+{
+    U8                      Reserved[2];
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[2];
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_PORT_ENABLE_REPLY, MPI_POINTER PTR_MSG_PORT_ENABLE_REPLY,
+  PortEnableReply_t, MPI_POINTER pPortEnableReply_t;
+
+
+/*****************************************************************************
+*
+*               E v e n t    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Event Notification messages                                             */
+/****************************************************************************/
+
+typedef struct _MSG_EVENT_NOTIFY
+{
+    U8                      Switch;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+} MSG_EVENT_NOTIFY, MPI_POINTER PTR_MSG_EVENT_NOTIFY,
+  EventNotification_t, MPI_POINTER pEventNotification_t;
+
+/* Event Notification Reply */
+
+typedef struct _MSG_EVENT_NOTIFY_REPLY
+{
+     U16                    EventDataLength;
+     U8                     MsgLength;
+     U8                     Function;
+     U8                     Reserved1[2];
+     U8                     AckRequired;
+     U8                     MsgFlags;
+     U32                    MsgContext;
+     U8                     Reserved2[2];
+     U16                    IOCStatus;
+     U32                    IOCLogInfo;
+     U32                    Event;
+     U32                    EventContext;
+     U32                    Data[1];
+} MSG_EVENT_NOTIFY_REPLY, MPI_POINTER PTR_MSG_EVENT_NOTIFY_REPLY,
+  EventNotificationReply_t, MPI_POINTER pEventNotificationReply_t;
+
+/* Event Acknowledge */
+
+typedef struct _MSG_EVENT_ACK
+{
+    U8                      Reserved[2];
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U32                     Event;
+    U32                     EventContext;
+} MSG_EVENT_ACK, MPI_POINTER PTR_MSG_EVENT_ACK,
+  EventAck_t, MPI_POINTER pEventAck_t;
+
+typedef struct _MSG_EVENT_ACK_REPLY
+{
+    U8                      Reserved[2];
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_EVENT_ACK_REPLY, MPI_POINTER PTR_MSG_EVENT_ACK_REPLY,
+  EventAckReply_t, MPI_POINTER pEventAckReply_t;
+
+
+/* Switch */
+
+#define MPI_EVENT_NOTIFICATION_SWITCH_OFF   (0x00)
+#define MPI_EVENT_NOTIFICATION_SWITCH_ON    (0x01)
+
+/* Event */
+
+#define MPI_EVENT_NONE                      (0x00000000)
+#define MPI_EVENT_LOG_DATA                  (0x00000001)
+#define MPI_EVENT_STATE_CHANGE              (0x00000002)
+#define MPI_EVENT_UNIT_ATTENTION            (0x00000003)
+#define MPI_EVENT_IOC_BUS_RESET             (0x00000004)
+#define MPI_EVENT_EXT_BUS_RESET             (0x00000005)
+#define MPI_EVENT_RESCAN                    (0x00000006)
+#define MPI_EVENT_LINK_STATUS_CHANGE        (0x00000007)
+#define MPI_EVENT_LOOP_STATE_CHANGE         (0x00000008)
+#define MPI_EVENT_LOGOUT                    (0x00000009)
+#define MPI_EVENT_EVENT_CHANGE              (0x0000000A)
+#define MPI_EVENT_RAID_STATUS_CHANGE        (0x0000000B)
+
+/* AckRequired field values */
+
+#define MPI_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00)
+#define MPI_EVENT_NOTIFICATION_ACK_REQUIRED     (0x01)
+
+/* SCSI Event data for Port, Bus and Device forms) */
+
+typedef struct _EVENT_DATA_SCSI
+{
+    U8                      TargetID;
+    U8                      BusPort;
+    U16                     Reserved;
+} EVENT_DATA_SCSI, MPI_POINTER PTR_EVENT_DATA_SCSI,
+  EventDataScsi_t, MPI_POINTER pEventDataScsi_t;
+
+/* MPI Link Status Change Event data */
+
+typedef struct _EVENT_DATA_LINK_STATUS
+{
+    U8                      State;
+    U8                      Reserved;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      Port;
+    U16                     Reserved3;
+} EVENT_DATA_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_LINK_STATUS,
+  EventDataLinkStatus_t, MPI_POINTER pEventDataLinkStatus_t;
+
+#define MPI_EVENT_LINK_STATUS_FAILURE       (0x00000000)
+#define MPI_EVENT_LINK_STATUS_ACTIVE        (0x00000001)
+
+/* MPI Loop State Change Event data */
+
+typedef struct _EVENT_DATA_LOOP_STATE
+{
+    U8                      Character4;
+    U8                      Character3;
+    U8                      Type;
+    U8                      Reserved;
+    U8                      Reserved1;
+    U8                      Port;
+    U16                     Reserved2;
+} EVENT_DATA_LOOP_STATE, MPI_POINTER PTR_EVENT_DATA_LOOP_STATE,
+  EventDataLoopState_t, MPI_POINTER pEventDataLoopState_t;
+
+#define MPI_EVENT_LOOP_STATE_CHANGE_LIP     (0x0001)
+#define MPI_EVENT_LOOP_STATE_CHANGE_LPE     (0x0002)
+#define MPI_EVENT_LOOP_STATE_CHANGE_LPB     (0x0003)
+
+/* MPI LOGOUT Event data */
+
+typedef struct _EVENT_DATA_LOGOUT
+{
+    U32                     NPortID;
+    U8                      Reserved;
+    U8                      Port;
+    U16                     Reserved1;
+} EVENT_DATA_LOGOUT, MPI_POINTER PTR_EVENT_DATA_LOGOUT,
+  EventDataLogout_t, MPI_POINTER pEventDataLogout_t;
+
+/* MPI RAID Status Change Event data */
+
+typedef struct _EVENT_DATA_RAID_STATUS_CHANGE
+{
+    U8                      VolumeTargetID;
+    U8                      VolumeBus;
+    U8                      ReasonCode;
+    U8                      PhysDiskNum;
+    U8                      ASC;
+    U8                      ASCQ;
+    U16                     Reserved;
+} EVENT_DATA_RAID_STATUS_CHANGE, MPI_POINTER PTR_EVENT_DATA_RAID_STATUS_CHANGE,
+  MpiEventDataRaidStatusChange_t, MPI_POINTER pMpiEventDataRaidStatusChange_t;
+
+
+/* MPI RAID Status Change Event data ReasonCode values */
+
+#define MPI_EVENT_RAID_DATA_RC_VOLUME_OPTIMAL       (0x00)
+#define MPI_EVENT_RAID_DATA_RC_VOLUME_DEGRADED      (0x01)
+#define MPI_EVENT_RAID_DATA_RC_STARTED_RESYNC       (0x02)
+#define MPI_EVENT_RAID_DATA_RC_DISK_ADDED           (0x03)
+#define MPI_EVENT_RAID_DATA_RC_DISK_NOT_RESPONDING  (0x04)
+#define MPI_EVENT_RAID_DATA_RC_SMART_DATA           (0x05)
+
+
+/*****************************************************************************
+*
+*               F i r m w a r e    L o a d    M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/*  Firmware Download message and associated structures                     */
+/****************************************************************************/
+
+typedef struct _MSG_FW_DOWNLOAD
+{
+    U8                      ImageType;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    SGE_MPI_UNION           SGL;
+} MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD,
+  FWDownload_t, MPI_POINTER pFWDownload_t;
+
+#define MPI_FW_DOWNLOAD_ITYPE_RESERVED      (0x00)
+#define MPI_FW_DOWNLOAD_ITYPE_FW            (0x01)
+#define MPI_FW_DOWNLOAD_ITYPE_BIOS          (0x02)
+
+
+typedef struct _FWDownloadTCSGE
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     Reserved1;
+    U32                     ImageOffset;
+    U32                     ImageSize;
+} FW_DOWNLOAD_TCSGE, MPI_POINTER PTR_FW_DOWNLOAD_TCSGE,
+  FWDownloadTCSGE_t, MPI_POINTER pFWDownloadTCSGE_t;
+
+/* Firmware Download reply */
+typedef struct _MSG_FW_DOWNLOAD_REPLY
+{
+    U8                      ImageType;
+    U8                      Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_FW_DOWNLOAD_REPLY, MPI_POINTER PTR_MSG_FW_DOWNLOAD_REPLY,
+  FWDownloadReply_t, MPI_POINTER pFWDownloadReply_t;
+
+
+/****************************************************************************/
+/*  Firmware Upload message and associated structures                       */
+/****************************************************************************/
+
+typedef struct _MSG_FW_UPLOAD
+{
+    U8                      ImageType;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    SGE_MPI_UNION           SGL;
+} MSG_FW_UPLOAD, MPI_POINTER PTR_MSG_FW_UPLOAD,
+  FWUpload_t, MPI_POINTER pFWUpload_t;
+
+#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM      (0x00)
+#define MPI_FW_UPLOAD_ITYPE_FW_FLASH        (0x01)
+#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH      (0x02)
+#define MPI_FW_UPLOAD_ITYPE_DATA_IOC_MEM    (0x03)
+
+typedef struct _FWUploadTCSGE
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     Reserved1;
+    U32                     ImageOffset;
+    U32                     ImageSize;
+} FW_UPLOAD_TCSGE, MPI_POINTER PTR_FW_UPLOAD_TCSGE,
+  FWUploadTCSGE_t, MPI_POINTER pFWUploadTCSGE_t;
+
+/* Firmware Upload reply */
+typedef struct _MSG_FW_UPLOAD_REPLY
+{
+    U8                      ImageType;
+    U8                      Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved1[3];
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     ActualImageSize;
+} MSG_FW_UPLOAD_REPLY, MPI_POINTER PTR_MSG_FW_UPLOAD_REPLY,
+  FWUploadReply_t, MPI_POINTER pFWUploadReply_t;
+
+
+typedef struct _MPI_FW_HEADER
+{
+    U32                     ArmBranchInstruction0;
+    U32                     Signature0;
+    U32                     Signature1;
+    U32                     Signature2;
+    U32                     ArmBranchInstruction1;
+    U32                     ArmBranchInstruction2;
+    U32                     Reserved;
+    U32                     Checksum;
+    U16                     VendorId;
+    U16                     ProductId;
+    U16                     FwVersion;
+    U16                     Reserved1;
+    U32                     SeqCodeVersion;
+    U32                     ImageSize;
+    U32                     Reserved2;
+    U32                     LoadStartAddress;
+    U32                     IopResetVectorValue;
+    U32                     IopResetRegAddr;
+    U32                     VersionNameWhat;
+    U8                      VersionName[32];
+    U32                     VendorNameWhat;
+    U8                      VendorName[32];
+} MPI_FW_HEADER, MPI_POINTER PTR_MPI_FW_HEADER,
+  MpiFwHeader_t, MPI_POINTER pMpiFwHeader_t;
+
+#define MPI_FW_HEADER_WHAT_SIGNATURE    (0x29232840)
+
+
+typedef struct _MPI_DATA_HEADER
+{
+    U32                     Signature;
+    U16                     FunctionNumber;
+    U16                     Length;
+    U32                     Checksum;
+    U32                     LoadStartAddress;
+} MPI_DATA_HEADER, MPI_POINTER PTR_MPI_DATA_HEADER,
+  MpiDataHeader_t, MPI_POINTER pMpiDataHeader_t;
+
+#define MPI_DATA_HEADER_SIGNATURE       (0x43504147)
+
+#endif
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_lan.h linux/drivers/message/fusion/lsi/mpi_lan.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_lan.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_lan.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,204 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_LAN.H
+ *          Title:  MPI LAN messages and structures
+ *  Creation Date:  June 30, 2000
+ *
+ *    MPI Version:  01.01.02
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  05-24-00  00.10.02  Added LANStatus field to _MSG_LAN_SEND_REPLY.
+ *                      Added LANStatus field to _MSG_LAN_RECEIVE_POST_REPLY.
+ *                      Moved ListCount field in _MSG_LAN_RECEIVE_POST_REPLY.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-12-00  01.00.02  Added MPI_ to BUCKETSTATUS_ definitions.
+ *  06-22-00  01.00.03  Major changes to match new LAN definition in 1.0 spec.
+ *  06-30-00  01.00.04  Added Context Reply definitions per revised proposal.
+ *                      Changed transaction context usage to bucket/buffer.
+ *  07-05-00  01.00.05  Removed LAN_RECEIVE_POST_BUCKET_CONTEXT_MASK definition
+ *                      to lan private header file
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  02-20-01  01.01.02  Started using MPI_POINTER.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_LAN_H
+#define MPI_LAN_H
+
+
+/******************************************************************************
+*
+*               L A N    M e s s a g e s
+*
+*******************************************************************************/
+
+/* LANSend messages */
+
+typedef struct _MSG_LAN_SEND_REQUEST
+{
+    U16                     Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     Reserved2;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    SGE_MPI_UNION           SG_List[1];
+} MSG_LAN_SEND_REQUEST, MPI_POINTER PTR_MSG_LAN_SEND_REQUEST,
+  LANSendRequest_t, MPI_POINTER pLANSendRequest_t;
+
+
+typedef struct _MSG_LAN_SEND_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved2;
+    U8                      NumberOfContexts;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     BufferContext;
+} MSG_LAN_SEND_REPLY, MPI_POINTER PTR_MSG_LAN_SEND_REPLY,
+  LANSendReply_t, MPI_POINTER pLANSendReply_t;
+
+
+/* LANReceivePost */
+
+typedef struct _MSG_LAN_RECEIVE_POST_REQUEST
+{
+    U16                     Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     Reserved2;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U32                     BucketCount;
+    SGE_MPI_UNION           SG_List[1];
+} MSG_LAN_RECEIVE_POST_REQUEST, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REQUEST,
+  LANReceivePostRequest_t, MPI_POINTER pLANReceivePostRequest_t;
+
+
+typedef struct _MSG_LAN_RECEIVE_POST_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      Reserved2;
+    U8                      NumberOfContexts;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     BucketsRemaining;
+    U32                     PacketOffset;
+    U32                     PacketLength;
+    U32                     BucketContext[1];
+} MSG_LAN_RECEIVE_POST_REPLY, MPI_POINTER PTR_MSG_LAN_RECEIVE_POST_REPLY,
+  LANReceivePostReply_t, MPI_POINTER pLANReceivePostReply_t;
+
+
+/* LANReset */
+
+typedef struct _MSG_LAN_RESET_REQUEST
+{
+    U16                     Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     Reserved2;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+} MSG_LAN_RESET_REQUEST, MPI_POINTER PTR_MSG_LAN_RESET_REQUEST,
+  LANResetRequest_t, MPI_POINTER pLANResetRequest_t;
+
+
+typedef struct _MSG_LAN_RESET_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved2;
+    U8                      PortNumber;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_LAN_RESET_REPLY, MPI_POINTER PTR_MSG_LAN_RESET_REPLY,
+  LANResetReply_t, MPI_POINTER pLANResetReply_t;
+
+
+/****************************************************************************/
+/* LAN Context Reply defines and macros                                     */
+/****************************************************************************/
+
+#define LAN_REPLY_PACKET_LENGTH_MASK            (0x0000FFFF)
+#define LAN_REPLY_PACKET_LENGTH_SHIFT           (0)
+#define LAN_REPLY_BUCKET_CONTEXT_MASK           (0x07FF0000)
+#define LAN_REPLY_BUCKET_CONTEXT_SHIFT          (16)
+#define LAN_REPLY_BUFFER_CONTEXT_MASK           (0x07FFFFFF)
+#define LAN_REPLY_BUFFER_CONTEXT_SHIFT          (0)
+#define LAN_REPLY_FORM_MASK                     (0x18000000)
+#define LAN_REPLY_FORM_RECEIVE_SINGLE           (0x00)
+#define LAN_REPLY_FORM_RECEIVE_MULTIPLE         (0x01)
+#define LAN_REPLY_FORM_SEND_SINGLE              (0x02)
+#define LAN_REPLY_FORM_MESSAGE_CONTEXT          (0x03)
+#define LAN_REPLY_FORM_SHIFT                    (27)
+
+#define GET_LAN_PACKET_LENGTH(x)    (((x) & LAN_REPLY_PACKET_LENGTH_MASK)   \
+                                        >> LAN_REPLY_PACKET_LENGTH_SHIFT)
+
+#define SET_LAN_PACKET_LENGTH(x, lth)                                       \
+            ((x) = ((x) & ~LAN_REPLY_PACKET_LENGTH_MASK) |                  \
+                            (((lth) << LAN_REPLY_PACKET_LENGTH_SHIFT) &     \
+                                        LAN_REPLY_PACKET_LENGTH_MASK))
+
+#define GET_LAN_BUCKET_CONTEXT(x)   (((x) & LAN_REPLY_BUCKET_CONTEXT_MASK)  \
+                                        >> LAN_REPLY_BUCKET_CONTEXT_SHIFT)
+
+#define SET_LAN_BUCKET_CONTEXT(x, ctx)                                      \
+            ((x) = ((x) & ~LAN_REPLY_BUCKET_CONTEXT_MASK) |                 \
+                            (((ctx) << LAN_REPLY_BUCKET_CONTEXT_SHIFT) &    \
+                                        LAN_REPLY_BUCKET_CONTEXT_MASK))
+
+#define GET_LAN_BUFFER_CONTEXT(x)   (((x) & LAN_REPLY_BUFFER_CONTEXT_MASK)  \
+                                        >> LAN_REPLY_BUFFER_CONTEXT_SHIFT)
+
+#define SET_LAN_BUFFER_CONTEXT(x, ctx)                                      \
+            ((x) = ((x) & ~LAN_REPLY_BUFFER_CONTEXT_MASK) |                 \
+                            (((ctx) << LAN_REPLY_BUFFER_CONTEXT_SHIFT) &    \
+                                        LAN_REPLY_BUFFER_CONTEXT_MASK))
+
+#define GET_LAN_FORM(x)             (((x) & LAN_REPLY_FORM_MASK)            \
+                                        >> LAN_REPLY_FORM_SHIFT)
+
+#define SET_LAN_FORM(x, frm)                                                \
+            ((x) = ((x) & ~LAN_REPLY_FORM_MASK) |                           \
+                            (((frm) << LAN_REPLY_FORM_SHIFT) &              \
+                                        LAN_REPLY_FORM_MASK))
+
+
+/****************************************************************************/
+/* LAN Current Device State defines                                         */
+/****************************************************************************/
+
+#define MPI_LAN_DEVICE_STATE_RESET                     (0x00)
+#define MPI_LAN_DEVICE_STATE_OPERATIONAL               (0x01)
+
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_targ.h linux/drivers/message/fusion/lsi/mpi_targ.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_targ.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_targ.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,328 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_TARG.H
+ *          Title:  MPI Target mode messages and structures
+ *  Creation Date:  June 22, 2000
+ *
+ *    MPI Version:  01.01.03
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  06-22-00  01.00.02  Added _MSG_TARGET_CMD_BUFFER_POST_REPLY structure.
+ *                      Corrected DECSRIPTOR typo to DESCRIPTOR.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *                      Modified target mode to use IoIndex instead of
+ *                      HostIndex and IocIndex. Added Alias.
+ *  01-09-01  01.01.02  Added defines for TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER
+ *                      and TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER.
+ *  02-20-01  01.01.03  Started using MPI_POINTER.
+ *                      Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and
+ *                      MPI_TARGET_FCP_CMD_BUFFER.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_TARG_H
+#define MPI_TARG_H
+
+
+/******************************************************************************
+*
+*        S C S I    T a r g e t    M e s s a g e s
+*
+*******************************************************************************/
+
+typedef struct _CMD_BUFFER_DESCRIPTOR
+{
+    U16                     IoIndex;
+    U16                     Reserved;
+    union
+    {
+        U32                 PhysicalAddress32;
+        U64                 PhysicalAddress64;
+    } u;
+} CMD_BUFFER_DESCRIPTOR, MPI_POINTER PTR_CMD_BUFFER_DESCRIPTOR,
+  CmdBufferDescriptor_t, MPI_POINTER pCmdBufferDescriptor_t;
+
+
+/****************************************************************************/
+/* Target Command Buffer Post Request                                       */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_REQUEST
+{
+    U8                      BufferPostFlags;
+    U8                      BufferCount;
+    U8                      ChainOffset;
+    U8                      Function;
+    U8                      BufferLength;
+    U8                      Reserved;
+    U8                      Reserved1;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    CMD_BUFFER_DESCRIPTOR   Buffer[1];
+} MSG_TARGET_CMD_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REQUEST,
+  TargetCmdBufferPostRequest_t, MPI_POINTER pTargetCmdBufferPostRequest_t;
+
+#define CMD_BUFFER_POST_FLAGS_PORT_MASK         (0x01)
+#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_MASK    (0x80)
+#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_32      (0)
+#define CMD_BUFFER_POST_FLAGS_ADDR_MODE_64      (1)
+#define CMD_BUFFER_POST_FLAGS_64_BIT_ADDR       (0x80)
+
+#define CMD_BUFFER_POST_IO_INDEX_MASK           (0x00003FFF)
+
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_REPLY
+{
+    U8                      BufferPostFlags;
+    U8                      BufferCount;
+    U8                      MsgLength;
+    U8                      Function;
+    U8                      BufferLength;
+    U8                      Reserved;
+    U8                      Reserved1;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved2;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+} MSG_TARGET_CMD_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_REPLY,
+  TargetCmdBufferPostReply_t, MPI_POINTER pTargetCmdBufferPostReply_t;
+
+
+typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U8                      PriorityReason;
+    U8                      Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     ReplyWord;
+} MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY,
+  PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t;
+
+#define PRIORITY_REASON_NO_DISCONNECT           (0x00)
+#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT    (0x01)
+#define PRIORITY_REASON_UNKNOWN                 (0xFF)
+
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     ReplyWord;
+} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
+  MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
+  TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t;
+
+
+typedef struct _MPI_TARGET_FCP_CMD_BUFFER
+{
+    U8      FcpLun[8];
+    U8      FcpCntl[4];
+    U8      FcpCdb[16];
+    U32     FcpDl;
+} MPI_TARGET_FCP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_FCP_CMD_BUFFER,
+  MpiTargetFcpCmdBuffer, MPI_POINTER pMpiTargetFcpCmdBuffer;
+
+
+typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER
+{
+    /* SPI L_Q information unit */
+    U8      L_QType;
+    U8      Reserved;
+    U16     Tag;
+    U8      LogicalUnitNumber[8];
+    U32     DataLength;
+    /* SPI command information unit */
+    U8      ReservedFirstByteOfCommandIU;
+    U8      TaskAttribute;
+    U8      TaskManagementFlags;
+    U8      AdditionalCDBLength;
+    U8      CDB[16];
+} MPI_TARGET_SCSI_SPI_CMD_BUFFER,
+  MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER,
+  MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer;
+
+
+/****************************************************************************/
+/* Target Assist Request                                                    */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_ASSIST_REQUEST
+{
+    U8                      StatusCode;
+    U8                      TargetAssistFlags;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     QueueTag;
+    U8                      Reserved;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U32                     ReplyWord;
+    U8                      LUN[8];
+    U32                     RelativeOffset;
+    U32                     DataLength;
+    SGE_IO_UNION            SGL[1];
+} MSG_TARGET_ASSIST_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_REQUEST,
+  TargetAssistRequest_t, MPI_POINTER pTargetAssistRequest_t;
+
+#define TARGET_ASSIST_FLAGS_DATA_DIRECTION          (0x01)
+#define TARGET_ASSIST_FLAGS_AUTO_STATUS             (0x02)
+#define TARGET_ASSIST_FLAGS_HIGH_PRIORITY           (0x04)
+#define TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER       (0x80)
+
+
+typedef struct _MSG_TARGET_ERROR_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     ReplyWord;
+    U32                     TransferCount;
+} MSG_TARGET_ERROR_REPLY, MPI_POINTER PTR_MSG_TARGET_ERROR_REPLY,
+  TargetErrorReply_t, MPI_POINTER pTargetErrorReply_t;
+
+
+/****************************************************************************/
+/* Target Status Send Request                                               */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_STATUS_SEND_REQUEST
+{
+    U8                      StatusCode;
+    U8                      StatusFlags;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     QueueTag;
+    U8                      Reserved;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U32                     ReplyWord;
+    U8                      LUN[8];
+    SGE_SIMPLE_UNION        StatusDataSGE;
+} MSG_TARGET_STATUS_SEND_REQUEST, MPI_POINTER PTR_MSG_TARGET_STATUS_SEND_REQUEST,
+  TargetStatusSendRequest_t, MPI_POINTER pTargetStatusSendRequest_t;
+
+#define TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS   (0x01)
+#define TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER  (0x80)
+
+
+/****************************************************************************/
+/* Target Mode Abort Request                                                */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_MODE_ABORT_REQUEST
+{
+    U8                      AbortType;
+    U8                      Reserved;
+    U8                      ChainOffset;
+    U8                      Function;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U32                     ReplyWord;
+    U32                     MsgContextToAbort;
+} MSG_TARGET_MODE_ABORT, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT,
+  TargetModeAbort_t, MPI_POINTER pTargetModeAbort_t;
+
+#define TARGET_MODE_ABORT_TYPE_ALL_CMD_BUFFERS      (0x00)
+#define TARGET_MODE_ABORT_TYPE_ALL_IO               (0x01)
+#define TARGET_MODE_ABORT_TYPE_EXACT_IO             (0x02)
+#define TARGET_MODE_ABORT_TYPE_EXACT_IO_REQUEST     (0x03)
+
+/* Target Mode Abort Reply */
+
+typedef struct _MSG_TARGET_MODE_ABORT_REPLY
+{
+    U16                     Reserved;
+    U8                      MsgLength;
+    U8                      Function;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      MsgFlags;
+    U32                     MsgContext;
+    U16                     Reserved3;
+    U16                     IOCStatus;
+    U32                     IOCLogInfo;
+    U32                     AbortCount;
+} MSG_TARGET_MODE_ABORT_REPLY, MPI_POINTER PTR_MSG_TARGET_MODE_ABORT_REPLY,
+  TargetModeAbortReply_t, MPI_POINTER pTargetModeAbortReply_t;
+
+
+/****************************************************************************/
+/* Target Mode Context Reply                                                */
+/****************************************************************************/
+
+#define TARGET_MODE_REPLY_IO_INDEX_MASK         (0x00003FFF)
+#define TARGET_MODE_REPLY_IO_INDEX_SHIFT        (0)
+#define TARGET_MODE_REPLY_INITIATOR_INDEX_MASK  (0x03FFC000)
+#define TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT (14)
+#define TARGET_MODE_REPLY_ALIAS_MASK            (0x0C000000)
+#define TARGET_MODE_REPLY_ALIAS_SHIFT           (26)
+#define TARGET_MODE_REPLY_PORT_MASK             (0x10000000)
+#define TARGET_MODE_REPLY_PORT_SHIFT            (28)
+
+
+#define GET_IO_INDEX(x)     (((x) & TARGET_MODE_REPLY_IO_INDEX_MASK)           \
+                                    >> TARGET_MODE_REPLY_IO_INDEX_SHIFT)
+
+#define SET_IO_INDEX(t, i)                                                     \
+            ((t) = ((t) & ~TARGET_MODE_REPLY_IO_INDEX_MASK) |                  \
+                              (((i) << TARGET_MODE_REPLY_IO_INDEX_SHIFT) &     \
+                                             TARGET_MODE_REPLY_IO_INDEX_MASK))
+
+#define GET_INITIATOR_INDEX(x) (((x) & TARGET_MODE_REPLY_INITIATOR_INDEX_MASK) \
+                                   >> TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT)
+
+#define SET_INITIATOR_INDEX(t, ii)                                             \
+        ((t) = ((t) & ~TARGET_MODE_REPLY_INITIATOR_INDEX_MASK) |               \
+                        (((ii) << TARGET_MODE_REPLY_INITIATOR_INDEX_SHIFT) &   \
+                                      TARGET_MODE_REPLY_INITIATOR_INDEX_MASK))
+
+#define GET_ALIAS(x) (((x) & TARGET_MODE_REPLY_ALIAS_MASK)                     \
+                                               >> TARGET_MODE_REPLY_ALIAS_SHIFT)
+
+#define SET_ALIAS(t, a)  ((t) = ((t) & ~TARGET_MODE_REPLY_ALIAS_MASK) |        \
+                                    (((a) << TARGET_MODE_REPLY_ALIAS_SHIFT) &  \
+                                                 TARGET_MODE_REPLY_ALIAS_MASK))
+
+#define GET_PORT(x) (((x) & TARGET_MODE_REPLY_PORT_MASK)                       \
+                                               >> TARGET_MODE_REPLY_PORT_SHIFT)
+
+#define SET_PORT(t, p)  ((t) = ((t) & ~TARGET_MODE_REPLY_PORT_MASK) |          \
+                                    (((p) << TARGET_MODE_REPLY_PORT_SHIFT) &   \
+                                                  TARGET_MODE_REPLY_PORT_MASK))
+
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_type.h linux/drivers/message/fusion/lsi/mpi_type.h
--- linux-2.4.7-pre3/drivers/message/fusion/lsi/mpi_type.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/lsi/mpi_type.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation.
+ *
+ *
+ *           Name:  MPI_TYPE.H
+ *          Title:  MPI Basic type definitions
+ *  Creation Date:  June 6, 2000
+ *
+ *    MPI Version:  01.01.02
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
+ *  06-06-00  01.00.01  Update version number for 1.0 release.
+ *  11-02-00  01.01.01  Original release for post 1.0 work
+ *  02-20-01  01.01.02  Added define and ifdef for MPI_POINTER.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_TYPE_H
+#define MPI_TYPE_H
+
+
+/*******************************************************************************
+ * Define MPI_POINTER if it hasn't already been defined. By default MPI_POINTER
+ * is defined to be a near pointer. MPI_POINTER can be defined as a far pointer
+ * by defining MPI_POINTER as "far *" before this header file is included.
+ */
+#ifndef MPI_POINTER
+#define MPI_POINTER     *
+#endif
+
+
+/*****************************************************************************
+*
+*               B a s i c    T y p e s
+*
+*****************************************************************************/
+
+typedef signed   char   S8;
+typedef unsigned char   U8;
+typedef signed   short  S16;
+typedef unsigned short  U16;
+
+
+#if defined(unix) || defined(__arm) || defined(ALPHA)
+
+    typedef signed   int   S32;
+    typedef unsigned int   U32;
+
+#else
+
+    typedef signed   long  S32;
+    typedef unsigned long  U32;
+
+#endif
+
+
+typedef struct _S64
+{
+    U32          Low;
+    S32          High;
+} S64;
+
+typedef struct _U64
+{
+    U32          Low;
+    U32          High;
+} U64;
+
+
+/****************************************************************************/
+/*  Pointers                                                                */
+/****************************************************************************/
+
+typedef S8      *PS8;
+typedef U8      *PU8;
+typedef S16     *PS16;
+typedef U16     *PU16;
+typedef S32     *PS32;
+typedef U32     *PU32;
+typedef S64     *PS64;
+typedef U64     *PU64;
+
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptbase.c linux/drivers/message/fusion/mptbase.c
--- linux-2.4.7-pre3/drivers/message/fusion/mptbase.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptbase.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,3360 @@
+/*
+ *  linux/drivers/message/fusion/mptbase.c
+ *      High performance SCSI + LAN / Fibre Channel device drivers.
+ *      This is the Fusion MPT base driver which supports multiple
+ *      (SCSI + LAN) specialized protocol drivers.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *      There are lots of people not mentioned below that deserve credit
+ *      and thanks but won't get it here - sorry in advance that you
+ *      got overlooked.
+ *
+ *      This driver would not exist if not for Alan Cox's development
+ *      of the linux i2o driver.
+ *
+ *      A special thanks to Noah Romer (LSI Logic) for tons of work
+ *      and tough debugging on the LAN driver, especially early on;-)
+ *      And to Roger Hickerson (LSI Logic) for tirelessly supporting
+ *      this driver project.
+ *
+ *      All manner of help from Stephen Shirron (LSI Logic):
+ *      low-level FC analysis, debug + various fixes in FCxx firmware,
+ *      initial port to alpha platform, various driver code optimizations,
+ *      being a faithful sounding board on all sorts of issues & ideas,
+ *      etc.
+ *
+ *      A huge debt of gratitude is owed to David S. Miller (DaveM)
+ *      for fixing much of the stupid and broken stuff in the early
+ *      driver while porting to sparc64 platform.  THANK YOU!
+ *
+ *      Special thanks goes to the I2O LAN driver people at the
+ *      University of Helsinki, who, unbeknownst to them, provided
+ *      the inspiration and initial structure for this driver.
+ *
+ *      A really huge debt of gratitude is owed to Eddie C. Dost
+ *      for gobs of hard work fixing and optimizing LAN code.
+ *      THANK YOU!
+ *
+ *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Originally By: Steven J. Ralston
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: mptbase.c,v 1.47 2001/03/22 10:32:23 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <asm/io.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "mptbase.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"Fusion MPT base driver"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"mptbase"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+
+/*
+ *  cmd line parameters
+ */
+MODULE_PARM(PortIo, "0-1i");
+MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");
+MODULE_PARM(HardReset, "0-1i");
+MODULE_PARM_DESC(HardReset, "0=Disable HardReset, [1]=Enable HardReset");
+static int PortIo = 0;
+static int HardReset = 1;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Public data...
+ */
+int mpt_lan_index = 0;
+int mpt_stm_index = 0;
+
+void *mpt_v_ASCQ_TablePtr = NULL;
+const char **mpt_ScsiOpcodesPtr = NULL;
+int mpt_ASCQ_TableSz = 0;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Private data...
+ */
+					/* Adapter lookup table */
+static MPT_ADAPTER		*mpt_adapters[MPT_MAX_ADAPTERS] = {0};
+static MPT_ADAPTER_TRACKER	 MptAdapters;
+					/* Callback lookup table */
+static MPT_CALLBACK		 MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
+					/* Protocol driver class lookup table */
+static int	 		 MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
+					/* Event handler lookup table */
+static MPT_EVHANDLER		 MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
+
+static int	FusionInitCalled = 0;
+static int	mpt_base_index = -1;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Forward protos...
+ */
+static void	mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
+static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
+
+static int 	mpt_adapter_install(struct pci_dev *pdev);
+static void	mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
+static void	mpt_adapter_disable(MPT_ADAPTER *ioc);
+static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
+
+static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
+static u32	GetIocState(MPT_ADAPTER *ioc, int cooked);
+static int	GetIocFacts(MPT_ADAPTER *ioc);
+static int	GetPortFacts(MPT_ADAPTER *ioc);
+static int	SendIocInit(MPT_ADAPTER *ioc);
+static int	SendPortEnable(MPT_ADAPTER *ioc, int portnum);
+static int	mpt_fc9x9_reset(MPT_ADAPTER *ioc);
+static int	KickStart(MPT_ADAPTER *ioc);
+static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type);
+static int	PrimeIocFifos(MPT_ADAPTER *ioc);
+static int	HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply);
+static int	WaitForDoorbellAck(MPT_ADAPTER *ioc);
+static int	WaitForDoorbellInt(MPT_ADAPTER *ioc);
+static int	WaitForDoorbellReply(MPT_ADAPTER *ioc);
+static int	GetLanConfigPages(MPT_ADAPTER *ioc);
+static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
+static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+
+static int	procmpt_create(void);
+#ifdef CONFIG_PROC_FS
+static int	procmpt_destroy(void);
+#endif
+static int	procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data);
+static int	procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data);
+/*static int	procmpt_info(char *buf, char **start, off_t offset, int len);*/
+
+static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
+static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+
+static struct proc_dir_entry	*procmpt_root_dir = NULL;
+
+int		fusion_init(void);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* 20000207 -sralston
+ *  GRRRRR...  IOSpace (port i/o) register access (for the 909) is back!
+ * 20000517 -sralston
+ *  Let's trying going back to default mmap register access...
+ */
+
+static inline u32 CHIPREG_READ32(volatile u32 *a)
+{
+	if (PortIo)
+		return inl((unsigned long)a);
+	else
+		return readl(a);
+}
+
+static inline void CHIPREG_WRITE32(volatile u32 *a, u32 v)
+{
+	if (PortIo)
+		outl(v, (unsigned long)a);
+	else
+		writel(v, a);
+}
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
+ *	@irq: irq number (not used)
+ *	@bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
+ *	@r: pt_regs pointer (not used)
+ *
+ *	This routine is registered via the request_irq() kernel API call,
+ *	and handles all interrupts generated from a specific MPT adapter
+ *	(also referred to as a IO Controller or IOC).
+ *	This routine must clear the interrupt from the adapter and does
+ *	so by reading the reply FIFO.  Multiple replies may be processed
+ *	per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
+ *	which is currently set to 32 in mptbase.h.
+ *
+ *	This routine handles register-level access of the adapter but
+ *	dispatches (calls) a protocol-specific callback routine to handle
+ *	the protocol-specific details of the MPT request completion.
+ */
+static void
+mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
+{
+	MPT_ADAPTER	*ioc;
+	MPT_FRAME_HDR	*mf;
+	MPT_FRAME_HDR	*mr;
+	u32		 pa;
+	u32		*m;
+	int		 req_idx;
+	int		 cb_idx;
+	int		 type;
+	int		 freeme;
+	int		 count = 0;
+
+	ioc = bus_id;
+
+	/*
+	 *  Drain the reply FIFO!
+	 *
+	 * NOTES: I've seen up to 10 replies processed in this loop, so far...
+	 * Update: I've seen up to 9182 replies processed in this loop! ??
+	 * Update: Limit ourselves to processing max of N replies
+	 *	(bottom of loop).
+	 */
+	while (1) {
+
+		if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
+			return;
+
+		cb_idx = 0;
+		freeme = 0;
+
+		/*
+		 *  Check for non-TURBO reply!
+		 */
+		if (pa & MPI_ADDRESS_REPLY_A_BIT) {
+			dma_addr_t reply_dma_addr;
+			u16 ioc_stat;
+
+			/* non-TURBO reply!  Hmmm, something may be up...
+			 *  Newest turbo reply mechanism; get address
+			 *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
+			 */
+			reply_dma_addr = (pa = (pa << 1));
+
+			/* Map DMA address of reply header to cpu address. */
+			m = (u32 *) ((u8 *)ioc->reply_frames +
+					(reply_dma_addr - ioc->reply_frames_dma));
+
+			mr = (MPT_FRAME_HDR *) m;
+			req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
+			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+
+			dprintk((KERN_INFO MYNAM ": %s: Got non-TURBO reply=%p\n",
+					ioc->name, mr));
+			DBG_DUMP_REPLY_FRAME(mr)
+
+			/* NEW!  20010301 -sralston
+			 *  Check/log IOC log info
+			 */
+			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+	 		if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+				u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+				if ((int)ioc->chip_type <= (int)FC929)
+					mpt_fc_log_info(ioc, log_info);
+				else
+					mpt_sp_log_info(ioc, log_info);
+			}
+		} else {
+			/*
+			 *  Process turbo (context) reply...
+			 */
+			dirqprintk((KERN_INFO MYNAM ": %s: Got TURBO reply(=%08x)\n", ioc->name, pa));
+			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
+			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
+				cb_idx = mpt_stm_index;
+				mf = NULL;
+				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+			} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
+				cb_idx = mpt_lan_index;
+				/*
+				 * BUG FIX!  20001218 -sralston
+				 *  Blind set of mf to NULL here was fatal
+				 *  after lan_reply says "freeme"
+				 *  Fix sort of combined with an optimization here;
+				 *  added explicit check for case where lan_reply
+				 *  was just returning 1 and doing nothing else.
+				 *  For this case skip the callback, but set up
+				 *  proper mf value first here:-)
+				 */
+				if ((pa & 0x58000000) == 0x58000000) {
+					req_idx = pa & 0x0000FFFF;
+					mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+					freeme = 1;
+					/*
+					 *  IMPORTANT!  Invalidate the callback!
+					 */
+					cb_idx = 0;
+				} else {
+					mf = NULL;
+				}
+				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+			} else {
+				req_idx = pa & 0x0000FFFF;
+				cb_idx = (pa & 0x00FF0000) >> 16;
+				mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+				mr = NULL;
+			}
+			pa = 0;					/* No reply flush! */
+		}
+
+		/*  Check for (valid) IO callback!  */
+		if (cb_idx) {
+			/*  Do the callback!  */
+			freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
+		}
+
+		if (pa) {
+			/*  Flush (non-TURBO) reply with a WRITE!  */
+			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+		}
+
+		if (freeme) {
+			unsigned long flags;
+
+			/*  Put Request back on FreeQ!  */
+			spin_lock_irqsave(&ioc->FreeQlock, flags);
+			Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+		}
+
+		count++;
+		dirqprintk((KERN_INFO MYNAM ": %s: ISR processed frame #%d\n", ioc->name, count));
+		mb();
+
+		if (count >= MPT_MAX_REPLIES_PER_ISR) {
+			dirqprintk((KERN_INFO MYNAM ": %s: ISR processed %d replies.",
+					ioc->name, count));
+			dirqprintk((" Giving this ISR a break!\n"));
+			return;
+		}
+
+	}	/* drain reply FIFO */
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_base_reply - MPT base driver's callback routine; all base driver
+ *	"internal" request/reply processing is routed here.
+ *	Currently used for EventNotification and EventAck handling.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@mf: Pointer to original MPT request frame
+ *	@reply: Pointer to MPT reply frame (NULL if TurboReply)
+ *
+ *	Returns 1 indicating original alloc'd request frame ptr
+ *	should be freed, or 0 if it shouldn't.
+ */
+static int
+mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
+{
+	int freereq = 1;
+	u8 func;
+
+	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply() called\n", ioc->name));
+
+	if ((mf == NULL) ||
+	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
+		printk(KERN_ERR MYNAM ": %s: ERROR - NULL or BAD request frame ptr! (=%p)\n",
+				ioc->name, mf);
+		return 1;
+	}
+
+	if (reply == NULL) {
+		dprintk((KERN_ERR MYNAM ": %s: ERROR - Unexpected NULL Event (turbo?) reply!\n",
+				ioc->name));
+		return 1;
+	}
+
+	if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
+		dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
+		DBG_DUMP_REQUEST_FRAME_HDR(mf)
+	}
+
+	func = reply->u.hdr.Function;
+	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, Function=%02Xh\n",
+			ioc->name, func));
+
+	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
+		EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
+		int evHandlers = 0;
+		int results;
+
+		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
+		if (results != evHandlers) {
+			/* CHECKME! Any special handling needed here? */
+			dprintk((KERN_WARNING MYNAM ": %s: Hmmm... Called %d event handlers, sum results = %d\n",
+					ioc->name, evHandlers, results));
+		}
+
+		/*
+		 *  Hmmm...  It seems that EventNotificationReply is an exception
+		 *  to the rule of one reply per request.
+		 */
+		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+			freereq = 0;
+#ifdef CONFIG_PROC_FS
+//		LogEvent(ioc, pEvReply);
+#endif
+	} else if (func == MPI_FUNCTION_EVENT_ACK) {
+		dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, EventAck reply received\n",
+				ioc->name));
+	} else {
+		printk(KERN_ERR MYNAM ": %s: ERROR - Unexpected msg function (=%02Xh) reply received!\n",
+				ioc->name, func);
+	}
+
+	/*
+	 *  Conditionally tell caller to free the original
+	 *  EventNotification/EventAck/unexpected request frame!
+	 */
+	return freereq;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_register - Register protocol-specific main callback handler.
+ *	@cbfunc: callback function pointer
+ *	@dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
+ *
+ *	This routine is called by a protocol-specific driver (SCSI host,
+ *	LAN, SCSI target) to register it's reply callback routine.  Each
+ *	protocol-specific driver must do this before it will be able to
+ *	use any IOC resources, such as obtaining request frames.
+ *
+ *	NOTES: The SCSI protocol driver currently calls this routine twice
+ *	in order to register separate callbacks; one for "normal" SCSI IO
+ *	and another for MptScsiTaskMgmt requests.
+ *
+ *	Returns a positive integer valued "handle" in the
+ *	range (and S.O.D. order) {7,6,...,1} if successful.
+ *	Any non-positive return value (including zero!) should be considered
+ *	an error by the caller.
+ */
+int
+mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
+{
+	int r = -1;
+	int i;
+
+#ifndef MODULE
+	/*
+	 *  Handle possibility of the mptscsih_detect() routine getting
+	 *  called *before* fusion_init!
+	 */
+	if (!FusionInitCalled) {
+		dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
+		/*
+		 *  NOTE! We'll get recursion here, as fusion_init()
+		 *  calls mpt_register()!
+		 */
+		fusion_init();
+		FusionInitCalled++;
+	}
+#endif
+
+	/*
+	 *  Search for empty callback slot in this order: {7,6,...,1}
+	 *  (slot/handle 0 is reserved!)
+	 */
+	for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
+		if (MptCallbacks[i] == NULL) {
+			MptCallbacks[i] = cbfunc;
+			MptDriverClass[i] = dclass;
+			MptEvHandlers[i] = NULL;
+			r = i;
+			if (cbfunc != mpt_base_reply) {
+				MOD_INC_USE_COUNT;
+			}
+			break;
+		}
+	}
+
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_deregister - Deregister a protocol drivers resources.
+ *	@cb_idx: previously registered callback handle
+ *
+ *	Each protocol-specific driver should call this routine when it's
+ *	module is unloaded.
+ */
+void
+mpt_deregister(int cb_idx)
+{
+	if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
+		MptCallbacks[cb_idx] = NULL;
+		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
+		MptEvHandlers[cb_idx] = NULL;
+		if (cb_idx != mpt_base_index) {
+			MOD_DEC_USE_COUNT;
+		}
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_event_register - Register protocol-specific event callback
+ *	handler.
+ *	@cb_idx: previously registered (via mpt_register) callback handle
+ *	@ev_cbfunc: callback function
+ *
+ *	This routine can be called by one or more protocol-specific drivers
+ *	if/when they choose to be notified of MPT events.
+ *
+ *	Returns 0 for success.
+ */
+int
+mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
+{
+	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+		return -1;
+
+	MptEvHandlers[cb_idx] = ev_cbfunc;
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_event_deregister - Deregister protocol-specific event callback
+ *	handler.
+ *	@cb_idx: previously registered callback handle
+ *
+ *	Each protocol-specific driver should call this routine
+ *	when it does not (or can no longer) handle events,
+ *	or when it's module is unloaded.
+ */
+void
+mpt_event_deregister(int cb_idx)
+{
+	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+		return;
+
+	MptEvHandlers[cb_idx] = NULL;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
+ *	allocated per MPT adapter.
+ *	@handle: Handle of registered MPT protocol driver
+ *	@iocid: IOC unique identifier (integer)
+ *
+ *	Returns pointer to a MPT request frame or %NULL if none are available.
+ */
+MPT_FRAME_HDR*
+mpt_get_msg_frame(int handle, int iocid)
+{
+	MPT_FRAME_HDR *mf = NULL;
+	MPT_ADAPTER *iocp;
+	unsigned long flags;
+
+	/* validate handle and ioc identifier */
+	iocp = mpt_adapters[iocid];
+	spin_lock_irqsave(&iocp->FreeQlock, flags);
+	if (! Q_IS_EMPTY(&iocp->FreeQ)) {
+		int req_offset;
+
+		mf = iocp->FreeQ.head;
+		Q_DEL_ITEM(&mf->u.frame.linkage);
+		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */
+		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+								/* u16! */
+		mf->u.frame.hwhdr.msgctxu.fld.req_idx =
+				cpu_to_le16(req_offset / iocp->req_sz);
+		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+	}
+	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
+			iocp->name, handle, iocid, mf));
+	return mf;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_put_msg_frame - Send a protocol specific MPT request frame
+ *	to a IOC.
+ *	@handle: Handle of registered MPT protocol driver
+ *	@iocid: IOC unique identifier (integer)
+ *	@mf: Pointer to MPT request frame
+ *
+ *	This routine posts a MPT request frame to the request post FIFO of a
+ *	specific MPT adapter.
+ */
+void
+mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+{
+	MPT_ADAPTER *iocp;
+
+	iocp = mpt_adapters[iocid];
+	if (iocp != NULL) {
+		dma_addr_t mf_dma_addr;
+		int req_offset;
+
+		/* ensure values are reset properly! */
+		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */
+		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+									/* u16! */
+		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
+		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+
+#ifdef MPT_DEBUG_MSG_FRAME
+		{
+			u32	*m = mf->u.frame.hwhdr.__hdr;
+			int	 i, n;
+
+			printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
+					iocp->name, m);
+			n = iocp->req_sz/4 - 1;
+			while (m[n] == 0)
+				n--;
+			for (i=0; i<=n; i++) {
+				if (i && ((i%8)==0))
+					printk("\n" KERN_INFO " ");
+				printk(" %08x", le32_to_cpu(m[i]));
+			}
+			printk("\n");
+		}
+#endif
+
+		mf_dma_addr = iocp->req_frames_dma + req_offset;
+		CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_free_msg_frame - Place MPT request frame back on FreeQ.
+ *	@handle: Handle of registered MPT protocol driver
+ *	@iocid: IOC unique identifier (integer)
+ *	@mf: Pointer to MPT request frame
+ *
+ *	This routine places a MPT request frame back on the MPT adapter's
+ *	FreeQ.
+ */
+void
+mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
+{
+	MPT_ADAPTER *iocp;
+	unsigned long flags;
+
+	iocp = mpt_adapters[iocid];
+	if (iocp != NULL) {
+		/*  Put Request back on FreeQ!  */
+		spin_lock_irqsave(&iocp->FreeQlock, flags);
+		Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+		spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_send_handshake_request - Send MPT request via doorbell
+ *	handshake method.
+ *	@handle: Handle of registered MPT protocol driver
+ *	@iocid: IOC unique identifier (integer)
+ *	@reqBytes: Size of the request in bytes
+ *	@req: Pointer to MPT request frame
+ *
+ *	This routine is used exclusively by mptscsih to send MptScsiTaskMgmt
+ *	requests since they are required to be sent via doorbell handshake.
+ *
+ *	NOTE: It is the callers responsibility to byte-swap fields in the
+ *	request which are greater than 1 byte in size.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+int
+mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req)
+{
+	MPT_ADAPTER	*iocp;
+	int		 r = 0;
+
+	iocp = mpt_adapters[iocid];
+	if (iocp != NULL) {
+		u8 *req_as_bytes;
+		int i;
+
+		/*
+		 *  Emulate what mpt_put_msg_frame() does /wrt to sanity
+		 *  setting cb_idx/req_idx.  But ONLY if this request
+		 *  is in proper (pre-alloc'd) request buffer range...
+		 */
+		i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
+		if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) {
+			MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
+			mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(i);
+			mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+		}
+
+		/*  Make sure there are no doorbells  */
+		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+
+		CHIPREG_WRITE32(&iocp->chip->Doorbell,
+				((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
+				 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+
+		/*  Wait for IOC doorbell int  */
+		if ((i = WaitForDoorbellInt(iocp)) < 0) {
+			/* FIXME! Recovery action(s)? */
+			/*i = unresponsive_ioc(i);*/
+			return i;
+		}
+
+		dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
+				iocp->name, i));
+
+		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+
+		if ((r = WaitForDoorbellAck(iocp)) < 0)
+			return -2;
+
+		/*  Send request via doorbell handshake  */
+		req_as_bytes = (u8 *) req;
+		for (i = 0; i < reqBytes/4; i++) {
+			u32 word;
+
+			word = ((req_as_bytes[(i*4) + 0] <<  0) |
+				(req_as_bytes[(i*4) + 1] <<  8) |
+				(req_as_bytes[(i*4) + 2] << 16) |
+				(req_as_bytes[(i*4) + 3] << 24));
+			CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
+			if ((r = WaitForDoorbellAck(iocp)) < 0) {
+				r = -3;
+				break;
+			}
+		}
+
+		/*  Make sure there are no doorbells  */
+		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+
+	}
+
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_adapter_find_first - Find first MPT adapter pointer.
+ *
+ *	Returns first MPT adapter pointer or %NULL if no MPT adapters
+ *	are present.
+ */
+MPT_ADAPTER *
+mpt_adapter_find_first(void)
+{
+	MPT_ADAPTER *this = NULL;
+
+	if (! Q_IS_EMPTY(&MptAdapters))
+		this = MptAdapters.head;
+
+	return this;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * 	mpt_adapter_find_next - Find next MPT adapter pointer.
+ * 	@prev: Pointer to previous MPT adapter
+ *
+ *	Returns next MPT adapter pointer or %NULL if there are no more.
+ */
+MPT_ADAPTER *
+mpt_adapter_find_next(MPT_ADAPTER *prev)
+{
+	MPT_ADAPTER *next = NULL;
+
+	if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
+		next = prev->forw;
+
+	return next;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_pci_scan - Scan PCI devices for MPT adapters.
+ *
+ *	Returns count of MPT adapters found, keying off of PCI vendor and
+ *	device_id's.
+ */
+int __init
+mpt_pci_scan(void)
+{
+	struct pci_dev *pdev;
+	struct pci_dev *pdev2;
+	int found = 0;
+	int count = 0;
+	int r;
+
+	dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
+
+	/*
+	 *  NOTE: The 929 (I believe) will appear as 2 separate PCI devices,
+	 *  one for each channel.
+	 */
+	pci_for_each_dev(pdev) {
+		pdev2 = NULL;
+		if (pdev->vendor != 0x1000)
+			continue;
+
+		if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&
+		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&
+#if 0
+		    /* FIXME! FC919 */
+		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&
+		    /* FIXME! C103x family */
+		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
+		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) &&
+		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&
+#endif
+		    1) {
+			dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));
+			continue;
+		}
+
+		/* GRRRRR
+		 * 929 dual function devices may be presented in Func 1,0 order,
+		 * but we'd really really rather have them in Func 0,1 order.
+		 * Do some kind of look ahead here...
+		 */
+		if (pdev->devfn & 1) {
+			pdev2 = pci_peek_next_dev(pdev);
+			if (pdev2 && (pdev2->vendor == 0x1000) &&
+			    (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
+			    (pdev2->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
+			    (pdev2->bus->number == pdev->bus->number) &&
+			    !(pdev2->devfn & 1)) {
+				dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
+			 		pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
+				found++;
+				if ((r = mpt_adapter_install(pdev2)) == 0)
+					count++;
+			} else {
+				pdev2 = NULL;
+			}
+		}
+
+		dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
+			 pdev->bus->number, pdev->devfn, pdev->class, pdev->device));
+		found++;
+		if ((r = mpt_adapter_install(pdev)) == 0)
+			count++;
+
+		if (pdev2)
+			pdev = pdev2;
+	}
+
+	printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n",
+		 found, (found==1) ? "" : "s", count);
+
+	if (count == 0)
+		return -ENODEV;
+
+#ifdef CONFIG_PROC_FS
+	if (procmpt_create() != 0)
+		printk(KERN_WARNING MYNAM ": WARNING! - %s creation failed!\n",
+				MPT_PROCFS_MPTBASEDIR);
+#endif
+
+	return count;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_verify_adapter - Given a unique IOC identifier, set pointer to
+ *	the associated MPT adapter structure.
+ *	@iocid: IOC unique identifier (integer)
+ *	@iocpp: Pointer to pointer to IOC adapter
+ *
+ *	Returns iocid and sets iocpp.
+ */
+int
+mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
+{
+	MPT_ADAPTER *p;
+
+	*iocpp = NULL;
+	if (iocid >= MPT_MAX_ADAPTERS)
+		return -1;
+
+	p = mpt_adapters[iocid];
+	if (p == NULL)
+		return -1;
+
+	*iocpp = p;
+	return iocid;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_adapter_install - Install a PCI intelligent MPT adapter.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	This routine performs all the steps necessary to bring the IOC of
+ *	a MPT adapter to a OPERATIONAL state.  This includes registering
+ *	memory regions, registering the interrupt, and allocating request
+ *	and reply memory pools.
+ *
+ *	This routine also pre-fetches the LAN MAC address of a Fibre Channel
+ *	MPT adapter.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ *	TODO: Add support for polled controllers
+ */
+static int __init
+mpt_adapter_install(struct pci_dev *pdev)
+{
+	MPT_ADAPTER	*ioc;
+	char		*myname;
+	u8		*mem;
+	unsigned long	 mem_phys;
+	unsigned long	 port;
+	u32		 msize;
+	u32		 psize;
+	u32		 ioc_state;
+	int		 i;
+	int		 r = -ENODEV;
+	int 		 cntdn;
+	int		 len;
+	int		 statefault = 0;
+
+	ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL);
+	if (ioc == NULL) {
+		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
+		return -ENOMEM;
+	}
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->req_sz = MPT_REQ_SIZE;			/* avoid div by zero! */
+	ioc->alloc_total = sizeof(MPT_ADAPTER);
+
+	ioc->pcidev = pdev;
+
+	/*  Find lookup slot.  GRRRR...  */
+	for (i=0; i < MPT_MAX_ADAPTERS; i++) {
+		if (mpt_adapters[i] == NULL) {
+			ioc->id = i;		/* Assign adapter unique id (lookup) */
+			break;
+		}
+	}
+	if (i == MPT_MAX_ADAPTERS) {
+		printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", i);
+		kfree(ioc);
+		return -ENFILE;
+	}
+
+	mem_phys = msize = 0;
+	port = psize = 0;
+	for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
+		if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) {
+			/*  Get I/O space!  */
+			port = pdev->PCI_BASEADDR_START(i);
+			psize = PCI_BASEADDR_SIZE(pdev,i);
+		} else {
+			/*  Get memmap  */
+			mem_phys = pdev->PCI_BASEADDR_START(i);
+			msize = PCI_BASEADDR_SIZE(pdev,i);
+			break;
+		}
+	}
+	ioc->mem_size = msize;
+
+	if (i == DEVICE_COUNT_RESOURCE) {
+		printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
+		kfree(ioc);
+		return -EINVAL;
+	}
+
+	dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
+	dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
+	dprintk((KERN_INFO MYNAM ": Using %s register access method\n", PortIo ? "PortIo" : "MemMap"));
+
+	mem = NULL;
+	if (! PortIo) {
+		/*  Get logical ptr for PciMem0 space  */
+		/*mem = ioremap(mem_phys, msize);*/
+		mem = ioremap(mem_phys, 0x100);
+		if (mem == NULL) {
+			printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
+			kfree(ioc);
+			return -EINVAL;
+		}
+		ioc->memmap = mem;
+	}
+	dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+
+	if (PortIo) {
+		u8 *pmem = (u8*)port;
+		ioc->mem_phys = port;
+		ioc->chip = (SYSIF_REGS*)pmem;
+	} else {
+		ioc->mem_phys = mem_phys;
+		ioc->chip = (SYSIF_REGS*)mem;
+	}
+
+	ioc->chip_type = FCUNK;
+	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
+		ioc->chip_type = FC909;
+		ioc->prod_name = "LSIFC909";
+	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
+		ioc->chip_type = FC929;
+		ioc->prod_name = "LSIFC929";
+	}
+#if 0
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
+		ioc->chip_type = C1030;
+		ioc->prod_name = "LSIFC919";
+	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) {
+		ioc->chip_type = C1030;
+		ioc->prod_name = "LSI53C1030";
+	}
+#endif
+
+	myname = "iocN";
+	len = strlen(myname);
+	memcpy(ioc->name, myname, len+1);
+	ioc->name[len-1] = '0' + ioc->id;
+
+	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
+	spin_lock_init(&ioc->FreeQlock);
+
+	/*  Disable all!  */
+	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	ioc->active = 0;
+
+	ioc->pci_irq = -1;
+	if (pdev->irq) {
+		r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
+
+		if (r < 0) {
+			printk(KERN_ERR MYNAM ": %s: ERROR - Unable to allocate interrupt %d!\n",
+					ioc->name, pdev->irq);
+			iounmap(mem);
+			kfree(ioc);
+			return -EBUSY;
+		}
+
+		ioc->pci_irq = pdev->irq;
+
+		pci_set_master(pdev);			/* ?? */
+
+		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
+	}
+
+	/*  tack onto tail of our MPT adapter list  */
+	Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
+
+	/* Set lookup ptr. */
+	mpt_adapters[ioc->id] = ioc;
+
+	/* NEW!  20010220 -sralston
+	 * Check for "929 bound ports" to reduce redundant resets.
+	 */
+	if (ioc->chip_type == FC929)
+		mpt_detect_929_bound_ports(ioc, pdev);
+
+	/*  Get current [raw] IOC state  */
+	ioc_state = GetIocState(ioc, 0);
+	dhsprintk((KERN_INFO MYNAM ": %s initial [raw] state=%08x\n", ioc->name, ioc_state));
+
+	/*
+	 *  Check to see if IOC got left/stuck in doorbell handshake
+	 *  grip of death.  If so, hard reset the IOC.
+	 */
+	if (ioc_state & MPI_DOORBELL_ACTIVE) {
+		statefault = 1;
+		printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n",
+				ioc->name);
+	}
+
+	/*
+	 *  Check to see if IOC is in FAULT state.
+	 *  If so, hard reset the IOC.
+	 */
+	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
+		statefault = 2;
+		printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n",
+				ioc->name);
+		printk(KERN_WARNING "           FAULT code = %04xh\n",
+				ioc_state & MPI_DOORBELL_DATA_MASK);
+	}
+
+	if (HardReset || statefault) {
+		if ((r = KickStart(ioc)) != 0) {
+			r = -ENODEV;
+			goto ioc_up_fail;
+		}
+	}
+
+	/*
+	 *  Loop here waiting for IOC to come READY.
+	 */
+	i = 0;
+	cntdn = HZ * 10;
+	while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
+		if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
+			/*
+			 *  BIOS or previous driver load left IOC in OP state.
+			 *  Reset messaging FIFOs.
+			 */
+			dprintk((KERN_WARNING MYNAM ": %s: Sending IOC msg unit reset!\n", ioc->name));
+			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) {
+				printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name);
+				r = -ENODEV;
+				goto ioc_up_fail;
+			}
+		} else if (ioc_state == MPI_IOC_STATE_RESET) {
+			/*
+			 *  Something is wrong.  Try to get IOC back
+			 *  to a known state.
+			 */
+			dprintk((KERN_WARNING MYNAM ": %s: Sending IO unit reset!\n", ioc->name));
+			if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) {
+				printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name);
+				r = -ENODEV;
+				goto ioc_up_fail;
+			}
+		}
+
+		i++; cntdn--;
+		if (!cntdn) {
+			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
+					ioc->name, (i+5)/HZ);
+			r = -ETIME;
+			goto ioc_up_fail;
+		}
+
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	if (statefault) {
+		printk(KERN_WARNING MYNAM ": %s: Whew!  Recovered from %s\n",
+				ioc->name, statefault==1 ? "stuck handshake" : "IOC FAULT");
+	}
+
+	/*  Enable! (reply interrupt)  */
+	CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+	ioc->active = 1;
+
+	/*  Get IOC facts! (first time, ioc->facts0 and ioc->pfacts0)  */
+	if ((r = GetIocFacts(ioc)) != 0)
+		goto ioc_up_fail;
+
+	/* Does IocFacts.EventState need any looking at / attention here? */
+
+	if ((r = SendIocInit(ioc)) != 0)
+		goto ioc_up_fail;
+
+	/*
+	 *  Prime reply & request queues!
+	 *  (mucho alloc's)
+	 */
+	if ((r = PrimeIocFifos(ioc)) != 0)
+		goto ioc_up_fail;
+
+	/*  Get IOC facts again! (2nd time, ioc->factsN and ioc->pfactsN)  */
+	if ((r = GetIocFacts(ioc)) != 0)
+		goto ioc_up_fail;
+
+	/* Does IocFacts.EventState need any looking at / attention here? */
+
+	MptDisplayIocCapabilities(ioc);
+
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+		/*
+		 *  Pre-fetch the ports LAN MAC address!
+		 *  (LANPage1_t stuff)
+		 */
+		(void) GetLanConfigPages(ioc);
+#ifdef MPT_DEBUG
+		{
+			u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
+			dprintk((KERN_INFO MYNAM ": %s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+					ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
+		}
+#endif
+	}
+
+	/* NEW!  20010120 -sralston
+	 *  Enable MPT base driver management of EventNotification
+	 *  and EventAck handling.
+	 */
+	(void) SendEventNotification(ioc, 1);	/* 1=Enable EventNotification */
+
+	return 0;
+
+ioc_up_fail:
+	//Q_DEL_ITEM(ioc);
+	//mpt_adapter_dispose(ioc);
+	mpt_adapter_disable(ioc);
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_detect_929_bound_ports - Search for PCI bus/dev_function
+ *	which matches PCI bus/dev_function (+/-1) for newly discovered 929.
+ *	@ioc: Pointer to MPT adapter structure
+ *	@pdev: Pointer to (struct pci_dev) structure
+ *
+ *	If match on PCI dev_function +/-1 is found, bind the two MPT adapters
+ *	using alt_ioc pointer fields in their %MPT_ADAPTER structures.
+ */
+static void
+mpt_detect_929_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
+	unsigned int match_lo, match_hi;
+
+	match_lo = pdev->devfn-1;
+	match_hi = pdev->devfn+1;
+	dprintk((KERN_INFO MYNAM ": %s: PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
+			ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
+
+	while (ioc_srch != NULL) {
+		struct pci_dev *_pcidev = ioc_srch->pcidev;
+
+		if ( (_pcidev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
+		     (_pcidev->bus->number == pdev->bus->number) &&
+		     (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+			/* Paranoia checks */
+			if (ioc->alt_ioc != NULL) {
+				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
+						ioc->name, ioc->alt_ioc->name);
+				break;
+			} else if (ioc_srch->alt_ioc != NULL) {
+				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
+						ioc_srch->name, ioc_srch->alt_ioc->name);
+				break;
+			}
+			dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
+					ioc->name, ioc_srch->name));
+			ioc_srch->alt_ioc = ioc;
+			ioc->alt_ioc = ioc_srch;
+			ioc->sod_reset = ioc->alt_ioc->sod_reset;
+			ioc->last_kickstart = ioc->alt_ioc->last_kickstart;
+			break;
+		}
+		ioc_srch = mpt_adapter_find_next(ioc_srch);
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_adapter_disable - Disable misbehaving MPT adapter.
+ *	@this: Pointer to MPT adapter structure
+ */
+static void
+mpt_adapter_disable(MPT_ADAPTER *this)
+{
+	if (this != NULL) {
+		int sz;
+
+		/* Disable adapter interrupts! */
+		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
+		/* Clear any lingering interrupt */
+		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
+		this->active = 0;
+
+		if (this->reply_alloc != NULL) {
+			sz = (this->reply_sz * this->reply_depth) + 128;
+			pci_free_consistent(this->pcidev, sz,
+					this->reply_alloc, this->reply_alloc_dma);
+			this->reply_frames = NULL;
+			this->reply_alloc = NULL;
+			this->alloc_total -= sz;
+		}
+
+		if (this->req_alloc != NULL) {
+			sz = (this->req_sz * this->req_depth) + 128;
+			/*
+			 *  Rounding UP to nearest 4-kB boundary here...
+			 */
+			sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+			pci_free_consistent(this->pcidev, sz,
+					this->req_alloc, this->req_alloc_dma);
+			this->req_frames = NULL;
+			this->req_alloc = NULL;
+			this->alloc_total -= sz;
+		}
+
+		if (this->sense_buf_pool != NULL) {
+			sz = (this->req_depth * 256);
+			pci_free_consistent(this->pcidev, sz,
+					this->sense_buf_pool, this->sense_buf_pool_dma);
+			this->sense_buf_pool = NULL;
+			this->alloc_total -= sz;
+		}
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_adapter_dispose - Free all resources associated with a MPT
+ *	adapter.
+ *	@this: Pointer to MPT adapter structure
+ *
+ *	This routine unregisters h/w resources and frees all alloc'd memory
+ *	associated with a MPT adapter structure.
+ */
+static void
+mpt_adapter_dispose(MPT_ADAPTER *this)
+{
+	if (this != NULL) {
+		int sz_first, sz_last;
+
+		sz_first = this->alloc_total;
+
+		mpt_adapter_disable(this);
+
+		if (this->pci_irq != -1) {
+			free_irq(this->pci_irq, this);
+			this->pci_irq = -1;
+		}
+
+		if (this->memmap != NULL)
+			iounmap((u8 *) this->memmap);
+
+#if defined(CONFIG_MTRR) && 0
+		if (this->mtrr_reg > 0) {
+			mtrr_del(this->mtrr_reg, 0, 0);
+			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
+		}
+#endif
+
+		/*  Zap the adapter lookup ptr!  */
+		mpt_adapters[this->id] = NULL;
+
+		sz_last = this->alloc_total;
+		dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+				this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
+		kfree(this);
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	MptDisplayIocCapabilities - Disply IOC's capacilities.
+ *	@ioc: Pointer to MPT adapter structure
+ */
+static void
+MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
+{
+	int i = 0;
+
+	printk(KERN_INFO "%s: ", ioc->name);
+	if (ioc->prod_name && strlen(ioc->prod_name) > 3)
+		printk("%s: ", ioc->prod_name+3);
+	printk("Capabilities={");
+
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
+		printk("Initiator");
+		i++;
+	}
+
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
+		printk("%sTarget", i ? "," : "");
+		i++;
+	}
+
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+		printk("%sLAN", i ? "," : "");
+		i++;
+	}
+
+#if 0
+	/*
+	 *  This would probably evoke more questions than it's worth
+	 */
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
+		printk("%sLogBusAddr", i ? "," : "");
+		i++;
+	}
+#endif
+
+	printk("}\n");
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetIocState - Get the current state of a MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@cooked: Request raw or cooked IOC state
+ *
+ *	Returns all IOC Doorbell register bits if cooked==0, else just the
+ *	Doorbell bits in MPI_IOC_STATE_MASK.
+ */
+static u32
+GetIocState(MPT_ADAPTER *ioc, int cooked)
+{
+	u32 s, sc;
+
+	/*  Get!  */
+	s = CHIPREG_READ32(&ioc->chip->Doorbell);
+	dprintk((KERN_INFO MYNAM ": %s: raw state = %08x\n", ioc->name, s));
+	sc = s & MPI_IOC_STATE_MASK;
+
+	/*  Save!  */
+	ioc->last_state = sc;
+
+	return cooked ? sc : s;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetIocFacts - Send IOCFacts request to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+GetIocFacts(MPT_ADAPTER *ioc)
+{
+	IOCFacts_t		 get_facts;
+	IOCFactsReply_t		*facts;
+	int			 r;
+	int			 req_sz;
+	int			 reply_sz;
+	u32			 status;
+
+	/*  IOC *must* NOT be in RESET state!  */
+	if (ioc->last_state == MPI_IOC_STATE_RESET) {
+		printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
+				ioc->name,
+				ioc->last_state );
+		return -44;
+	}
+
+	facts = &ioc->facts0;
+	/*  Nth (2,3,...) time thru? (been here, done that?)  */
+	if (ioc->facts0.Function == MPI_FUNCTION_IOC_FACTS) {
+		facts = &ioc->factsN;
+	}
+
+	/*  Destination (reply area)...  */
+	reply_sz = sizeof(*facts);
+	memset(facts, 0, reply_sz);
+
+	/*  Request area (get_facts on the stack right now!)  */
+	req_sz = sizeof(get_facts);
+	memset(&get_facts, 0, req_sz);
+
+	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
+	/*  Assert: All other get_facts fields are zero!  */
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending IocFacts%s request\n",
+			ioc->name, facts == &ioc->facts0 ? "0" : "N" ));
+
+	/* No non-zero fields in the get_facts request are greater than
+	 * 1 byte in size, so we can just fire it off as is.
+	 */
+	r = HandShakeReqAndReply(ioc,
+			req_sz, (u32*)&get_facts,
+			reply_sz, (u16*)facts);
+	if (r != 0)
+		return r;
+
+	/*
+	 *  Now byte swap the necessary fields before any further
+	 *  inspection of reply contents.
+	 *
+	 *  But need to do some sanity checks on MsgLength (byte) field
+	 *  to make sure we don't zero IOC's req_sz!
+	 */
+	/* Did we get a valid reply? */
+	if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
+		facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
+		facts->MsgContext = le32_to_cpu(facts->MsgContext);
+		facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
+		facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
+		status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
+		/* CHECKME! IOCStatus, IOCLogInfo */
+
+		facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
+		facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
+		facts->FWVersion = le16_to_cpu(facts->FWVersion);
+		facts->ProductID = le16_to_cpu(facts->ProductID);
+		facts->CurrentHostMfaHighAddr =
+				le32_to_cpu(facts->CurrentHostMfaHighAddr);
+		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
+		facts->CurrentSenseBufferHighAddr =
+				le32_to_cpu(facts->CurrentSenseBufferHighAddr);
+		facts->CurReplyFrameSize =
+				le16_to_cpu(facts->CurReplyFrameSize);
+
+		/*
+		 *  Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
+		 *  Older MPI-1.00.xx struct had 13 dwords, and enlarged
+		 *  to 14 in MPI-1.01.0x.
+		 */
+		if (facts->MsgLength >= sizeof(IOCFactsReply_t)/sizeof(u32) && facts->MsgVersion > 0x0100) {
+			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
+			facts->DataImageSize = le32_to_cpu(facts->DataImageSize);
+		}
+
+		if (facts->RequestFrameSize) {
+			/*
+			 *  Set values for this IOC's REQUEST queue size & depth...
+			 */
+			ioc->req_sz = MIN(MPT_REQ_SIZE, facts->RequestFrameSize * 4);
+
+			/*
+			 *  Set values for this IOC's REPLY queue size & depth...
+			 *
+			 * BUG? FIX?  20000516 -nromer & sralston 
+			 *  GRRR...  The following did not translate well from MPI v0.09:
+			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->ReplySize * 4);
+			 *  to 0.10:
+			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->BlockSize * 4);
+			 *  Was trying to minimally optimize to smallest possible reply size
+			 *  (and greatly reduce kmalloc size).  But LAN may need larger reply?
+			 *
+			 *  So for now, just set reply size to request size.  FIXME?
+			 */
+			ioc->reply_sz = ioc->req_sz;
+		} else {
+			/*  Something is wrong!  */
+			printk(KERN_ERR MYNAM ": %s: ERROR - IOC reported invalid 0 request size!\n",
+					ioc->name);
+			ioc->req_sz = MPT_REQ_SIZE;
+			ioc->reply_sz = MPT_REPLY_SIZE;
+			return -55;
+		}
+		ioc->req_depth = MIN(MPT_REQ_DEPTH, facts->GlobalCredits);
+		ioc->reply_depth = MIN(MPT_REPLY_DEPTH, facts->ReplyQueueDepth);
+
+		dprintk((KERN_INFO MYNAM ": %s: reply_sz=%3d, reply_depth=%4d\n",
+				ioc->name, ioc->reply_sz, ioc->reply_depth));
+		dprintk((KERN_INFO MYNAM ": %s: req_sz  =%3d, req_depth  =%4d\n",
+				ioc->name, ioc->req_sz, ioc->req_depth));
+
+		/*  Get port facts!  */
+		if ( (r = GetPortFacts(ioc)) != 0 )
+			return r;
+	} else {
+		printk(KERN_ERR MYNAM ": %s: ERROR - Invalid IOC facts reply!\n",
+				ioc->name);
+		return -66;
+	}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetPortFacts - Send PortFacts request to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+GetPortFacts(MPT_ADAPTER *ioc)
+{
+	PortFacts_t		 get_pfacts;
+	PortFactsReply_t	*pfacts;
+	int			 i;
+	int			 req_sz;
+	int			 reply_sz;
+
+	/*  IOC *must* NOT be in RESET state!  */
+	if (ioc->last_state == MPI_IOC_STATE_RESET) {
+		printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
+				ioc->name,
+				ioc->last_state );
+		return -4;
+	}
+
+	pfacts = &ioc->pfacts0;
+	/*  Nth (2,3,...) time thru? (been here, done that?)  */
+	if (ioc->pfacts0.Function == MPI_FUNCTION_PORT_FACTS) {
+		pfacts = &ioc->pfactsN;
+	}
+
+	/*  Destination (reply area)...  */
+	reply_sz = sizeof(*pfacts);
+	memset(pfacts, 0, reply_sz);
+
+	/*  Request area (get_pfacts on the stack right now!)  */
+	req_sz = sizeof(get_pfacts);
+	memset(&get_pfacts, 0, req_sz);
+
+	get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
+	/*  Assert: All other get_pfacts fields are zero!  */
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending PortFacts%s request\n",
+			ioc->name, pfacts == &ioc->pfacts0 ? "0" : "N" ));
+
+	/* No non-zero fields in the get_pfacts request are greater than
+	 * 1 byte in size, so we can just fire it off as is.
+	 */
+	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_pfacts,
+				reply_sz, (u16*)pfacts);
+	if (i != 0)
+		return i;
+
+	/* Did we get a valid reply? */
+
+	/* Now byte swap the necessary fields in the response. */
+	pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
+	pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
+	pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
+	pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
+	pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
+	pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
+	pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
+	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
+	pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	SendIocInit - Send IOCInit request to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+SendIocInit(MPT_ADAPTER *ioc)
+{
+	IOCInit_t		 ioc_init;
+	MPIDefaultReply_t	 init_reply;
+	u32			 state;
+	int			 r;
+	int			 count;
+	int			 cntdn;
+
+	memset(&ioc_init, 0, sizeof(ioc_init));
+	memset(&init_reply, 0, sizeof(init_reply));
+
+	ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
+/*	ioc_init.ChainOffset = 0;			*/
+	ioc_init.Function = MPI_FUNCTION_IOC_INIT;
+/*	ioc_init.Flags = 0;				*/
+
+	/*ioc_init.MaxDevices = 16;*/
+	ioc_init.MaxDevices = 255;
+/*	ioc_init.MaxBuses = 16;				*/
+	ioc_init.MaxBuses = 1;
+
+/*	ioc_init.MsgFlags = 0;				*/
+/*	ioc_init.MsgContext = cpu_to_le32(0x00000000);	*/
+	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
+	ioc_init.HostMfaHighAddr = cpu_to_le32(0);	/* Say we 32-bit! for now */
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init));
+
+	r = HandShakeReqAndReply(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
+			sizeof(MPIDefaultReply_t), (u16*)&init_reply);
+	if (r != 0)
+		return r;
+
+	/* No need to byte swap the multibyte fields in the reply
+	 * since we don't even look at it's contents.
+	 */
+
+	if ((r = SendPortEnable(ioc, 0)) != 0)
+		return r;
+
+	/* YIKES!  SUPER IMPORTANT!!!
+	 *  Poll IocState until _OPERATIONAL while IOC is doing
+	 *  LoopInit and TargetDiscovery!
+	 */
+	count = 0;
+	cntdn = HZ * 60;					/* chg'd from 30 to 60 seconds */
+	state = GetIocState(ioc, 1);
+	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+
+		if (!cntdn) {
+			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_OP state timeout(%d)!\n",
+					ioc->name, (count+5)/HZ);
+			return -9;
+		}
+
+		state = GetIocState(ioc, 1);
+		count++;
+	}
+	dhsprintk((KERN_INFO MYNAM ": %s: INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+			ioc->name, count));
+
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	SendPortEnable - Send PortEnable request to MPT adapter port.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@portnum: Port number to enable
+ *
+ *	Send PortEnable to bring IOC to OPERATIONAL state.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+SendPortEnable(MPT_ADAPTER *ioc, int portnum)
+{
+	PortEnable_t		 port_enable;
+	MPIDefaultReply_t	 reply_buf;
+	int	 i;
+	int	 req_sz;
+	int	 reply_sz;
+
+	/*  Destination...  */
+	reply_sz = sizeof(MPIDefaultReply_t);
+	memset(&reply_buf, 0, reply_sz);
+
+	req_sz = sizeof(PortEnable_t);
+	memset(&port_enable, 0, req_sz);
+
+	port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
+	port_enable.PortNumber = portnum;
+/*	port_enable.ChainOffset = 0;		*/
+/*	port_enable.MsgFlags = 0;		*/
+/*	port_enable.MsgContext = 0;		*/
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending Port(%d)Enable (req @ %p)\n",
+			ioc->name, portnum, &port_enable));
+
+	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&port_enable,
+			reply_sz, (u16*)&reply_buf);
+	if (i != 0)
+		return i;
+
+	/* We do not even look at the reply, so we need not
+	 * swap the multi-byte fields.
+	 */
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	KickStart - Perform hard reset of MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine places MPT adapter in diagnostic mode via the
+ *	WriteSequence register, and then performs a hard reset of adapter
+ *	via the Diagnostic register.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+KickStart(MPT_ADAPTER *ioc)
+{
+	int r;
+	u32 ioc_state;
+	int cnt = 0;
+
+	dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+
+	if (ioc->chip_type == FC909) {
+		r = mpt_fc9x9_reset(ioc);
+	} else if (ioc->chip_type == FC929) {
+		unsigned long delta;
+
+		delta = jiffies - ioc->last_kickstart;
+		dprintk((KERN_INFO MYNAM ": %s: 929 KickStart, last=%ld, delta = %ld\n",
+				ioc->name, ioc->last_kickstart, delta));
+		if ((ioc->sod_reset == 0) || (delta >= 10*HZ))
+			r = mpt_fc9x9_reset(ioc);
+		else {
+			dprintk((KERN_INFO MYNAM ": %s: Skipping KickStart (delta=%ld)!\n",
+					ioc->name, delta));
+			return 0;
+		}
+	/* TODO! Add FC919!
+	} else if (ioc->chip_type == FC919) {
+	 */
+	/* TODO! Add C1030!
+	} else if (ioc->chip_type == C1030) {
+	 */
+	} else {
+		printk(KERN_ERR MYNAM ": %s: ERROR - Bad chip_type (0x%x)\n",
+				ioc->name, ioc->chip_type);
+		return -5;
+	}
+
+	if (r != 0)
+		return -r;
+
+	dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset successful\n",
+			ioc->name));
+
+	for (cnt=0; cnt<HZ*20; cnt++) {
+		if ((ioc_state = GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
+			dprintk((KERN_INFO MYNAM ": %s: KickStart successful! (cnt=%d)\n",
+					ioc->name, cnt));
+			return 0;
+		}
+		/* udelay(10000) ? */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	printk(KERN_ERR MYNAM ": %s: ERROR - Failed to come READY after reset!\n",
+			ioc->name);
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_fc9x9_reset - Perform hard reset of FC9x9 adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine places FC9x9 adapter in diagnostic mode via the
+ *	WriteSequence register, and then performs a hard reset of adapter
+ *	via the Diagnostic register.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+mpt_fc9x9_reset(MPT_ADAPTER *ioc)
+{
+	u32 diagval;
+
+	/* Use "Diagnostic reset" method! (only thing available!) */
+
+	/*
+	 * Extra read to handle 909 B.0 chip problem with reset
+	 * logic not finishing the RAM access before hard reset hits.
+	 * (? comment taken from NT SYMMPI source)
+	 */
+	(void) CHIPREG_READ32(&ioc->chip->Fubar);
+
+	/*
+	 * Write magic sequence to WriteSequence register.
+	 * But, send 0x0F first to insure a reset to the beginning of the sequence.
+	 */
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_KEY_VALUE_MASK);
+
+	/* Now write magic sequence */
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+	dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence\n",
+			ioc->name));
+
+	/* Now hit the reset bit in the Diagnostic register */
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER);
+
+	udelay(100);
+
+	if ((diagval = CHIPREG_READ32(&ioc->chip->Diagnostic)) &
+				(MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM)) {
+		printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED!\n",
+				ioc->name);
+		return -9;
+	}
+
+	/* TODO!
+	 * Cleanup all event stuff for this IOC;
+	 * re-issue EventNotification request if needed.
+	 */
+	if (ioc->factsN.Function)
+		ioc->factsN.EventState = 0;
+
+	/* NEW!  20010220 -sralston
+	 * Try to avoid redundant resets of the 929.
+	 */
+	ioc->sod_reset++;
+	ioc->last_kickstart = jiffies;
+	if (ioc->alt_ioc) {
+		ioc->alt_ioc->sod_reset = ioc->sod_reset;
+		ioc->alt_ioc->last_kickstart = ioc->last_kickstart;
+	}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	SendIocReset - Send IOCReset request to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@reset_type: reset type, expected values are
+ *	%MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
+ *
+ *	Send IOCReset request to the MPT adapter.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+SendIocReset(MPT_ADAPTER *ioc, u8 reset_type)
+{
+	int r;
+
+	printk(KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+			ioc->name, reset_type);
+	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
+	if ((r = WaitForDoorbellAck(ioc)) < 0)
+		return r;
+
+	/* TODO!
+	 *  Cleanup all event stuff for this IOC; re-issue EventNotification
+	 *  request if needed.
+	 */
+	if (ioc->factsN.Function)
+		ioc->factsN.EventState = 0;
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine allocates memory for the MPT reply and request frame
+ *	pools, and primes the IOC reply FIFO with reply frames.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+PrimeIocFifos(MPT_ADAPTER *ioc)
+{
+	MPT_FRAME_HDR *mf;
+	unsigned long b;
+	dma_addr_t aligned_mem_dma;
+	u8 *mem, *aligned_mem;
+	int i, sz;
+
+	/*  Prime reply FIFO...  */
+
+	if (ioc->reply_frames == NULL) {
+		sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+		mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->reply_alloc_dma);
+		if (mem == NULL)
+			goto out_fail;
+
+		memset(mem, 0, sz);
+		ioc->alloc_total += sz;
+		ioc->reply_alloc = mem;
+		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%08x], sz=%d bytes\n",
+			 ioc->name, mem, ioc->reply_alloc_dma, sz));
+
+		b = (unsigned long) mem;
+		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
+		aligned_mem = (u8 *) b;
+		ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
+		ioc->reply_frames_dma =
+			(ioc->reply_alloc_dma + (aligned_mem - mem));
+		aligned_mem_dma = ioc->reply_frames_dma;
+		dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%08x]\n",
+			 ioc->name, aligned_mem, aligned_mem_dma));
+
+		for (i = 0; i < ioc->reply_depth; i++) {
+			/*  Write each address to the IOC!  */
+			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
+			aligned_mem_dma += ioc->reply_sz;
+		}
+	}
+
+
+	/*  Request FIFO - WE manage this!  */
+
+	if (ioc->req_frames == NULL) {
+		sz = (ioc->req_sz * ioc->req_depth) + 128;
+		/*
+		 *  Rounding UP to nearest 4-kB boundary here...
+		 */
+		sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+
+		mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->req_alloc_dma);
+		if (mem == NULL)
+			goto out_fail;
+
+		memset(mem, 0, sz);
+		ioc->alloc_total += sz;
+		ioc->req_alloc = mem;
+		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%08x], sz=%d bytes\n",
+			 ioc->name, mem, ioc->req_alloc_dma, sz));
+
+		b = (unsigned long) mem;
+		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
+		aligned_mem = (u8 *) b;
+		ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
+		ioc->req_frames_dma =
+			(ioc->req_alloc_dma + (aligned_mem - mem));
+		aligned_mem_dma = ioc->req_frames_dma;
+
+		dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%08x]\n",
+			 ioc->name, aligned_mem, aligned_mem_dma));
+
+		for (i = 0; i < ioc->req_depth; i++) {
+			mf = (MPT_FRAME_HDR *) aligned_mem;
+
+			/*  Queue REQUESTs *internally*!  */
+			Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			aligned_mem += ioc->req_sz;
+		}
+
+#if defined(CONFIG_MTRR) && 0
+		/*
+		 *  Enable Write Combining MTRR for IOC's memory region.
+		 *  (at least as much as we can; "size and base must be
+		 *  multiples of 4 kiB"
+		 */
+		ioc->mtrr_reg = mtrr_add(ioc->req_alloc_dma,
+					 sz,
+					 MTRR_TYPE_WRCOMB, 1);
+		dprintk((KERN_INFO MYNAM ": %s: MTRR region registered (base:size=%08x:%x)\n",
+				ioc->name, ioc->req_alloc_dma,
+				sz ));
+#endif
+
+	}
+
+	if (ioc->sense_buf_pool == NULL) {
+		sz = (ioc->req_depth * 256);
+		ioc->sense_buf_pool =
+				pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+		if (ioc->sense_buf_pool == NULL)
+			goto out_fail;
+
+		ioc->alloc_total += sz;
+	}
+
+	return 0;
+
+out_fail:
+	if (ioc->reply_alloc != NULL) {
+		sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+		pci_free_consistent(ioc->pcidev,
+				sz,
+				ioc->reply_alloc, ioc->reply_alloc_dma);
+		ioc->reply_frames = NULL;
+		ioc->reply_alloc = NULL;
+		ioc->alloc_total -= sz;
+	}
+	if (ioc->req_alloc != NULL) {
+		sz = (ioc->req_sz * ioc->req_depth) + 128;
+		/*
+		 *  Rounding UP to nearest 4-kB boundary here...
+		 */
+		sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+		pci_free_consistent(ioc->pcidev,
+				sz,
+				ioc->req_alloc, ioc->req_alloc_dma);
+#if defined(CONFIG_MTRR) && 0
+		if (ioc->mtrr_reg > 0) {
+			mtrr_del(ioc->mtrr_reg, 0, 0);
+			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n",
+					ioc->name));
+		}
+#endif
+		ioc->req_frames = NULL;
+		ioc->req_alloc = NULL;
+		ioc->alloc_total -= sz;
+	}
+	if (ioc->sense_buf_pool != NULL) {
+		sz = (ioc->req_depth * 256);
+		pci_free_consistent(ioc->pcidev,
+				sz,
+				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+		ioc->sense_buf_pool = NULL;
+	}
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	HandShakeReqAndReply - Send MPT request to and receive reply from
+ *	IOC via doorbell handshake method.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@reqBytes: Size of the request in bytes
+ *	@req: Pointer to MPT request frame
+ *	@replyBytes: Expected size of the reply in bytes
+ *	@u16reply: Pointer to area where reply should be written
+ *
+ *	NOTES: It is the callers responsibility to byte-swap fields in the
+ *	request which are greater than 1 byte in size.  It is also the
+ *	callers responsibility to byte-swap response fields which are
+ *	greater than 1 byte in size.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply)
+{
+	MPIDefaultReply_t *mptReply;
+	int failcnt = 0;
+	int t;
+
+	/*
+	 * Get ready to cache a handshake reply
+	 */
+	ioc->hs_reply_idx = 0;
+	mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
+	mptReply->MsgLength = 0;
+
+	/*
+	 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
+	 * then tell IOC that we want to handshake a request of N words.
+	 * (WRITE u32val to Doorbell reg).
+	 */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	CHIPREG_WRITE32(&ioc->chip->Doorbell,
+			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
+			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+
+	/*
+	 * Wait for IOC's doorbell handshake int
+	 */
+	if ((t = WaitForDoorbellInt(ioc)) < 0)
+		failcnt++;
+
+	dhsprintk((KERN_INFO MYNAM ": %s: HandShake request start, WaitCnt=%d%s\n",
+			ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+
+	/*
+	 * Clear doorbell int (WRITE 0 to IntStatus reg),
+	 * then wait for IOC to ACKnowledge that it's ready for
+	 * our handshake request.
+	 */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (!failcnt && (t = WaitForDoorbellAck(ioc)) < 0)
+		failcnt++;
+
+	if (!failcnt) {
+		int	 i;
+		u8	*req_as_bytes = (u8 *) req;
+
+		/*
+		 * Stuff request words via doorbell handshake,
+		 * with ACK from IOC for each.
+		 */
+		for (i = 0; !failcnt && i < reqBytes/4; i++) {
+			u32 word = ((req_as_bytes[(i*4) + 0] <<  0) |
+				    (req_as_bytes[(i*4) + 1] <<  8) |
+				    (req_as_bytes[(i*4) + 2] << 16) |
+				    (req_as_bytes[(i*4) + 3] << 24));
+
+			CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+			if ((t = WaitForDoorbellAck(ioc)) < 0)
+				failcnt++;
+		}
+
+		dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
+		DBG_DUMP_REQUEST_FRAME_HDR(req)
+
+		dhsprintk((KERN_INFO MYNAM ": %s: HandShake request post done, WaitCnt=%d%s\n",
+				ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
+
+		/*
+		 * Wait for completion of doorbell handshake reply from the IOC
+		 */
+		if (!failcnt && (t = WaitForDoorbellReply(ioc)) < 0)
+			failcnt++;
+
+		/*
+		 * Copy out the cached reply...
+		 */
+		for(i=0; i < MIN(replyBytes/2,mptReply->MsgLength*2); i++)
+			u16reply[i] = ioc->hs_reply[i];
+	} else {
+		return -99;
+	}
+
+	return -failcnt;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
+ *	in it's IntStatus register.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine waits (up to ~30 seconds max) for IOC doorbell
+ *	handshake ACKnowledge.
+ *
+ *	Returns a negative value on failure, else wait loop count.
+ */
+static int
+WaitForDoorbellAck(MPT_ADAPTER *ioc)
+{
+	int cntdn = HZ * 30;			/* ~30 seconds */
+	int count = 0;
+	u32 intstat;
+
+	while (--cntdn) {
+		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+		if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+			break;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+		count++;
+	}
+
+	if (cntdn) {
+		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell ACK (cnt=%d)\n",
+				ioc->name, count));
+		return count;
+	}
+
+	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell ACK timeout(%d)!\n",
+			ioc->name, (count+5)/HZ);
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
+ *	in it's IntStatus register.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine waits (up to ~30 seconds max) for IOC doorbell interrupt.
+ *
+ *	Returns a negative value on failure, else wait loop count.
+ */
+static int
+WaitForDoorbellInt(MPT_ADAPTER *ioc)
+{
+	int cntdn = HZ * 30;			/* ~30 seconds */
+	int count = 0;
+	u32 intstat;
+
+	while (--cntdn) {
+		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+		if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+			break;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+		count++;
+	}
+
+	if (cntdn) {
+		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell INT (cnt=%d)\n",
+				ioc->name, count));
+		return count;
+	}
+
+	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell INT timeout(%d)!\n",
+			ioc->name, (count+5)/HZ);
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine polls the IOC for a handshake reply, 16 bits at a time.
+ *	Reply is cached to IOC private area large enough to hold a maximum
+ *	of 128 bytes of reply data.
+ *
+ *	Returns a negative value on failure, else size of reply in WORDS.
+ */
+static int
+WaitForDoorbellReply(MPT_ADAPTER *ioc)
+{
+	int u16cnt = 0;
+	int failcnt = 0;
+	int t;
+	u16 *hs_reply = ioc->hs_reply;
+ 	volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
+	u16 hword;
+
+	hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
+
+	/*
+	 * Get first two u16's so we can look at IOC's intended reply MsgLength
+	 */
+	for (u16cnt=0; !failcnt && u16cnt < 2; u16cnt++) {
+		if ((t = WaitForDoorbellInt(ioc)) < 0)
+			failcnt++;
+		hs_reply[u16cnt] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
+		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	}
+
+	dhsprintk((KERN_INFO MYNAM ": %s: First handshake reply word=%08x%s\n",
+			ioc->name, le32_to_cpu(*(u32 *)hs_reply),
+			failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+
+	/*
+	 * If no error (and IOC said MsgLength is > 0), piece together
+	 * reply 16 bits at a time.
+	 */
+	for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
+		if ((t = WaitForDoorbellInt(ioc)) < 0)
+			failcnt++;
+		hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
+		/* don't overflow our IOC hs_reply[] buffer! */
+		if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
+			hs_reply[u16cnt] = hword;
+		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	}
+
+	if (!failcnt && (t = WaitForDoorbellInt(ioc)) < 0)
+		failcnt++;
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+	if (failcnt) {
+		printk(KERN_ERR MYNAM ": %s: ERROR - Handshake reply failure!\n",
+				ioc->name);
+		return -failcnt;
+	}
+#if 0
+	else if (u16cnt != (2 * mptReply->MsgLength)) {
+		return -101;
+	}
+	else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
+		return -102;
+	}
+#endif
+
+	dmfprintk((KERN_INFO MYNAM ": %s: Got Handshake reply:\n", ioc->name));
+	DBG_DUMP_REPLY_FRAME(mptReply)
+
+	dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell REPLY (sz=%d)\n",
+			ioc->name, u16cnt/2));
+	return u16cnt/2;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	GetLanConfigPages - Fetch LANConfig pages.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+GetLanConfigPages(MPT_ADAPTER *ioc)
+{
+	Config_t		 config_req;
+	ConfigReply_t		 config_reply;
+	LANPage0_t		*page0;
+	dma_addr_t		 page0_dma;
+	LANPage1_t		*page1;
+	dma_addr_t		 page1_dma;
+	int			 i;
+	int			 req_sz;
+	int			 reply_sz;
+	int			 data_sz;
+
+/* LANPage0 */
+	/*  Immediate destination (reply area)...  */
+	reply_sz = sizeof(config_reply);
+	memset(&config_reply, 0, reply_sz);
+
+	/*  Ultimate destination...  */
+	page0 = &ioc->lan_cnfg_page0;
+	data_sz = sizeof(*page0);
+	memset(page0, 0, data_sz);
+
+	/*  Request area (config_req on the stack right now!)  */
+	req_sz = sizeof(config_req);
+	memset(&config_req, 0, req_sz);
+	config_req.Function = MPI_FUNCTION_CONFIG;
+	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	/*	config_req.Header.PageVersion = 0;	*/
+	/*	config_req.Header.PageLength = 0;	*/
+	config_req.Header.PageNumber = 0;
+	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
+	/*	config_req.PageAddress = 0;		*/
+	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
+			((MPI_SGE_FLAGS_LAST_ELEMENT |
+			  MPI_SGE_FLAGS_END_OF_BUFFER |
+			  MPI_SGE_FLAGS_END_OF_LIST |
+			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
+			(u32)data_sz
+	);
+	page0_dma = pci_map_single(ioc->pcidev, page0, data_sz, PCI_DMA_FROMDEVICE);
+	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page0_dma);
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_0\n",
+			ioc->name));
+
+	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
+				reply_sz, (u16*)&config_reply);
+	pci_unmap_single(ioc->pcidev, page0_dma, data_sz, PCI_DMA_FROMDEVICE);
+	if (i != 0)
+		return i;
+
+	/*  Now byte swap the necessary LANPage0 fields  */
+
+/* LANPage1 */
+	/*  Immediate destination (reply area)...  */
+	reply_sz = sizeof(config_reply);
+	memset(&config_reply, 0, reply_sz);
+
+	/*  Ultimate destination...  */
+	page1 = &ioc->lan_cnfg_page1;
+	data_sz = sizeof(*page1);
+	memset(page1, 0, data_sz);
+
+	/*  Request area (config_req on the stack right now!)  */
+	req_sz = sizeof(config_req);
+	memset(&config_req, 0, req_sz);
+	config_req.Function = MPI_FUNCTION_CONFIG;
+	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	/*	config_req.Header.PageVersion = 0;	*/
+	/*	config_req.Header.PageLength = 0;	*/
+	config_req.Header.PageNumber = 1;
+	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
+	/*	config_req.PageAddress = 0;		*/
+	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
+			((MPI_SGE_FLAGS_LAST_ELEMENT |
+			  MPI_SGE_FLAGS_END_OF_BUFFER |
+			  MPI_SGE_FLAGS_END_OF_LIST |
+			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
+			(u32)data_sz
+	);
+	page1_dma = pci_map_single(ioc->pcidev, page1, data_sz, PCI_DMA_FROMDEVICE);
+	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page1_dma);
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_1\n",
+			ioc->name));
+
+	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
+				reply_sz, (u16*)&config_reply);
+	pci_unmap_single(ioc->pcidev, page1_dma, data_sz, PCI_DMA_FROMDEVICE);
+	if (i != 0)
+		return i;
+
+	/*  Now byte swap the necessary LANPage1 fields  */
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	SendEventNotification - Send EventNotification (on or off) request
+ *	to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@EvSwitch: Event switch flags
+ */
+static int
+SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
+{
+	EventNotification_t	*evnp;
+
+	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
+	if (evnp == NULL) {
+		dprintk((KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate a event request frame!\n",
+				ioc->name));
+		return 0;
+	}
+	memset(evnp, 0, sizeof(*evnp));
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+
+	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
+	evnp->ChainOffset = 0;
+	evnp->MsgFlags = 0;
+	evnp->Switch = EvSwitch;
+
+	mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	SendEventAck - Send EventAck request to MPT adapter.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@evnp: Pointer to original EventNotification request
+ */
+static int
+SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
+{
+	EventAck_t	*pAck;
+
+	if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
+		printk(KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate event ACK request frame!\n",
+				ioc->name);
+		return -1;
+	}
+	memset(pAck, 0, sizeof(*pAck));
+
+	dprintk((KERN_INFO MYNAM ": %s: Sending EventAck\n", ioc->name));
+
+	pAck->Function     = MPI_FUNCTION_EVENT_ACK;
+	pAck->ChainOffset  = 0;
+	pAck->MsgFlags     = 0;
+	pAck->Event        = evnp->Event;
+	pAck->EventContext = evnp->EventContext;
+
+	mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS		/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
+ */
+
+#define PROC_MPT_READ_RETURN(page,start,off,count,eof,len) \
+{ \
+	len -= off;			\
+	if (len < count) {		\
+		*eof = 1;		\
+		if (len <= 0)		\
+			return 0;	\
+	} else				\
+		len = count;		\
+	*start = page + off;		\
+	return len;			\
+}
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+procmpt_create(void)
+{
+	MPT_ADAPTER *ioc;
+	struct proc_dir_entry *ent;
+	int errcnt = 0;
+
+	/*
+	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
+	 * 	(single level) to multi level (e.g. "driver/message/fusion")
+	 * 	something here needs to change.  -sralston
+	 */
+	procmpt_root_dir = CREATE_PROCDIR_ENTRY(MPT_PROCFS_MPTBASEDIR, NULL);
+	if (procmpt_root_dir == NULL)
+		return -ENOTDIR;
+
+	if ((ioc = mpt_adapter_find_first()) != NULL) {
+		ent = create_proc_read_entry(MPT_PROCFS_SUMMARY_NODE, 0, NULL, procmpt_read_summary, NULL);
+		if (ent == NULL) {
+			printk(KERN_WARNING MYNAM ": WARNING - Could not create %s entry!\n",
+					MPT_PROCFS_SUMMARY_PATHNAME);
+			errcnt++;
+		}
+	}
+
+	while (ioc != NULL) {
+		char pname[32];
+		int namelen;
+		/*
+		 *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
+		 */
+		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+		if ((ent = CREATE_PROCDIR_ENTRY(pname, NULL)) != NULL) {
+			/*
+			 *  And populate it with: "summary" and "dbg" file entries.
+			 */
+			(void) sprintf(pname+namelen, "/summary");
+			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_summary, ioc);
+			if (ent == NULL) {
+				errcnt++;
+				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
+						ioc->name, pname);
+			}
+//#ifdef MPT_DEBUG
+			/* DEBUG aid! */
+			(void) sprintf(pname+namelen, "/dbg");
+			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_dbg, ioc);
+			if (ent == NULL) {
+				errcnt++;
+				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
+						ioc->name, pname);
+			}
+//#endif
+		} else {
+			errcnt++;
+			printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
+					ioc->name, pname);
+
+		}
+
+		ioc = mpt_adapter_find_next(ioc);
+	}
+
+	if (errcnt) {
+//		remove_proc_entry("mpt", 0);
+		return -ENOTDIR;
+	}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+procmpt_destroy(void)
+{
+	MPT_ADAPTER *ioc;
+
+	/*
+	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
+	 * 	(single level) to multi level (e.g. "driver/message/fusion")
+	 * 	something here needs to change.  -sralston
+	 */
+
+	ioc = mpt_adapter_find_first();
+	if (ioc != NULL) {
+		remove_proc_entry(MPT_PROCFS_SUMMARY_NODE, 0);
+	}
+
+	while (ioc != NULL) {
+		char pname[32];
+		int namelen;
+		/*
+		 *  Tear down each "/proc/mpt/iocN" subdirectory.
+		 */
+		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+		(void) sprintf(pname+namelen, "/summary");
+		remove_proc_entry(pname, 0);
+//#ifdef MPT_DEBUG
+		(void) sprintf(pname+namelen, "/dbg");
+		remove_proc_entry(pname, 0);
+//#endif
+		(void) sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
+		remove_proc_entry(pname, 0);
+
+		ioc = mpt_adapter_find_next(ioc);
+	}
+
+	if (atomic_read((atomic_t *)&procmpt_root_dir->count) == 0) {
+		remove_proc_entry(MPT_PROCFS_MPTBASEDIR, 0);
+		return 0;
+	}
+
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	procmpt_read_summary - Handle read request from /proc/mpt/summary
+ *	or from /proc/mpt/iocN/summary.
+ *	@page: Pointer to area to write information
+ *	@start: Pointer to start pointer
+ *	@off: Offset to start writing
+ *	@count: 
+ *	@eof: Pointer to EOF integer
+ *	@data: Pointer 
+ *
+ *	Returns numbers of characters written to process performing the read.
+ */
+static int
+procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	MPT_ADAPTER *ioc;
+	char *out = page;
+	int len;
+
+	if (data == NULL)
+		ioc = mpt_adapter_find_first();
+	else
+		ioc = data;
+
+// Too verbose!
+//	out += sprintf(out, "Attached Fusion MPT I/O Controllers:%s\n", ioc ? "" : " none");
+
+	while (ioc) {
+		int	more = 0;
+
+// Too verbose!
+//		mpt_print_ioc_facts(ioc, out, &more, 0);
+		mpt_print_ioc_summary(ioc, out, &more, 0);
+
+		out += more;
+		if ((out-page) >= count) {
+			break;
+		}
+
+		if (data == NULL)
+			ioc = mpt_adapter_find_next(ioc);
+		else
+			ioc = NULL;				/* force exit for iocN */
+	}
+	len = out - page;
+
+	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
+}
+
+// debug aid!
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	procmpt_read_dbg - Handle read request from /proc/mpt/iocN/dbg.
+ *	@page: Pointer to area to write information
+ *	@start: Pointer to start pointer
+ *	@off: Offset to start writing
+ *	@count: 
+ *	@eof: Pointer to EOF integer
+ *	@data: Pointer 
+ *
+ *	Returns numbers of characters written to process performing the read.
+ */
+static int
+procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	MPT_ADAPTER *ioc;
+	char *out = page;
+	int len;
+
+	ioc = data;
+
+	while (ioc) {
+		int	more = 0;
+
+		mpt_print_ioc_facts(ioc, out, &more, 0);
+
+		out += more;
+		if ((out-page) >= count) {
+			break;
+		}
+		ioc = NULL;
+	}
+	len = out - page;
+
+	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
+}
+#endif		/* CONFIG_PROC_FS } */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
+{
+	if ((ioc->facts0.FWVersion & 0xF000) == 0xE000)
+		sprintf(buf, " (Exp %02d%02d)",
+			(ioc->facts0.FWVersion & 0x0F00) >> 8,	/* Month */
+			ioc->facts0.FWVersion & 0x001F);	/* Day */
+	else
+		buf[0] ='\0';
+
+	/* insider hack! */
+	if (ioc->facts0.FWVersion & 0x0080) {
+		strcat(buf, " [MDBG]");
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@buffer: Pointer to buffer where IOC summary info should be written
+ *	@size: Pointer to number of bytes we wrote (set by this routine)
+ *	@len: Offset at which to start writing in buffer
+ *
+ * 	This routine writes (english readable) ASCII text, which represents
+ * 	a summary of IOC information, to a buffer.
+ */
+void
+mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len)
+{
+	char expVer[32];
+	int y;
+
+
+	mpt_get_fw_exp_ver(expVer, ioc);
+
+	/*
+	 *  Shorter summary of attached ioc's...
+	 */
+	y = sprintf(buffer+len, "%s: %s, %s%04xh%s, Ports=%d, MaxQ=%d",
+			ioc->name,
+			ioc->prod_name,
+			MPT_FW_REV_MAGIC_ID_STRING,	/* "FwRev=" or somesuch */
+			ioc->facts0.FWVersion,
+			expVer,
+			ioc->facts0.NumberOfPorts,
+			ioc->req_depth);
+
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+		u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
+		y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
+			a[5], a[4], a[3], a[2], a[1], a[0]);
+	}
+
+	if (!ioc->active)
+		y += sprintf(buffer+len+y, " (disabled)");
+
+	y += sprintf(buffer+len+y, "\n");
+
+	*size = y;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_print_ioc_facts - Write ASCII summary of IOC facts to a buffer.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@buffer: Pointer to buffer where IOC facts should be written
+ *	@size: Pointer to number of bytes we wrote (set by this routine)
+ *	@len: Offset at which to start writing in buffer
+ *
+ * 	This routine writes (english readable) ASCII text, which represents
+ * 	a summary of the IOC facts, to a buffer.
+ */
+void
+mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buffer, int *size, int len)
+{
+	char expVer[32];
+	char iocName[16];
+	int sz;
+	int y;
+
+
+	mpt_get_fw_exp_ver(expVer, ioc);
+
+	strcpy(iocName, ioc->name);
+	y = sprintf(buffer+len, "%s:\n", iocName);
+
+	y += sprintf(buffer+len+y, "  ProductID = 0x%04x\n", ioc->facts0.ProductID);
+	y += sprintf(buffer+len+y, "  PortNumber = %d (of %d)\n",
+		ioc->pfacts0.PortNumber+1,
+		ioc->facts0.NumberOfPorts);
+	if (ioc->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+		u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
+		y += sprintf(buffer+len+y, "  LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
+			a[5], a[4], a[3], a[2], a[1], a[0]);
+	}
+	y += sprintf(buffer+len+y, "  FWVersion = 0x%04x%s\n", ioc->facts0.FWVersion, expVer);
+	y += sprintf(buffer+len+y, "  MsgVersion = 0x%04x\n", ioc->facts0.MsgVersion);
+	y += sprintf(buffer+len+y, "  WhoInit = 0x%02x\n", ioc->facts0.WhoInit);
+	y += sprintf(buffer+len+y, "  EventState = 0x%02x\n", ioc->facts0.EventState);
+	y += sprintf(buffer+len+y, "  CurrentHostMfaHighAddr = 0x%08x\n",
+		 	ioc->facts0.CurrentHostMfaHighAddr);
+	y += sprintf(buffer+len+y, "  CurrentSenseBufferHighAddr = 0x%08x\n",
+			ioc->facts0.CurrentSenseBufferHighAddr);
+	y += sprintf(buffer+len+y, "  MaxChainDepth = 0x%02x frames\n", ioc->facts0.MaxChainDepth);
+	y += sprintf(buffer+len+y, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts0.BlockSize);
+
+	y += sprintf(buffer+len+y, "  RequestFrames @ 0x%p (Dma @ 0x%08x)\n",
+					ioc->req_alloc, ioc->req_alloc_dma);
+	/*
+	 *  Rounding UP to nearest 4-kB boundary here...
+	 */
+	sz = (ioc->req_sz * ioc->req_depth) + 128;
+	sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+	y += sprintf(buffer+len+y, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
+					ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
+	y += sprintf(buffer+len+y, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
+					4*ioc->facts0.RequestFrameSize,
+					ioc->facts0.GlobalCredits);
+
+	y += sprintf(buffer+len+y, "  ReplyFrames   @ 0x%p (Dma @ 0x%08x)\n",
+					ioc->reply_alloc, ioc->reply_alloc_dma);
+	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+	y += sprintf(buffer+len+y, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
+					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
+	y += sprintf(buffer+len+y, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
+					ioc->factsN.CurReplyFrameSize,
+					ioc->facts0.ReplyQueueDepth);
+
+	*size = y;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static char *
+EventDescriptionStr(u8 event, u32 evData0)
+{
+	char *ds = NULL;
+
+	switch(event) {
+	case MPI_EVENT_NONE:
+		ds = "None";
+		break;
+	case MPI_EVENT_LOG_DATA:
+		ds = "Log Data";
+		break;
+	case MPI_EVENT_STATE_CHANGE:
+		ds = "State Change";
+		break;
+	case MPI_EVENT_UNIT_ATTENTION:
+		ds = "Unit Attention";
+		break;
+	case MPI_EVENT_IOC_BUS_RESET:
+		ds = "IOC Bus Reset";
+		break;
+	case MPI_EVENT_EXT_BUS_RESET:
+		ds = "External Bus Reset";
+		break;
+	case MPI_EVENT_RESCAN:
+		ds = "Bus Rescan Event"; 
+		/* Ok, do we need to do anything here? As far as
+		   I can tell, this is when a new device gets added
+		   to the loop. */
+		break;
+	case MPI_EVENT_LINK_STATUS_CHANGE:
+		if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
+			ds = "Link Status(FAILURE) Change";
+		else
+			ds = "Link Status(ACTIVE) Change";
+		break;
+	case MPI_EVENT_LOOP_STATE_CHANGE:
+		if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
+			ds = "Loop State(LIP) Change";
+		else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
+			ds = "Loop State(LPE) Change";			/* ??? */
+		else
+			ds = "Loop State(LPB) Change";			/* ??? */
+		break;
+	case MPI_EVENT_LOGOUT:
+		ds = "Logout";
+		break;
+	case MPI_EVENT_EVENT_CHANGE:
+		if (evData0)
+			ds = "Events(ON) Change";
+		else
+			ds = "Events(OFF) Change";
+		break;
+	/*
+	 *  MPT base "custom" events may be added here...
+	 */
+	default:
+		ds = "Unknown";
+		break;
+	}
+	return ds;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	ProcessEventNotification - Route a received EventNotificationReply to
+ *	all currently regeistered event handlers.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@pEventReply: Pointer to EventNotification reply frame
+ *	@evHandlers: Pointer to integer, number of event handlers
+ *
+ *	Returns sum of event handlers return values.
+ */
+static int
+ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
+{
+	u16 evDataLen;
+	u32 evData0 = 0;
+//	u32 evCtx;
+	int i;
+	int r = 0;
+	int handlers = 0;
+	char *evStr;
+	u8 event;
+
+	/*
+	 *  Do platform normalization of values
+	 */
+	event = le32_to_cpu(pEventReply->Event) & 0xFF;
+//	evCtx = le32_to_cpu(pEventReply->EventContext);
+	evDataLen = le16_to_cpu(pEventReply->EventDataLength);
+	if (evDataLen) {
+		evData0 = le32_to_cpu(pEventReply->Data[0]);
+	}
+
+	evStr = EventDescriptionStr(event, evData0);
+	dprintk((KERN_INFO MYNAM ": %s: MPT event (%s=%02Xh) detected!\n",
+			ioc->name,
+			evStr,
+			event));
+
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+	printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
+	for (i = 0; i < evDataLen; i++)
+		printk(" %08x", le32_to_cpu(pEventReply->Data[i]));
+	printk("\n");
+#endif
+
+	/*
+	 *  Do general / base driver event processing
+	 */
+	switch(event) {
+	case MPI_EVENT_NONE:			/* 00 */
+	case MPI_EVENT_LOG_DATA:		/* 01 */
+	case MPI_EVENT_STATE_CHANGE:		/* 02 */
+	case MPI_EVENT_UNIT_ATTENTION:		/* 03 */
+	case MPI_EVENT_IOC_BUS_RESET:		/* 04 */
+	case MPI_EVENT_EXT_BUS_RESET:		/* 05 */
+	case MPI_EVENT_RESCAN:			/* 06 */
+	case MPI_EVENT_LINK_STATUS_CHANGE:	/* 07 */
+	case MPI_EVENT_LOOP_STATE_CHANGE:	/* 08 */
+	case MPI_EVENT_LOGOUT:			/* 09 */
+	default:
+		break;
+	case MPI_EVENT_EVENT_CHANGE:		/* 0A */
+		if (evDataLen) {
+			u8 evState = evData0 & 0xFF;
+
+			/* CHECKME! What if evState unexpectedly says OFF (0)? */
+
+			/* Update EventState field in cached IocFacts */
+			if (ioc->factsN.Function) {
+				ioc->factsN.EventState = evState;
+			}
+		}
+		break;
+	}
+
+	/*
+	 *  Call each currently registered protocol event handler.
+	 */
+	for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
+		if (MptEvHandlers[i]) {
+			dprintk((KERN_INFO MYNAM ": %s: Routing Event to event handler #%d\n",
+					ioc->name, i));
+			r += (*(MptEvHandlers[i]))(ioc, pEventReply);
+			handlers++;
+		}
+	}
+	/* FIXME?  Examine results here? */
+
+	/*
+	 *  If needed, send (a single) EventAck.
+	 */
+	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+		if ((i = SendEventAck(ioc, pEventReply)) != 0) {
+		}
+	}
+
+	*evHandlers = handlers;
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_fc_log_info - Log information returned from Fibre Channel IOC.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@log_info: U32 LogInfo reply word from the IOC
+ *
+ *	Refer to lsi/fc_log.h.
+ */
+static void
+mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
+{
+	static char *subcl_str[8] = {
+		"FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
+		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
+	};
+	char *desc = "unknown";
+	u8 subcl = (log_info >> 24) & 0x7;
+	u32 SubCl = log_info & 0x27000000;
+
+	switch(log_info) {
+/* FCP Initiator */
+    	case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
+		desc = "Received an out of order frame - unsupported";
+		break;
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME:
+		desc = "Bad start of frame primative";
+		break;
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME:
+		desc = "Bad end of frame primative";
+		break;
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN:
+		desc = "Receiver hardware detected overrun";
+		break;
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER:
+		desc = "Other errors caught by IOC which require retries";
+		break;
+	case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD:
+		desc = "Main processor could not initialize sub-processor";
+		break;
+/* FC Target */
+	case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC:
+		desc = "Not sent because we are waiting for a PDISC from the initiator";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN:
+		desc = "Not sent because we are not logged in to the remote node";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP:
+		desc = "Data Out, Auto Response, not sent due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP:
+		desc = "Data In, Auto Response, not sent due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA:
+		desc = "Data In, Auto Response, missing data frames";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP:
+		desc = "Data Out, No Response, not sent due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP:
+		desc = "Auto-response after a write not sent due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP:
+		desc = "Data In, No Response, not completed due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA:
+		desc = "Data In, No Response, missing data frames";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP:
+		desc = "Manual Response not sent due to a LIP";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3:
+		desc = "Not sent because remote node does not support Class 3";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID:
+		desc = "Not sent because login to remote node not validated";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND:
+		desc = "Cleared from the outbound after a logout";
+		break;
+	case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN:
+		desc = "Cleared waiting for data after a logout";
+		break;
+/* LAN */
+	case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING:
+		desc = "Transaction Context Sgl Missing";
+		break;
+	case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE:
+		desc = "Transaction Context found before an EOB";
+		break;
+	case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET:
+		desc = "Transaction Context value has reserved bits set";
+		break;
+	case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG:
+		desc = "Invalid SGL Flags";
+		break;
+/* FC Link */
+	case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT:
+		desc = "Loop initialization timed out";
+		break;
+	case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED:
+		desc = "Another system controller already initialized the loop";
+		break;
+	case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED:
+		desc = "Not synchronized to signal or still negotiating (possible cable problem)";
+		break;
+	}
+
+	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x): SubCl={%s}",
+			ioc->name, log_info, subcl_str[subcl]);
+	if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET)
+		printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET);
+	else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE)
+		printk("\n");		/* StateChg in LogInfo & 0x00FFFFFF, above */
+	else
+		printk("\n" KERN_INFO " %s\n", desc);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@mr: Pointer to MPT reply frame
+ *	@log_info: U32 LogInfo word from the IOC
+ *
+ *	Refer to lsi/sp_log.h.
+ */
+static void
+mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
+{
+	/* FIXME! */
+	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x)\n", ioc->name, log_info);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
+ *	OpCode strings from the (optional) isense module.
+ *	@ascqTable: Pointer to ASCQ_Table_t structure
+ *	@ascqtbl_sz: Number of entries in ASCQ_Table
+ *	@opsTable: Pointer to array of SCSI OpCode strings (char pointers)
+ *
+ *	Specialized driver registration routine for the isense driver.
+ */
+int
+mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable)
+{
+	int r = 0;
+
+	if (ascqTable && ascqtbl_sz && opsTable) {
+		mpt_v_ASCQ_TablePtr = ascqTable;
+		mpt_ASCQ_TableSz = ascqtbl_sz;
+		mpt_ScsiOpcodesPtr = opsTable;
+		printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
+		r = 1;
+	}
+	MOD_INC_USE_COUNT;
+	return r;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
+ *	OpCode strings from the isense driver.
+ *
+ *	Specialized driver deregistration routine for the isense driver.
+ */
+void
+mpt_deregister_ascqops_strings(void)
+{
+	mpt_v_ASCQ_TablePtr = NULL;
+	mpt_ASCQ_TableSz = 0;
+	mpt_ScsiOpcodesPtr = NULL;
+	printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
+	MOD_DEC_USE_COUNT;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+EXPORT_SYMBOL(mpt_register);
+EXPORT_SYMBOL(mpt_deregister);
+EXPORT_SYMBOL(mpt_event_register);
+EXPORT_SYMBOL(mpt_event_deregister);
+EXPORT_SYMBOL(mpt_get_msg_frame);
+EXPORT_SYMBOL(mpt_put_msg_frame);
+EXPORT_SYMBOL(mpt_free_msg_frame);
+EXPORT_SYMBOL(mpt_send_handshake_request);
+EXPORT_SYMBOL(mpt_adapter_find_first);
+EXPORT_SYMBOL(mpt_adapter_find_next);
+EXPORT_SYMBOL(mpt_verify_adapter);
+EXPORT_SYMBOL(mpt_print_ioc_summary);
+EXPORT_SYMBOL(mpt_lan_index);
+EXPORT_SYMBOL(mpt_stm_index);
+
+EXPORT_SYMBOL(mpt_register_ascqops_strings);
+EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
+EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
+EXPORT_SYMBOL(mpt_ASCQ_TableSz);
+EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	fusion_init - Fusion MPT base driver initialization routine.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+int __init fusion_init(void)
+{
+	int i;
+
+	if (FusionInitCalled++) {
+		dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
+		return 0;
+	}
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+	printk(KERN_INFO COPYRIGHT "\n");
+
+	Q_INIT(&MptAdapters, MPT_ADAPTER);			/* set to empty */
+	for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
+		MptCallbacks[i] = NULL;
+		MptDriverClass[i] = MPTUNKNOWN_DRIVER;
+		MptEvHandlers[i] = NULL;
+	}
+
+	/* NEW!  20010120 -sralston
+	 *  Register ourselves (mptbase) in order to facilitate
+	 *  EventNotification handling.
+	 */
+	mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
+
+	if ((i = mpt_pci_scan()) < 0)
+		return i;
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	fusion_exit - Perform driver unload cleanup.
+ *
+ *	This routine frees all resources associated with each MPT adapter
+ *	and removes all %MPT_PROCFS_MPTBASEDIR entries.
+ */
+static void fusion_exit(void)
+{
+	MPT_ADAPTER *this;
+	int i;
+
+	dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+
+	/*
+	 *  Paranoia; disable interrupts on all MPT adapters.
+	 */
+	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
+		if ((this = mpt_adapters[i]) != NULL) {
+			/* Disable adapter interrupts! */
+			CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
+			/* Clear any lingering interrupt */
+			CHIPREG_WRITE32(&this->chip->IntStatus, 0);
+			this->active = 0;
+		}
+	}
+
+	/* Whups?  20010120 -sralston
+	 *  Moved this *above* removal of all MptAdapters!
+	 */
+#ifdef CONFIG_PROC_FS
+	procmpt_destroy();
+#endif
+
+	while (! Q_IS_EMPTY(&MptAdapters)) {
+		this = MptAdapters.head;
+		Q_DEL_ITEM(this);
+		mpt_adapter_dispose(this);
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+module_init(fusion_init);
+module_exit(fusion_exit);
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptbase.h linux/drivers/message/fusion/mptbase.h
--- linux-2.4.7-pre3/drivers/message/fusion/mptbase.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptbase.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,581 @@
+/*
+ *  linux/drivers/message/fusion/mptbase.h
+ *      High performance SCSI + LAN / Fibre Channel device drivers.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *     (see mptbase.c)
+ *
+ *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Originally By: Steven J. Ralston
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: mptbase.h,v 1.38 2001/03/22 10:54:30 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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
+*/
+
+#ifndef MPTBASE_H_INCLUDED
+#define MPTBASE_H_INCLUDED
+/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include "linux_compat.h"	/* linux-2.2.x (vs. -2.4.x) tweaks */
+
+#include "lsi/mpi_type.h"
+#include "lsi/mpi.h"		/* Fusion MPI(nterface) basic defs */
+#include "lsi/mpi_ioc.h"	/* Fusion MPT IOC(ontroller) defs */
+#include "lsi/mpi_cnfg.h"	/* IOC configuration support */
+#include "lsi/mpi_init.h"	/* SCSI Host (initiator) protocol support */
+#include "lsi/mpi_lan.h"	/* LAN over FC protocol support */
+
+//#include "lsi/mpi_fc.h"	/* Fibre Channel (lowlevel) support */
+//#include "lsi/mpi_targ.h"	/* SCSI/FCP Target protcol support */
+#include "lsi/fc_log.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#ifndef MODULEAUTHOR
+#define MODULEAUTHOR	"LSI Logic Corporation"
+#endif
+
+#ifndef COPYRIGHT
+#define COPYRIGHT	"Copyright (c) 1999-2001 " MODULEAUTHOR
+#endif
+
+#define MPT_LINUX_VERSION_COMMON	"1.00.11"
+#define MPT_LINUX_VERSION_EXP		"0.09.66-EXP"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-1.00.11"
+#define WHAT_MAGIC_STRING		"@" "(" "#" ")"
+
+#define show_mptmod_ver(s,ver)  \
+	printk(KERN_INFO "%s %s\n", s, ver);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Fusion MPT(linux) driver configurable stuff...
+ */
+#define MPT_MAX_ADAPTERS		16
+#define MPT_MAX_PROTOCOL_DRIVERS	8
+
+#define MPT_MISCDEV_BASENAME		"mptctl"
+#define MPT_MISCDEV_PATHNAME		"/dev/" MPT_MISCDEV_BASENAME
+
+#define MPT_PROCFS_MPTBASEDIR		"mpt"
+						/* chg it to "driver/fusion" ? */
+#define MPT_PROCFS_SUMMARY_NODE		MPT_PROCFS_MPTBASEDIR "/summary"
+#define MPT_PROCFS_SUMMARY_PATHNAME	"/proc/" MPT_PROCFS_SUMMARY_NODE
+#define MPT_FW_REV_MAGIC_ID_STRING	"FwRev="
+
+#ifdef __KERNEL__	/* { */
+#define  MPT_MAX_REQ_DEPTH		1023
+#define  MPT_REQ_DEPTH			256
+#define  MPT_MIN_REQ_DEPTH		128
+
+#define  MPT_MAX_REPLY_DEPTH		MPT_MAX_REQ_DEPTH
+#define  MPT_REPLY_DEPTH		128
+#define  MPT_MIN_REPLY_DEPTH		8
+#define  MPT_MAX_REPLIES_PER_ISR	32
+
+#define  MPT_MAX_FRAME_SIZE		128
+#define  MPT_REQ_SIZE			128
+#define  MPT_REPLY_SIZE			128
+
+#define  MPT_SG_BUCKETS_PER_HUNK	1
+
+#ifdef MODULE
+#define  MPT_REQ_DEPTH_RANGE_STR	__MODULE_STRING(MPT_MIN_REQ_DEPTH) "-" __MODULE_STRING(MPT_MAX_REQ_DEPTH)
+#define  MPT_REPLY_DEPTH_RANGE_STR	__MODULE_STRING(MPT_MIN_REPLY_DEPTH) "-" __MODULE_STRING(MPT_MAX_REPLY_DEPTH)
+#define  MPT_REPLY_SIZE_RANGE_STR	__MODULE_STRING(MPT_MIN_REPLY_SIZE) "-" __MODULE_STRING(MPT_MAX_FRAME_SIZE)
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  MPT protocol driver defs...
+ */
+typedef enum {
+	MPTBASE_DRIVER,		/* MPT base class */
+	MPTCTL_DRIVER,		/* MPT ioctl class */
+	MPTSCSIH_DRIVER,	/* MPT SCSI host (initiator) class */
+	MPTLAN_DRIVER,		/* MPT LAN class */
+	MPTSTM_DRIVER,		/* MPT SCSI target mode class */
+	MPTUNKNOWN_DRIVER
+} MPT_DRIVER_CLASS;
+
+/*
+ *  MPT adapter / port / bus / device info structures...
+ */
+
+typedef union _MPT_FRAME_TRACKER {
+	struct {
+		struct _MPT_FRAME_HDR	*forw;
+		struct _MPT_FRAME_HDR	*back;
+		u32			 arg1;
+		void			*argp1;
+	} linkage;
+	/*
+	 * NOTE: On non-32-bit systems, where pointers are LARGE,
+	 * using the linkage pointers destroys our sacred MsgContext
+	 * field contents.  But we don't care anymore because these
+	 * are now reset in mpt_put_msg_frame() just prior to sending
+	 * a request off to the IOC.
+	 */
+	struct {
+		u32 __hdr[2];
+		/*
+		 * The following _MUST_ match the location of the
+		 * MsgContext field in the MPT message headers.
+		 */
+		union {
+			u32		 MsgContext;
+			struct {
+				u16	 req_idx;	/* Request index */
+				u8	 cb_idx;	/* callback function index */
+				u8	 rsvd;
+			} fld;
+		} msgctxu;
+	} hwhdr;
+} MPT_FRAME_TRACKER;
+
+/*
+ *  We might want to view/access a frame as:
+ *    1) generic request header
+ *    2) SCSIIORequest
+ *    3) SCSIIOReply
+ *    4) MPIDefaultReply
+ *    5) frame tracker
+ */
+typedef struct _MPT_FRAME_HDR {
+	union {
+		MPIHeader_t		hdr;
+		SCSIIORequest_t		scsireq;
+		SCSIIOReply_t		sreply;
+		MPIDefaultReply_t	reply;
+		MPT_FRAME_TRACKER	frame;
+	} u;
+} MPT_FRAME_HDR;
+
+typedef struct _MPT_Q_TRACKER {
+	MPT_FRAME_HDR	*head;
+	MPT_FRAME_HDR	*tail;
+} MPT_Q_TRACKER;
+
+
+typedef struct _MPT_SGL_HDR {
+	SGESimple32_t	 sge[1];
+} MPT_SGL_HDR;
+
+typedef struct _MPT_SGL64_HDR {
+	SGESimple64_t	 sge[1];
+} MPT_SGL64_HDR;
+
+
+typedef struct _Q_ITEM {
+	struct _Q_ITEM	*forw;
+	struct _Q_ITEM	*back;
+} Q_ITEM;
+
+typedef struct _Q_TRACKER {
+	struct _Q_ITEM	*head;
+	struct _Q_ITEM	*tail;
+} Q_TRACKER;
+
+
+/*
+ *  Chip-specific stuff...
+ */
+
+typedef enum {
+	FC909 = 0x0909,
+	FC919 = 0x0919,
+	FC929 = 0x0929,
+	C1030 = 0x1030,
+	FCUNK = 0xFBAD
+} CHIP_TYPE;
+
+/*
+ *  System interface register set
+ */
+
+typedef struct _SYSIF_REGS
+{
+	u32	Doorbell;	/* 00     System<->IOC Doorbell reg  */
+	u32	WriteSequence;	/* 04     Write Sequence register    */
+	u32	Diagnostic;	/* 08     Diagnostic register        */
+	u32	TestBase;	/* 0C     Test Base Address          */
+	u32	Reserved1[8];	/* 10-2F  reserved for future use    */
+	u32	IntStatus;	/* 30     Interrupt Status           */
+	u32	IntMask;	/* 34     Interrupt Mask             */
+	u32	Reserved2[2];	/* 38-3F  reserved for future use    */
+	u32	RequestFifo;	/* 40     Request Post/Free FIFO     */
+	u32	ReplyFifo;	/* 44     Reply   Post/Free FIFO     */
+	u32	Reserved3[2];	/* 48-4F  reserved for future use    */
+	u32	HostIndex;	/* 50     Host Index register        */
+	u32	Reserved4[15];	/* 54-8F                             */
+	u32	Fubar;		/* 90     For Fubar usage            */
+	u32	Reserved5[27];	/* 94-FF                             */
+} SYSIF_REGS;
+
+/*
+ * NOTE: Use MPI_{DOORBELL,WRITESEQ,DIAG}_xxx defs in lsi/mpi.h
+ * in conjunction with SYSIF_REGS accesses!
+ */
+
+
+typedef struct _MPT_ADAPTER
+{
+	struct _MPT_ADAPTER	*forw;
+	struct _MPT_ADAPTER	*back;
+	int			 id;		/* Unique adapter id {0,1,2,...} */
+	int			 pci_irq;
+	IOCFactsReply_t		 facts0;
+	IOCFactsReply_t		 factsN;
+	char			 name[32];	/* "iocN"             */
+	char			*prod_name;	/* "LSIFC9x9"         */
+	u32			 mem_phys;	/* == f4020000 (mmap) */
+	volatile SYSIF_REGS	*chip;		/* == c8817000 (mmap) */
+	CHIP_TYPE		 chip_type;
+	int			 mem_size;
+	int			 alloc_total;
+	u32			 last_state;
+	int			 active;
+	int			 sod_reset;
+	unsigned long		 last_kickstart;
+	PortFactsReply_t	 pfacts0;
+	PortFactsReply_t	 pfactsN;
+	LANPage0_t		 lan_cnfg_page0;
+	LANPage1_t		 lan_cnfg_page1;
+	u8			*reply_alloc;		/* Reply frames alloc ptr */
+	dma_addr_t		 reply_alloc_dma;
+	MPT_FRAME_HDR		*reply_frames;		/* Reply frames - rounded up! */
+	dma_addr_t		 reply_frames_dma;
+	int			 reply_depth;
+	int			 reply_sz;
+		/* We (host driver) get to manage our own RequestQueue! */
+	u8			*req_alloc;		/* Request frames alloc ptr */
+	dma_addr_t		 req_alloc_dma;
+	MPT_FRAME_HDR		*req_frames;		/* Request msg frames for PULL mode! */
+	dma_addr_t		 req_frames_dma;
+	int			 req_depth;
+	int			 req_sz;
+	spinlock_t		 FreeQlock;
+	MPT_Q_TRACKER		 FreeQ;
+		/* Pool of SCSI sense buffers for commands coming from
+		 * the SCSI mid-layer.  We have one 256 byte sense buffer
+		 * for each REQ entry.
+		 */
+	u8			*sense_buf_pool;
+	dma_addr_t		 sense_buf_pool_dma;
+	int			 hs_reply_idx;
+	u32			 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
+	u16			 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
+	struct pci_dev		*pcidev;
+	struct _MPT_ADAPTER	*alt_ioc;
+/*	atomic_t		 userCnt;	*/
+	u8			*memmap;
+	int			 mtrr_reg;
+	struct Scsi_Host	*sh;
+	struct proc_dir_entry	*ioc_dentry;
+} MPT_ADAPTER;
+
+
+typedef struct _MPT_ADAPTER_TRACKER {
+	MPT_ADAPTER	*head;
+	MPT_ADAPTER	*tail;
+} MPT_ADAPTER_TRACKER;
+
+/*
+ *  New return value convention:
+ *    1 = Ok to free associated request frame
+ *    0 = not Ok ...
+ */
+typedef int (*MPT_CALLBACK)(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
+typedef int (*MPT_EVHANDLER)(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply);
+
+/*
+ *  Fibre Channel (SCSI) target device...
+ */
+typedef struct _FC_TARGET {
+	struct _FC_TARGET	*forw;
+	struct _FC_TARGET	*back;
+	int			 bus_id;
+	int			 target_id;
+	int			 lun_exists[32];
+	u8			 inquiry_data[36];
+	u8			 last_sense[256];
+} FC_TARGET;
+
+typedef struct _FCDEV_TRACKER {
+	FC_TARGET	*head;
+	FC_TARGET	*tail;
+} FCDEV_TRACKER;
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Funky (private) macros...
+ */
+#ifdef MPT_DEBUG
+#define dprintk(x)  printk x
+#else
+#define dprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_HANDSHAKE
+#define dhsprintk(x)  printk x
+#else
+#define dhsprintk(x)
+#endif
+
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
+#define dmfprintk(x)  printk x
+#else
+#define dmfprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_IRQ
+#define dirqprintk(x)  printk x
+#else
+#define dirqprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_EVENTS
+#define deventprintk(x)  printk x
+#else
+#define deventprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_SPINLOCK
+#define dslprintk(x)  printk x
+#else
+#define dslprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_SG
+#define dsgprintk(x)  printk x
+#else
+#define dsgprintk(x)
+#endif
+
+
+#define MPT_INDEX_2_MFPTR(ioc,idx) \
+	(MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) )
+
+#define MFPTR_2_MPT_INDEX(ioc,mf) \
+	(int)( ((u8*)mf - (u8*)(ioc)->req_frames) / (ioc)->req_sz )
+
+#define Q_INIT(q,type)  (q)->head = (q)->tail = (type*)(q)
+#define Q_IS_EMPTY(q)   ((Q_ITEM*)(q)->head == (Q_ITEM*)(q))
+
+#define Q_ADD_TAIL(qt,i,type) { \
+	Q_TRACKER	*_qt = (Q_TRACKER*)(qt); \
+	Q_ITEM		*oldTail = _qt->tail; \
+	(i)->forw = (type*)_qt; \
+	(i)->back = (type*)oldTail; \
+	oldTail->forw = (Q_ITEM*)(i); \
+	_qt->tail = (Q_ITEM*)(i); \
+}
+
+#define Q_ADD_HEAD(qt,i,type) { \
+	Q_TRACKER	*_qt = (Q_TRACKER*)(qt); \
+	Q_ITEM		*oldHead = _qt->head; \
+	(i)->forw = (type*)oldHead; \
+	(i)->back = (type*)_qt; \
+	oldHead->back = (Q_ITEM*)(i); \
+	_qt->head = (Q_ITEM*)(i); \
+}
+
+#define Q_DEL_ITEM(i) { \
+	Q_ITEM  *_forw = (Q_ITEM*)(i)->forw; \
+	Q_ITEM  *_back = (Q_ITEM*)(i)->back; \
+	_back->forw = _forw; \
+	_forw->back = _back; \
+}
+
+
+#define SWAB4(value) \
+	(u32)(   (((value) & 0x000000ff) << 24) \
+	       | (((value) & 0x0000ff00) << 8)  \
+	       | (((value) & 0x00ff0000) >> 8)  \
+	       | (((value) & 0xff000000) >> 24) )
+
+
+#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
+#define DBG_DUMP_REPLY_FRAME(mfp) \
+	{	u32 *m = (u32 *)(mfp);					\
+		int  i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16;	\
+		printk(KERN_INFO " ");					\
+		for (i=0; i<n; i++)					\
+			printk(" %08x", le32_to_cpu(m[i]));		\
+		printk("\n");						\
+	}
+#define DBG_DUMP_REQUEST_FRAME_HDR(mfp) \
+	{	int  i, n = 3;						\
+		u32 *m = (u32 *)(mfp);					\
+		printk(KERN_INFO " ");					\
+		for (i=0; i<n; i++)					\
+			printk(" %08x", le32_to_cpu(m[i]));		\
+		printk("\n");						\
+	}
+#else
+#define DBG_DUMP_REPLY_FRAME(mfp)
+#define DBG_DUMP_REQUEST_FRAME_HDR(mfp)
+#endif
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif		/* } __KERNEL__ */
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ *  MPT Control IOCTLs and structures
+ */
+#define MPT_MAGIC_NUMBER	'm'
+#define MPTRWPERF		_IOWR(MPT_MAGIC_NUMBER,0,struct mpt_raw_r_w)
+#define MPTRWPERF_CHK		_IOR(MPT_MAGIC_NUMBER,13,struct mpt_raw_r_w)
+#define MPTRWPERF_RESET		_IOR(MPT_MAGIC_NUMBER,14,struct mpt_raw_r_w)
+#define MPTFWDOWNLOAD		_IOWR(MPT_MAGIC_NUMBER,15,struct mpt_fw_xfer)
+#define MPTSCSICMD		_IOWR(MPT_MAGIC_NUMBER,16,struct mpt_scsi_cmd)
+
+/*
+ *  Define something *vague* enough that caller doesn't
+ *  really need to know anything about device parameters
+ *  (blk_size, capacity, etc.)
+ */
+struct mpt_raw_r_w {
+	unsigned int	 iocnum;	/* IOC unit number */
+	unsigned int	 port;		/* IOC port number */
+	unsigned int	 target;	/* SCSI Target */
+	unsigned int	 lun;		/* SCSI LUN */
+	unsigned int	 iters;		/* N iterations */
+	unsigned short	 nblks;		/* number of blocks per IO */
+	unsigned short	 qdepth;	/* max Q depth on this device */
+	unsigned char	 range;		/* 0-100% of FULL disk capacity, 0=use (nblks X iters) */
+	unsigned char	 skip;		/* % of disk to skip */
+	unsigned char	 rdwr;		/* 0-100%, 0=pure ReaDs, 100=pure WRites */
+	unsigned char	 seqran;	/* 0-100%, 0=pure SEQential, 100=pure RANdom */
+	unsigned int	 cache_sz;	/* In Kb!  Optimize hits to N Kb cache size */
+};
+
+struct mpt_fw_xfer {
+	unsigned int	 iocnum;	/* IOC unit number */
+/*	u8		 flags;*/	/* Message flags - bit field */
+	unsigned int	 fwlen;
+	void		*bufp;		/* Pointer to firmware buffer */
+};
+
+struct mpt_scsi_cmd {
+	unsigned int	 iocnum;	/* IOC unit number */
+	unsigned int	 port;		/* IOC port number */
+	unsigned int	 target;	/* SCSI Target */
+	unsigned int	 lun;		/* SCSI LUN */
+	SCSIIORequest_t	 scsi_req;
+	SCSIIOReply_t	 scsi_reply;
+};
+
+struct mpt_ioctl_sanity {
+	unsigned int	 iocnum;
+};
+
+#ifdef __KERNEL__	/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ *  Public entry points...
+ */
+extern int	 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
+extern void	 mpt_deregister(int cb_idx);
+extern int	 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);
+extern void	 mpt_event_deregister(int cb_idx);
+extern int	 mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable);
+extern void	 mpt_deregister_ascqops_strings(void);
+extern MPT_FRAME_HDR	*mpt_get_msg_frame(int handle, int iocid);
+extern void	 mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf);
+extern void	 mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf);
+extern int	 mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req);
+extern int	 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
+extern MPT_ADAPTER	*mpt_adapter_find_first(void);
+extern MPT_ADAPTER	*mpt_adapter_find_next(MPT_ADAPTER *prev);
+extern void	 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len);
+extern void	 mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buf, int *size, int len);
+
+/*
+ *  Public data decl's...
+ */
+extern int		  mpt_lan_index;	/* needed by mptlan.c */
+extern int		  mpt_stm_index;	/* needed by mptstm.c */
+
+extern void		 *mpt_v_ASCQ_TablePtr;
+extern const char	**mpt_ScsiOpcodesPtr;
+extern int		  mpt_ASCQ_TableSz;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif		/* } __KERNEL__ */
+
+/*
+ *  More (public) macros...
+ */
+#ifndef MIN
+#define MIN(a, b)   (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b)   (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef offsetof
+#define offsetof(t, m)	((size_t) (&((t *)0)->m))
+#endif
+
+#if defined(__alpha__) || defined(__sparc_v9__)
+#define CAST_U32_TO_PTR(x)	((void *)(u64)x)
+#define CAST_PTR_TO_U32(x)	((u32)(u64)x)
+#else
+#define CAST_U32_TO_PTR(x)	((void *)x)
+#define CAST_PTR_TO_U32(x)	((u32)x)
+#endif
+
+#define MPT_PROTOCOL_FLAGS_c_c_c_c(pflags) \
+	((pflags) & MPI_PORTFACTS_PROTOCOL_INITIATOR)	? 'I' : 'i',	\
+	((pflags) & MPI_PORTFACTS_PROTOCOL_TARGET)	? 'T' : 't',	\
+	((pflags) & MPI_PORTFACTS_PROTOCOL_LAN)		? 'L' : 'l',	\
+	((pflags) & MPI_PORTFACTS_PROTOCOL_LOGBUSADDR)	? 'B' : 'b'
+
+/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptctl.c linux/drivers/message/fusion/mptctl.c
--- linux-2.4.7-pre3/drivers/message/fusion/mptctl.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptctl.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,1296 @@
+/*
+ *  linux/drivers/message/fusion/mptctl.c
+ *      Fusion MPT misc device (ioctl) driver.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *      This driver would not exist if not for Alan Cox's development
+ *      of the linux i2o driver.
+ *
+ *      A huge debt of gratitude is owed to David S. Miller (DaveM)
+ *      for fixing much of the stupid and broken stuff in the early
+ *      driver while porting to sparc64 platform.  THANK YOU!
+ *
+ *      A big THANKS to Eddie C. Dost for fixing the ioctl path
+ *      and most importantly f/w download on sparc64 platform!
+ *      (plus Eddie's other helpful hints and insights)
+ *
+ *      Thanks to Arnaldo Carvalho de Melo for finding and patching
+ *      a potential memory leak in mpt_ioctl_do_fw_download(),
+ *      and for some kmalloc insight:-)
+ *
+ *      (see also mptbase.c)
+ *
+ *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Originally By: Steven J. Ralston, Noah Romer
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: mptctl.c,v 1.23 2001/03/21 19:42:31 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/miscdevice.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <linux/proc_fs.h>
+
+#define COPYRIGHT	"Copyright (c) 1999-2001 LSI Logic Corporation"
+#define MODULEAUTHOR	"Steven J. Ralston, Noah Romer"
+#include "mptbase.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"Fusion MPT misc device (ioctl) driver"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"mptctl"
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static int mptctl_id = -1;
+static int rwperf_reset = 0;
+static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static int mpt_ioctl_rwperf(unsigned long arg);
+static int mpt_ioctl_rwperf_status(unsigned long arg);
+static int mpt_ioctl_rwperf_reset(unsigned long arg);
+static int mpt_ioctl_fw_download(unsigned long arg);
+static int mpt_ioctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen);
+static int mpt_ioctl_scsi_cmd(unsigned long arg);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * Scatter gather list (SGL) sizes and limits...
+ */
+//#define MAX_SCSI_FRAGS	9
+#define MAX_FRAGS_SPILL1	9
+#define MAX_FRAGS_SPILL2	15
+#define FRAGS_PER_BUCKET	(MAX_FRAGS_SPILL2 + 1)
+
+//#define MAX_CHAIN_FRAGS	64
+//#define MAX_CHAIN_FRAGS	(15+15+15+16)
+#define MAX_CHAIN_FRAGS		(4 * MAX_FRAGS_SPILL2 + 1)
+
+//  Define max sg LIST bytes ( == (#frags + #chains) * 8 bytes each)
+//  Works out to: 592d bytes!     (9+1)*8 + 4*(15+1)*8
+//                  ^----------------- 80 + 512
+#define MAX_SGL_BYTES		((MAX_FRAGS_SPILL1 + 1 + (4 * FRAGS_PER_BUCKET)) * 8)
+
+/* linux only seems to ever give 128kB MAX contiguous (GFP_USER) mem bytes */
+#define MAX_KMALLOC_SZ		(128*1024)
+
+struct buflist {
+	u8	*kptr;
+	int	 len;
+};
+
+#define myMAX_TARGETS	(1<<4)
+#define myMAX_LUNS	(1<<3)
+#define myMAX_T_MASK	(myMAX_TARGETS-1)
+#define myMAX_L_MASK	(myMAX_LUNS-1)
+static u8  DevInUse[myMAX_TARGETS][myMAX_LUNS] = {{0,0}};
+static u32 DevIosCount[myMAX_TARGETS][myMAX_LUNS] = {{0,0}};
+
+static u32 fwReplyBuffer[16];
+static pMPIDefaultReply_t ReplyMsg = NULL;
+
+/* some private forw protos */
+static SGESimple32_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int *frags,
+		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
+static void kfree_sgl( SGESimple32_t *sgl, dma_addr_t sgl_dma,
+		struct buflist *buflist, MPT_ADAPTER *ioc);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptctl_syscall_down - Down the MPT adapter syscall semaphore.
+ *	@ioc: Pointer to MPT adapter
+ *	@nonblock: boolean, non-zero if O_NONBLOCK is set
+ *
+ *	All of the mptctl commands can potentially sleep, which is illegal
+ *	with a spinlock held, thus we perform mutual exclusion here.
+ *
+ *	Returns negative errno on error, or zero for success.
+ */
+static inline int
+mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
+{
+	dprintk((KERN_INFO MYNAM "::mpt_syscall_down(%p,%d) called\n", ioc, nonblock));
+
+	if (nonblock) {
+		if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+			return -EAGAIN;
+	} else {
+		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+			return -ERESTARTSYS;
+	}
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  This is the callback for any message we have posted. The message itself
+ *  will be returned to the message pool when we return from the IRQ
+ *
+ *  This runs in irq context so be short and sweet.
+ */
+static int
+mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
+{
+	u8 targ;
+
+	//dprintk((KERN_DEBUG MYNAM ": Got mptctl_reply()!\n"));
+
+	if (req && req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
+		targ = req->u.scsireq.TargetID & myMAX_T_MASK;
+		DevIosCount[targ][0]--;
+	} else if (reply && req && req->u.hdr.Function == MPI_FUNCTION_FW_DOWNLOAD) {
+		// NOTE: Expects/requires non-Turbo reply!
+		dprintk((KERN_INFO MYNAM ": Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n"));
+		memcpy(fwReplyBuffer, reply, MIN(sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength));
+		ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer;
+	}
+
+	return 1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static loff_t
+mptctl_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static ssize_t
+mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	printk(KERN_ERR MYNAM ": ioctl WRITE not yet supported\n");
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static ssize_t
+mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+{
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  MPT ioctl handler
+ */
+static int
+mpt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct mpt_ioctl_sanity	*usanity = (struct mpt_ioctl_sanity *) arg;
+	struct mpt_ioctl_sanity	 ksanity;
+	int iocnum;
+	unsigned iocnumX;
+	int nonblock = (file->f_flags & O_NONBLOCK);
+	int ret;
+	MPT_ADAPTER *iocp = NULL;
+
+	dprintk((KERN_INFO MYNAM "::mpt_ioctl() called\n"));
+
+	if (copy_from_user(&ksanity, usanity, sizeof(ksanity))) {
+		printk(KERN_ERR "%s::mpt_ioctl() @%d - "
+				"Unable to copy mpt_ioctl_sanity data @ %p\n",
+				__FILE__, __LINE__, (void*)usanity);
+		return -EFAULT;
+	}
+	ret = -ENXIO;				/* (-6) No such device or address */
+
+	/* Verify intended MPT adapter */
+	iocnumX = ksanity.iocnum & 0xFF;
+	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+	    (iocp == NULL)) {
+		printk(KERN_ERR "%s::mpt_ioctl() @%d - ioc%d not found!\n",
+				__FILE__, __LINE__, iocnumX);
+		return -ENODEV;
+	}
+
+	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+		return ret;
+
+	dprintk((KERN_INFO MYNAM "::mpt_ioctl() - Using %s\n", iocp->name));
+
+	switch(cmd) {
+	case MPTRWPERF:
+		ret = mpt_ioctl_rwperf(arg);
+		break;
+	case MPTRWPERF_CHK:
+		ret = mpt_ioctl_rwperf_status(arg);
+		break;
+	case MPTRWPERF_RESET:
+		ret = mpt_ioctl_rwperf_reset(arg);
+		break;
+	case MPTFWDOWNLOAD:
+		ret = mpt_ioctl_fw_download(arg);
+		break;
+	case MPTSCSICMD:
+		ret = mpt_ioctl_scsi_cmd(arg);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	up(&mptctl_syscall_sem_ioc[iocp->id]);
+
+	return ret;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int mptctl_open(struct inode *inode, struct file *file)
+{
+	/*
+	 * Should support multiple management users
+	 */
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int mptctl_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_fw_download(unsigned long arg)
+{
+	struct mpt_fw_xfer	*ufwdl = (struct mpt_fw_xfer *) arg;
+	struct mpt_fw_xfer	 kfwdl;
+
+	dprintk((KERN_INFO "mpt_ioctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
+	if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
+		printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+				"Unable to copy mpt_fw_xfer struct @ %p\n",
+				__FILE__, __LINE__, (void*)ufwdl);
+		return -EFAULT;
+	}
+
+	return mpt_ioctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * MPT FW Download
+ */
+static int
+mpt_ioctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
+{
+	FWDownload_t		*dlmsg;
+	MPT_FRAME_HDR		*mf;
+	MPT_ADAPTER		*iocp;
+//	char			*fwbuf;
+//	dma_addr_t		 fwbuf_dma;
+	FWDownloadTCSGE_t	*fwVoodoo;
+//	SGEAllUnion_t		*fwSgl;
+	int			 ret;
+
+	SGESimple32_t	*sgl;
+	SGESimple32_t	*sgOut, *sgIn;
+	dma_addr_t	 sgl_dma;
+	struct buflist	*buflist;
+	struct buflist	*bl;
+	int		 numfrags = 0;
+	int		 maxfrags;
+	int		 n = 0;
+	u32		 sgdir;
+	u32		 nib;
+	int		 fw_bytes_copied = 0;
+	u16		 iocstat;
+	int		 i;
+
+	dprintk((KERN_INFO "mpt_ioctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
+
+	dprintk((KERN_INFO "DbG: kfwdl.bufp  = %p\n", ufwbuf));
+	dprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen));
+	dprintk((KERN_INFO "DbG: kfwdl.ioc   = %04xh\n", ioc));
+
+	if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
+		printk("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
+				__FILE__, __LINE__, ioc);
+		return -ENXIO; /* (-6) No such device or address */
+	}
+
+	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
+		return -EAGAIN;
+	dlmsg = (FWDownload_t*) mf;
+	fwVoodoo = (FWDownloadTCSGE_t *) &dlmsg->SGL;
+	sgOut = (SGESimple32_t *) (fwVoodoo + 1);
+
+	/*
+	 * Construct f/w download request
+	 */
+	dlmsg->ImageType = MPI_FW_DOWNLOAD_ITYPE_FW;
+	dlmsg->Reserved = 0;
+	dlmsg->ChainOffset = 0;
+	dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
+	dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
+	dlmsg->MsgFlags = 0;
+
+	fwVoodoo->Reserved = 0;
+	fwVoodoo->ContextSize = 0;
+	fwVoodoo->DetailsLength = 12;
+	fwVoodoo->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
+	fwVoodoo->Reserved1 = 0;
+	fwVoodoo->ImageOffset = 0;
+	fwVoodoo->ImageSize = cpu_to_le32(fwlen);
+
+	/*
+	 * Need to kmalloc area(s) for holding firmware image bytes.
+	 * But we need to do it piece meal, using a proper
+	 * scatter gather list (with 128kB MAX hunks).
+	 * 
+	 * A practical limit here might be # of sg hunks that fit into
+	 * a single IOC request frame; 12 or 8 (see below), so:
+	 * For FC9xx: 12 x 128kB == 1.5 mB (max)
+	 * For C1030:  8 x 128kB == 1   mB (max)
+	 * We could support chaining, but things get ugly(ier:)
+	 */
+	sgdir = 0x04000000;		/* IOC will READ from sys mem */
+	if ((sgl = kbuf_alloc_2_sgl(fwlen, sgdir, &numfrags, &buflist, &sgl_dma, iocp)) == NULL)
+		return -ENOMEM;
+
+	/*
+	 * We should only need SGL with 2 simple_32bit entries (up to 256 kB)
+	 * for FC9xx f/w image, but calculate max number of sge hunks
+	 * we can fit into a request frame, and limit ourselves to that.
+	 * (currently no chain support)
+	 * For FC9xx: (128-12-16)/8 = 12.5 = 12
+	 * For C1030:  (96-12-16)/8 =  8.5 =  8
+	 */
+	maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) / sizeof(SGESimple32_t);
+	if (numfrags > maxfrags) {
+		ret = -EMLINK;
+		goto fwdl_out;
+	}
+
+	dprintk((KERN_INFO "DbG: sgl buffer  = %p, sgfrags = %d\n", sgl, numfrags));
+
+	/*
+	 * Parse SG list, copying sgl itself,
+	 * plus f/w image hunks from user space as we go...
+	 */
+	ret = -EFAULT;
+	sgIn = sgl;
+	bl = buflist;
+	for (i=0; i < numfrags; i++) {
+		nib = (sgIn->FlagsLength & 0xF0000000) >> 28;
+		/* skip ignore/chain. */
+		if (nib == 0 || nib == 3) {
+			;
+		} else if (sgIn->Address) {
+			*sgOut = *sgIn;
+			n++;
+			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
+				printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+						"Unable to copy f/w buffer hunk#%d @ %p\n",
+						__FILE__, __LINE__, n, (void*)ufwbuf);
+				goto fwdl_out;
+			}
+			fw_bytes_copied += bl->len;
+		}
+		sgIn++;
+		bl++;
+		sgOut++;
+	}
+
+#ifdef MPT_DEBUG
+	{
+		u32 *m = (u32 *)mf;
+		printk(KERN_INFO MYNAM ": F/W download request:\n" KERN_INFO " ");
+		for (i=0; i < 7+numfrags*2; i++)
+			printk(" %08x", le32_to_cpu(m[i]));
+		printk("\n");
+	}
+#endif
+
+	/*
+	 * Finally, perform firmware download.
+	 */
+	ReplyMsg = NULL;
+	mpt_put_msg_frame(mptctl_id, ioc, mf);
+
+	/*
+	 *  Wait until the reply has been received
+	 */
+	{
+		int	 foo = 0;
+
+		while (ReplyMsg == NULL) {
+			if (!(foo%1000000)) {
+				dprintk((KERN_INFO "DbG::_do_fwdl: "
+					   "In ReplyMsg loop - iteration %d\n",
+					   foo)); //tc
+			}
+			ret = -ETIME;
+			if (++foo > 60000000)
+				goto fwdl_out;
+			mb();
+			schedule();
+			barrier();
+		}
+	}
+
+	if (sgl)
+        	kfree_sgl(sgl, sgl_dma, buflist, iocp);
+
+	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
+	if (iocstat == MPI_IOCSTATUS_SUCCESS) {
+		printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
+		return 0;
+	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
+		printk(KERN_WARNING MYNAM ": ?Hmmm...  %s says it doesn't support F/W download!?!\n",
+				iocp->name);
+		printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n");
+		return -EBADRQC;
+	} else if (iocstat == MPI_IOCSTATUS_BUSY) {
+		printk(KERN_WARNING MYNAM ": Warning!  %s says: IOC_BUSY!\n", iocp->name);
+		printk(KERN_WARNING MYNAM ": (try again later?)\n");
+		return -EBUSY;
+	} else {
+		printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
+				    iocp->name, iocstat);
+		printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");
+		return -ENOMSG;
+	}
+	return 0;
+
+fwdl_out:
+        kfree_sgl(sgl, sgl_dma, buflist, iocp);
+	return ret;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  NEW rwperf (read/write performance) stuff starts here...
+ */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static SGESimple32_t *
+kbuf_alloc_2_sgl(int bytes, u32 sgdir, int *frags,
+		 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc)
+{
+	SGESimple32_t	*sglbuf = NULL;
+	struct buflist	*buflist = NULL;
+	int		 numfrags = 0;
+	int		 fragcnt = 0;
+	int		 alloc_sz = MIN(bytes,MAX_KMALLOC_SZ);	// avoid kernel warning msg!
+	int		 bytes_allocd = 0;
+	int		 this_alloc;
+	SGESimple32_t	*sgl;
+	u32		 pa;					// phys addr
+	SGEChain32_t	*last_chain = NULL;
+	SGEChain32_t	*old_chain = NULL;
+	int		 chaincnt = 0;
+	int		 i, buflist_ent;
+	int		 sg_spill = MAX_FRAGS_SPILL1;
+	int		 dir;
+
+	*frags = 0;
+	*blp = NULL;
+	i = MAX_SGL_BYTES / 8;
+	buflist = kmalloc(i, GFP_USER);
+	if (buflist == NULL)
+		return NULL;
+	memset(buflist, 0, i);
+	buflist_ent = 0;
+
+	sglbuf = pci_alloc_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf_dma);
+	if (sglbuf == NULL)
+		goto free_and_fail;
+
+	if (sgdir & 0x04000000)
+		dir = PCI_DMA_TODEVICE;
+	else
+		dir = PCI_DMA_FROMDEVICE;
+
+	sgl = sglbuf;
+	while (bytes_allocd < bytes) {
+		this_alloc = MIN(alloc_sz, bytes-bytes_allocd);
+		buflist[buflist_ent].len = this_alloc;
+		buflist[buflist_ent].kptr = pci_alloc_consistent(ioc->pcidev,
+								 this_alloc,
+								 &pa);
+		if (buflist[buflist_ent].kptr == NULL) {
+			alloc_sz = alloc_sz / 2;
+			if (alloc_sz == 0) {
+				printk(KERN_WARNING MYNAM "-SG: No can do - "
+						    "not enough memory!   :-(\n");
+				printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+						    numfrags);
+				goto free_and_fail;
+			}
+			continue;
+		} else {
+			dma_addr_t dma_addr;
+
+			bytes_allocd += this_alloc;
+
+			/* Write one SIMPLE sge */
+			sgl->FlagsLength = cpu_to_le32(0x10000000|sgdir|this_alloc);
+			dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);
+			sgl->Address = cpu_to_le32(dma_addr);
+
+			fragcnt++;
+			numfrags++;
+			sgl++;
+			buflist_ent++;
+		}
+
+		if (bytes_allocd >= bytes)
+			break;
+
+		/* Need to chain? */
+		if (fragcnt == sg_spill) {
+			dma_addr_t chain_link;
+
+			if (last_chain != NULL)
+				last_chain->NextChainOffset = 0x1E;
+
+			fragcnt = 0;
+			sg_spill = MAX_FRAGS_SPILL2;
+
+			/* fixup previous SIMPLE sge */
+			sgl[-1].FlagsLength |= cpu_to_le32(0x80000000);
+
+			chain_link = (*sglbuf_dma) +
+				((u8 *)(sgl+1) - (u8 *)sglbuf);
+
+			/* Write one CHAIN sge */
+			sgl->FlagsLength = cpu_to_le32(0x30000080);
+			sgl->Address = cpu_to_le32(chain_link);
+
+			old_chain = last_chain;
+			last_chain = (SGEChain32_t*)sgl;
+			chaincnt++;
+			numfrags++;
+			sgl++;
+		}
+
+		/* overflow check... */
+		if (numfrags*8 > MAX_SGL_BYTES) {
+			/* GRRRRR... */
+			printk(KERN_WARNING MYNAM "-SG: No can do - "
+					    "too many SG frags!   :-(\n");
+			printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+					    numfrags);
+			goto free_and_fail;
+		}
+	}
+
+	/* Last sge fixup: set LE+eol+eob bits */
+	sgl[-1].FlagsLength |= cpu_to_le32(0xC1000000);
+
+	/* Chain fixup needed? */
+	if (last_chain != NULL && fragcnt < 16)
+		last_chain->Length = cpu_to_le16(fragcnt * 8);
+
+	*frags = numfrags;
+	*blp = buflist;
+
+	dprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "
+			   "%d SG frags generated!  (%d CHAIN%s)\n",
+			   numfrags, chaincnt, chaincnt>1?"s":""));
+
+	dprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "
+			   "last (big) alloc_sz=%d\n",
+			   alloc_sz));
+
+	return sglbuf;
+
+free_and_fail:
+	if (sglbuf != NULL) {
+		int i;
+
+		for (i = 0; i < numfrags; i++) {
+			dma_addr_t dma_addr;
+			u8 *kptr;
+			int len;
+
+			if ((sglbuf[i].FlagsLength >> 24) == 0x30)
+				continue;
+
+			dma_addr = le32_to_cpu(sglbuf[i].Address);
+			kptr = buflist[i].kptr;
+			len = buflist[i].len;
+
+			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
+		}
+		pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf, *sglbuf_dma);
+	}
+	kfree(buflist);
+	return NULL;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+kfree_sgl(SGESimple32_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc)
+{
+	SGESimple32_t	*sg = sgl;
+	struct buflist	*bl = buflist;
+	u32		 nib;
+	int		 dir;
+	int		 n = 0;
+
+	if (sg->FlagsLength & 0x04000000)
+		dir = PCI_DMA_TODEVICE;
+	else
+		dir = PCI_DMA_FROMDEVICE;
+
+	nib = (sg->FlagsLength & 0xF0000000) >> 28;
+	while (! (nib & 0x4)) { /* eob */
+		/* skip ignore/chain. */
+		if (nib == 0 || nib == 3) {
+			;
+		} else if (sg->Address) {
+			dma_addr_t dma_addr;
+			void *kptr;
+			int len;
+
+			dma_addr = le32_to_cpu(sg->Address);
+			kptr = bl->kptr;
+			len = bl->len;
+			pci_unmap_single(ioc->pcidev, dma_addr, len, dir);
+			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
+			n++;
+		}
+		sg++;
+		bl++;
+		nib = (sg->FlagsLength & 0xF0000000) >> 28;
+	}
+
+	/* we're at eob! */
+	if (sg->Address) {
+		dma_addr_t dma_addr;
+		void *kptr;
+		int len;
+
+		dma_addr = le32_to_cpu(sg->Address);
+		kptr = bl->kptr;
+		len = bl->len;
+		pci_unmap_single(ioc->pcidev, dma_addr, len, dir);
+		pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);
+		n++;
+	}
+
+	pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sgl, sgl_dma);
+	kfree(buflist);
+	dprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n));
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_rwperf_init(struct mpt_raw_r_w *dest, unsigned long src,
+		      char *caller, MPT_ADAPTER **iocpp)
+{
+	char	*myname = "_rwperf_init()";
+	int	 ioc;
+
+	/* get copy of structure passed from user space */
+	if (copy_from_user(dest, (void*)src, sizeof(*dest))) {
+		printk(KERN_ERR MYNAM "::%s() @%d - Can't copy mpt_raw_r_w data @ %p\n",
+				myname, __LINE__, (void*)src);
+		return -EFAULT;				/* (-14) Bad address */
+	} else {
+		dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{ioc,targ,qd,iters,nblks}"
+				   ": %d %d %d %d %d\n",
+				   dest->iocnum, dest->target,
+				   (int)dest->qdepth, dest->iters, dest->nblks ));
+		dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{cache,skip,range,rdwr,seqran}"
+				   ": %d %d %d %d %d\n",
+				   dest->cache_sz, dest->skip, dest->range,
+				   dest->rdwr, dest->seqran ));
+
+		/* Get the MPT adapter id. */
+		if ((ioc = mpt_verify_adapter(dest->iocnum, iocpp)) < 0) {
+			printk(KERN_ERR MYNAM "::%s() @%d - ioc%d not found!\n",
+					myname, __LINE__, dest->iocnum);
+			return -ENXIO;			/* (-6) No such device or address */
+		} else {
+			dprintk((MYNAM "-perf: %s using mpt/ioc%x, target %02xh\n",
+					caller, dest->iocnum, dest->target));
+		}
+	}
+
+	return ioc;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*  Treat first N blocks of disk as sacred!  */
+#define SACRED_BLOCKS	100
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_rwperf(unsigned long arg)
+{
+	struct mpt_raw_r_w	 kPerfInfo;
+				/* NOTE: local copy, on stack==KERNEL_SPACE! */
+	u8		 target, targetM;
+	u8		 lun, lunM;
+	u8		 scsiop;
+	int		 qdepth;
+	int		 iters;
+	int		 cache_sz;
+	u32		 xferbytes;
+	u32		 scsidir;
+	u32		 qtag;
+	u32		 scsictl;
+	u32		 sgdir;
+	u32		 blkno;
+	u32		 sbphys;
+	SGESimple32_t	*sgl;
+	dma_addr_t	 sgl_dma;
+	struct buflist	*buflist;
+	SGESimple32_t	*sgOut, *sgIn;
+	int		 numfrags;
+	u32		*msg;
+	int		 i;
+	int		 ioc;
+	MPT_FRAME_HDR	*mf;
+	MPT_ADAPTER	*iocp;
+	int		 sgfragcpycnt;
+	int		 blklo, blkhi;
+	u8		 nextchainoffset;
+	u8		*SenseBuf;
+	dma_addr_t	 SenseBufDMA;
+	char		*myname = "_rwperf()";
+
+    dprintk((KERN_INFO "%s - starting...\n", myname));
+
+    /* Validate target device */
+    if ((ioc = mpt_ioctl_rwperf_init(&kPerfInfo, arg, myname, &iocp)) < 0)
+        return ioc;
+
+    /* Allocate DMA'able memory for the sense buffer. */
+    SenseBuf = pci_alloc_consistent(iocp->pcidev, 256, &SenseBufDMA);
+
+    /* set perf parameters from input */
+    target = kPerfInfo.target & 0x0FF;
+    targetM = target & myMAX_T_MASK;
+    lun = kPerfInfo.lun & 0x1F;			// LUN=31 max
+    lunM = lun & myMAX_L_MASK;
+    qdepth = kPerfInfo.qdepth;
+    iters = kPerfInfo.iters;
+    xferbytes = ((u32)kPerfInfo.nblks)<<9;
+
+    DevInUse[targetM][lunM] = 1;
+    DevIosCount[targetM][lunM] = 0;
+
+    cache_sz = kPerfInfo.cache_sz * 1024;	// CacheSz in kB!
+
+    /* ToDo: */
+    /* get capacity (?) */
+
+
+    // pre-build, one time, everything we can for speed in the loops below...
+
+    scsiop = 0x28;				// default to SCSI READ!
+    scsidir = MPI_SCSIIO_CONTROL_READ;		// DATA IN  (host<--ioc<--dev)
+						// 02000000
+    qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;		// 00000000
+
+    if (xferbytes == 0) {
+        // Do 0-byte READ!!!
+        //  IMPORTANT!  Need to set no SCSI DIR for this!
+        scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
+    }
+
+    scsictl = scsidir | qtag;
+
+    /*
+     *  Set sgdir for DMA transfer.
+     */
+//    sgdir   = 0x04000000;		// SCSI WRITE
+    sgdir = 0x00000000;			// SCSI READ
+
+    if ((sgl = kbuf_alloc_2_sgl(MAX(512,xferbytes), sgdir, &numfrags, &buflist, &sgl_dma, iocp)) == NULL)
+        return -ENOMEM;
+
+    sgfragcpycnt = MIN(10,numfrags);
+    nextchainoffset = 0;
+    if (numfrags > 10)
+        nextchainoffset = 0x1E;
+
+    sbphys = SenseBufDMA;
+
+    rwperf_reset = 0;
+
+//    do {	// target-loop
+
+        blkno = SACRED_BLOCKS;		// Treat first N blocks as sacred!
+					// FIXME!  Skip option
+        blklo = blkno;
+        blkhi = blkno;
+
+        do {    // inner-loop
+
+            while ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+                mb();
+                schedule();
+                barrier();
+            }
+            msg = (u32*)mf;
+
+            /* Start piecing the SCSIIORequest together */
+            msg[0] = 0x00000000 | nextchainoffset<<16 | target;
+            msg[1] = 0x0000FF0A;				// 255 sense bytes, 10-byte CDB!
+            msg[3] = lun << 8;
+            msg[4] = 0;
+            msg[5] = scsictl;
+
+            // 16 bytes of CDB @ msg[6,7,8,9] are below...
+
+            msg[6] = (   ((blkno & 0xFF000000) >> 8)
+                       | ((blkno & 0x00FF0000) << 8)
+                       | scsiop );
+            msg[7] = (   (((u32)kPerfInfo.nblks & 0x0000FF00) << 16)
+                       | ((blkno & 0x000000FF) << 8)
+                       | ((blkno & 0x0000FF00) >> 8) );
+            msg[8] = (kPerfInfo.nblks & 0x00FF);
+            msg[9] = 0;
+
+            msg[10] = xferbytes;
+
+//            msg[11] = 0xD0000100;
+//            msg[12] = sbphys;
+//            msg[13] = 0;
+            msg[11] = sbphys;
+
+            // Copy the SGL...
+            if (xferbytes) {
+                sgOut = (SGESimple32_t*)&msg[12];
+                sgIn  = sgl;
+                for (i=0; i < sgfragcpycnt; i++)
+                    *sgOut++ = *sgIn++;
+            }
+
+            // fubar!  QueueDepth issue!!!
+            while (    !rwperf_reset
+                    && (DevIosCount[targetM][lunM] >= MIN(qdepth,64)) )
+            {
+                mb();
+                schedule();
+                barrier();
+            }
+
+//            blkno += kPerfInfo.nblks;
+// EXP Stuff!
+// Try optimizing to certain cache size for the target!
+// by keeping blkno within cache range if at all possible
+#if 0
+            if (    cache_sz
+                 && ((2 * kPerfInfo.nblks) <= (cache_sz>>9))
+                 && ((blkno + kPerfInfo.nblks) > ((cache_sz>>9) + SACRED_BLOCKS)) )
+                blkno = SACRED_BLOCKS;
+            else
+                blkno += kPerfInfo.nblks;
+#endif
+// Ok, cheat!
+            if (cache_sz && ((blkno + kPerfInfo.nblks) > ((cache_sz>>9) + SACRED_BLOCKS)) )
+                   blkno = SACRED_BLOCKS;
+            else
+                blkno += kPerfInfo.nblks;
+
+            if (blkno > blkhi)
+                blkhi = blkno;
+
+            DevIosCount[targetM][lunM]++;
+
+            /*
+             *  Finally, post the request
+             */
+            mpt_put_msg_frame(mptctl_id, ioc, mf);
+
+
+            /* let linux breath! */
+            mb();
+            schedule();
+            barrier();
+
+            //dprintk((KERN_DEBUG MYNAM "-perf: inner-loop, cnt=%d\n", iters));
+
+        } while ((--iters > 0) && !rwperf_reset);
+
+        dprintk((KERN_INFO MYNAM "-perf: DbG: blklo=%d, blkhi=%d\n", blklo, blkhi));
+        dprintk((KERN_INFO MYNAM "-perf: target-loop, thisTarget=%d\n", target));
+
+//        //  TEMPORARY!
+//        target = 0;
+
+//    } while (target);
+
+
+    if (DevIosCount[targetM][lunM]) {
+        dprintk((KERN_INFO "  DbG: DevIosCount[%d][%d]=%d\n",
+                targetM, lunM, DevIosCount[targetM][lunM]));
+    }
+
+    while (DevIosCount[targetM][lunM]) {
+        //dprintk((KERN_DEBUG "  DbG: Waiting... DevIosCount[%d][%d]=%d\n",
+        //        targetM, lunM, DevIosCount[targetM][lunM]));
+        mb();
+        schedule();
+        barrier();
+    }
+    DevInUse[targetM][lunM] = 0;
+
+    pci_free_consistent(iocp->pcidev, 256, SenseBuf, SenseBufDMA);
+
+    if (sgl)
+        kfree_sgl(sgl, sgl_dma, buflist, iocp);
+
+    dprintk((KERN_INFO "  *** done ***\n"));
+
+    return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_rwperf_status(unsigned long arg)
+{
+	struct mpt_raw_r_w	 kPerfInfo;
+				/* NOTE: local copy, on stack==KERNEL_SPACE! */
+	MPT_ADAPTER	*iocp;
+	int		 ioc;
+//	u8		 targ;
+//	u8		 lun;
+	int		 T, L;
+	char		*myname = "_rwperf_status()";
+
+
+	dprintk((KERN_INFO "%s - starting...\n", myname));
+
+	/* Get a pointer to the MPT adapter. */
+	if ((ioc = mpt_ioctl_rwperf_init(&kPerfInfo, arg, myname, &iocp)) < 0)
+		return ioc;
+
+	/* set perf parameters from input */
+//	targ = kPerfInfo.target & 0xFF;
+//	lun = kPerfInfo.lun & 0x1F;
+
+	for (T=0; T < myMAX_TARGETS; T++)
+		for (L=0; L < myMAX_LUNS; L++)
+			if (DevIosCount[T][L]) {
+				printk(KERN_INFO "%s: ioc%d->00:%02x:%02x"
+						 ", IosCnt=%d\n",
+						 myname, ioc, T, L, DevIosCount[T][L] );
+			}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_rwperf_reset(unsigned long arg)
+{
+	struct mpt_raw_r_w	 kPerfInfo;
+				/* NOTE: local copy, on stack==KERNEL_SPACE! */
+	MPT_ADAPTER	*iocp;
+	int		 ioc;
+//	u8		 targ;
+//	u8		 lun;
+	int		 T, L;
+	int		 i;
+	char		*myname = "_rwperf_reset()";
+
+	dprintk((KERN_INFO "%s - starting...\n", myname));
+
+	/* Get MPT adapter id. */
+	if ((ioc = mpt_ioctl_rwperf_init(&kPerfInfo, arg, myname, &iocp)) < 0)
+		return ioc;
+
+	/* set perf parameters from input */
+//	targ = kPerfInfo.target & 0xFF;
+//	lun = kPerfInfo.lun & 0x1F;
+
+	rwperf_reset = 1;
+	for (i=0; i < 1000000; i++) {
+		mb();
+		schedule();
+		barrier();
+	}
+	rwperf_reset = 0;
+
+	for (T=0; T < myMAX_TARGETS; T++)
+		for (L=0; L < myMAX_LUNS; L++)
+			if (DevIosCount[T][L]) {
+				printk(KERN_INFO "%s: ioc%d->00:%02x:%02x, "
+						 "IosCnt RESET! (from %d to 0)\n",
+						 myname, ioc, T, L, DevIosCount[T][L] );
+				DevIosCount[T][L] = 0;
+				DevInUse[T][L] = 0;
+			}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_ioctl_scsi_cmd(unsigned long arg)
+{
+	return -ENOSYS;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static struct file_operations mptctl_fops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
+	owner:		THIS_MODULE,
+#endif
+	llseek:		mptctl_llseek,
+	read:		mptctl_read,
+	write:		mptctl_write,
+	ioctl:		mpt_ioctl,
+	open:		mptctl_open,
+	release:	mptctl_release,
+};
+
+static struct miscdevice mptctl_miscdev = {
+	MPT_MINOR,
+	MYNAM,
+	&mptctl_fops
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#if defined(__sparc__) && defined(__sparc_v9__)		/*{*/
+
+/* The dynamic ioctl32 compat. registry only exists in >2.3.x sparc64 kernels */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)		/*{*/
+extern int register_ioctl32_conversion(unsigned int cmd,
+				       int (*handler)(unsigned int,
+						      unsigned int,
+						      unsigned long,
+						      struct file *));
+int unregister_ioctl32_conversion(unsigned int cmd);
+
+struct mpt_fw_xfer32 {
+	unsigned int iocnum;
+	unsigned int fwlen;
+	u32 bufp;
+};
+
+#define MPTFWDOWNLOAD32     _IOWR(MPT_MAGIC_NUMBER,15,struct mpt_fw_xfer32)
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+sparc32_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
+			unsigned long arg, struct file *filp)
+{
+	struct mpt_fw_xfer32 kfw32;
+	struct mpt_fw_xfer kfw;
+	MPT_ADAPTER *iocp = NULL;
+	int iocnum, iocnumX;
+	int nonblock = (filp->f_flags & O_NONBLOCK);
+	int ret;
+
+	dprintk((KERN_INFO MYNAM "::sparc32_mptfwxfer_ioctl() called\n"));
+
+	if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32)))
+		return -EFAULT;
+
+	/* Verify intended MPT adapter */
+	iocnumX = kfw32.iocnum & 0xFF;
+	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+	    (iocp == NULL)) {
+		printk(KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n",
+				__LINE__, iocnumX);
+		return -ENODEV;
+	}
+
+	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+		return ret;
+
+	kfw.iocnum = iocnum;
+	kfw.fwlen = kfw32.fwlen;
+	kfw.bufp = (void *)(unsigned long)kfw32.bufp;
+
+	ret = mpt_ioctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
+
+	up(&mptctl_syscall_sem_ioc[iocp->id]);
+
+	return ret;
+}
+
+#if 0		/* { */
+static int
+sparc32_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
+			unsigned long arg, struct file *filp)
+{
+	struct mpt_fw_xfer32 kfw32;
+	struct mpt_fw_xfer kfw;
+	mm_segment_t old_fs;
+	int ret;
+
+	dprintk((KERN_INFO MYNAM "::sparc32_mptfwxfer_ioctl() called\n"));
+
+	if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32)))
+		return -EFAULT;
+
+	/* Verify intended MPT adapter */
+	iocnumX = kfw32.iocnum & 0xFF;
+	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+	    (iocp == NULL)) {
+		printk(KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n",
+				__LINE__, iocnumX);
+		return -ENODEV;
+	}
+
+	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+		return ret;
+
+	kfw.iocnum = iocnum;
+	kfw.fwlen = kfw32.fwlen;
+	kfw.bufp = (void *)(unsigned long)kfw32.bufp;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, MPTFWDOWNLOAD, (unsigned long)&kfw);
+	set_fs(old_fs);
+
+	up(&mptctl_syscall_sem_ioc[iocp->id]);
+
+	return ret;
+}
+#endif		/* #if 0 } */
+
+#endif		/*} linux >= 2.3.x */
+#endif		/*} sparc */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int __init mptctl_init(void)
+{
+	int err;
+	int i;
+	int where = 1;
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
+		sema_init(&mptctl_syscall_sem_ioc[i], 1);
+	}
+
+#if defined(__sparc__) && defined(__sparc_v9__)		/*{*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)		/*{*/
+	err = register_ioctl32_conversion(MPTRWPERF, NULL);
+	if (++where && err) goto out_fail;
+	err = register_ioctl32_conversion(MPTRWPERF_CHK, NULL);
+	if (++where && err) goto out_fail;
+	err = register_ioctl32_conversion(MPTRWPERF_RESET, NULL);
+	if (++where && err) goto out_fail;
+	err = register_ioctl32_conversion(MPTFWDOWNLOAD32,
+					  sparc32_mptfwxfer_ioctl);
+	if (++where && err) goto out_fail;
+#endif		/*} linux >= 2.3.x */
+#endif		/*} sparc */
+
+	if (misc_register(&mptctl_miscdev) == -1) {
+		printk(KERN_ERR MYNAM ": Can't register misc device [minor=%d].\n", MPT_MINOR);
+		err = -EBUSY;
+		goto out_fail;
+	}
+	printk(KERN_INFO MYNAM ": Registered with Fusion MPT base driver\n");
+	printk(KERN_INFO MYNAM ": /dev/%s @ (major,minor=%d,%d)\n",
+			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
+
+	/*
+	 *  Install our handler
+	 */
+	++where;
+	if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) {
+		printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
+		misc_deregister(&mptctl_miscdev);
+		err = -EBUSY;
+		goto out_fail;
+	}
+
+	return 0;
+
+out_fail:
+
+#if defined(__sparc__) && defined(__sparc_v9__)		/*{*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)		/*{*/
+	printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!"
+			" (%d:err=%d)\n", where, err);
+	unregister_ioctl32_conversion(MPTRWPERF);
+	unregister_ioctl32_conversion(MPTRWPERF_CHK);
+	unregister_ioctl32_conversion(MPTRWPERF_RESET);
+	unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
+#endif		/*} linux >= 2.3.x */
+#endif		/*} sparc */
+
+	return err;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+void mptctl_exit(void)
+{
+	misc_deregister(&mptctl_miscdev);
+	printk(KERN_INFO MYNAM ": /dev/%s @ (major,minor=%d,%d)\n",
+			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
+	printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
+
+	mpt_deregister(mptctl_id);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+module_init(mptctl_init);
+module_exit(mptctl_exit);
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptlan.c linux/drivers/message/fusion/mptlan.c
--- linux-2.4.7-pre3/drivers/message/fusion/mptlan.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptlan.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,1462 @@
+/*
+ *  linux/drivers/message/fusion/mptlan.c
+ *      IP Over Fibre Channel device driver.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *      This driver would not exist if not for Alan Cox's development
+ *      of the linux i2o driver.
+ *
+ *      Special thanks goes to the I2O LAN driver people at the
+ *      University of Helsinki, who, unbeknownst to them, provided
+ *      the inspiration and initial structure for this driver.
+ *
+ *      A huge debt of gratitude is owed to David S. Miller (DaveM)
+ *      for fixing much of the stupid and broken stuff in the early
+ *      driver while porting to sparc64 platform.  THANK YOU!
+ *
+ *      A really huge debt of gratitude is owed to Eddie C. Dost
+ *      for gobs of hard work fixing and optimizing LAN code.
+ *      THANK YOU!
+ *
+ *      (see also mptbase.c)
+ *
+ *  Copyright (c) 2000-2001 LSI Logic Corporation
+ *  Originally By: Noah Romer
+ *
+ *  $Id: mptlan.c,v 1.25 2001/03/02 22:12:04 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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
+*/
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * Define statements used for debugging
+ */
+//#define MPT_LAN_IO_DEBUG
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include "mptlan.h"
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#define MYNAM		"mptlan"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * MPT LAN message sizes without variable part.
+ */
+#define MPT_LAN_RECEIVE_POST_REQUEST_SIZE \
+	(sizeof(LANReceivePostRequest_t) - sizeof(SGE_MPI_UNION))
+
+#define MPT_LAN_TRANSACTION32_SIZE \
+	(sizeof(SGETransaction32_t) - sizeof(u32))
+
+/*
+ *  Fusion MPT LAN private structures
+ */
+
+struct BufferControl {
+	struct sk_buff	*skb;
+	dma_addr_t	dma;
+	unsigned int	len;
+};
+
+struct mpt_lan_priv {
+	MPT_ADAPTER *mpt_dev;
+	u8 pnum; /* Port number in the IOC. This is not a Unix network port! */
+
+	atomic_t buckets_out;	  	/* number of unused buckets on IOC */
+	int bucketthresh;		/* Send more when this many used */
+
+	int *mpt_txfidx; /* Free Tx Context list */
+	int mpt_txfidx_tail;
+	spinlock_t txfidx_lock;
+
+	int *mpt_rxfidx; /* Free Rx Context list */
+	int mpt_rxfidx_tail;
+	spinlock_t rxfidx_lock;
+
+	struct BufferControl *RcvCtl;	/* Receive BufferControl structs */
+	struct BufferControl *SendCtl;	/* Send BufferControl structs */
+
+	int max_buckets_out;	   	/* Max buckets to send to IOC */
+	int tx_max_out;		   	/* IOC's Tx queue len */
+
+	u32 total_posted;
+	u32 total_received;
+	struct net_device_stats stats;	/* Per device statistics */
+
+	struct tq_struct post_buckets_task;
+	unsigned long post_buckets_active;
+};
+
+struct mpt_lan_ohdr {
+	u16	dtype;
+	u8	daddr[FC_ALEN];
+	u16	stype;
+	u8	saddr[FC_ALEN];
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ *  Forward protos...
+ */
+static int  lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
+		       MPT_FRAME_HDR *reply);
+static int  mpt_lan_open(struct net_device *dev);
+static int  mpt_lan_reset(struct net_device *dev);
+static int  mpt_lan_close(struct net_device *dev);
+static void mpt_lan_post_receive_buckets(void *dev_id);
+static void mpt_lan_wake_post_buckets_task(struct net_device *dev);
+static int  mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg);
+static int  mpt_lan_receive_post_reply(struct net_device *dev,
+				       LANReceivePostReply_t *pRecvRep);
+static int  mpt_lan_send_turbo(struct net_device *dev, u32 tmsg);
+static int  mpt_lan_send_reply(struct net_device *dev,
+			       LANSendReply_t *pSendRep);
+static int  mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+static unsigned short mpt_lan_type_trans(struct sk_buff *skb,
+					 struct net_device *dev);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Fusion MPT LAN private data
+ */
+static int LanCtx = -1;
+
+static u32 max_buckets_out = 127;
+static u32 tx_max_out_p = 127 - 16;
+
+static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1];
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * Fusion MPT LAN external data
+ */
+extern int mpt_lan_index;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	lan_reply - Handle all data sent from the hardware.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@mf: Pointer to original MPT request frame (NULL if TurboReply)
+ *	@reply: Pointer to MPT reply frame
+ *
+ *	Returns 1 indicating original alloc'd request frame ptr
+ *	should be freed, or 0 if it shouldn't.
+ */
+static int
+lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
+{
+	struct net_device *dev = mpt_landev[ioc->id];
+	int FreeReqFrame = 0;
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
+		  IOC_AND_NETDEV_NAMES_s_s(dev)));
+
+//	dioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n",
+//			mf, reply));
+
+	if (mf == NULL) {
+		u32 tmsg = CAST_PTR_TO_U32(reply);
+
+		dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev),
+				tmsg));
+
+		switch (GET_LAN_FORM(tmsg)) {
+
+		// NOTE!  (Optimization) First case here is now caught in
+		//  mptbase.c::mpt_interrupt() routine and callcack here
+		//  is now skipped for this case!  20001218 -sralston
+#if 0
+		case LAN_REPLY_FORM_MESSAGE_CONTEXT:
+//			dioprintk((KERN_INFO MYNAM "/lan_reply: "
+//				  "MessageContext turbo reply received\n"));
+			FreeReqFrame = 1;
+			break;
+#endif
+
+		case LAN_REPLY_FORM_SEND_SINGLE:
+//			dioprintk((MYNAM "/lan_reply: "
+//				  "calling mpt_lan_send_reply (turbo)\n"));
+  
+			// Potential BUG here?  -sralston
+			//	FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
+			//  If/when mpt_lan_send_turbo would return 1 here,
+			//  calling routine (mptbase.c|mpt_interrupt)
+			//  would Oops because mf has already been set
+			//  to NULL.  So after return from this func,
+			//  mpt_interrupt() will attempt to put (NULL) mf ptr
+			//  item back onto it's adapter FreeQ - Oops!:-(
+			//  It's Ok, since mpt_lan_send_turbo() *currently*
+			//  always returns 0, but..., just in case:
+
+			(void) mpt_lan_send_turbo(dev, tmsg);
+			FreeReqFrame = 0;
+
+			break;
+
+		case LAN_REPLY_FORM_RECEIVE_SINGLE:
+//			dioprintk((KERN_INFO MYNAM "@lan_reply: "
+//				  "rcv-Turbo = %08x\n", tmsg));
+			mpt_lan_receive_post_turbo(dev, tmsg);
+			break;
+
+		default:
+			printk (KERN_ERR MYNAM "/lan_reply: Got a turbo reply "
+				"that I don't know what to do with\n");
+
+			/* CHECKME!  Hmmm...  FreeReqFrame is 0 here; is that right? */
+
+			break;
+		}
+
+		return FreeReqFrame;
+	}
+
+//	msg = (u32 *) reply;
+//	dioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n",
+//		  le32_to_cpu(msg[0]), le32_to_cpu(msg[1]),
+//		  le32_to_cpu(msg[2]), le32_to_cpu(msg[3])));
+//	dioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n",
+//		  reply->u.hdr.Function));
+
+	switch (reply->u.hdr.Function) {
+
+	case MPI_FUNCTION_LAN_SEND:
+	{
+		LANSendReply_t *pSendRep;
+
+		pSendRep = (LANSendReply_t *) reply;
+		FreeReqFrame = mpt_lan_send_reply(dev, pSendRep);
+		break;
+	}
+
+	case MPI_FUNCTION_LAN_RECEIVE:
+	{
+		LANReceivePostReply_t *pRecvRep;
+
+		pRecvRep = (LANReceivePostReply_t *) reply;
+		if (pRecvRep->NumberOfContexts) {
+			mpt_lan_receive_post_reply(dev, pRecvRep);
+			if (!(pRecvRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY))
+				FreeReqFrame = 1;
+		} else
+			dioprintk((KERN_INFO MYNAM "@lan_reply: zero context "
+				  "ReceivePostReply received.\n"));
+		break;
+	}
+
+	case MPI_FUNCTION_LAN_RESET:
+		/* Just a default reply. Might want to check it to
+		 * make sure that everything went ok.
+		 */
+		FreeReqFrame = 1;
+		break;
+
+	case MPI_FUNCTION_EVENT_NOTIFICATION:
+	case MPI_FUNCTION_EVENT_ACK:
+		/* UPDATE!  20010120 -sralston
+		 *  _EVENT_NOTIFICATION should NOT come down this path any more.
+		 *  Should be routed to mpt_lan_event_process(), but just in case...
+		 */
+		FreeReqFrame = 1;
+		break;
+
+	default:
+		printk (KERN_ERR MYNAM "/lan_reply: Got a non-turbo "
+			"reply that I don't know what to do with\n");
+
+		/* CHECKME!  Hmmm...  FreeReqFrame is 0 here; is that right? */
+		FreeReqFrame = 1;
+
+		break;
+	}
+
+	return FreeReqFrame;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+	dprintk((KERN_INFO MYNAM ": MPT event routed to LAN driver!\n"));
+
+	switch (le32_to_cpu(pEvReply->Event)) {
+	case MPI_EVENT_NONE:				/* 00 */
+	case MPI_EVENT_LOG_DATA:			/* 01 */
+	case MPI_EVENT_STATE_CHANGE:			/* 02 */
+	case MPI_EVENT_UNIT_ATTENTION:			/* 03 */
+	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
+	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
+	case MPI_EVENT_RESCAN:				/* 06 */
+		/* Ok, do we need to do anything here? As far as
+		   I can tell, this is when a new device gets added
+		   to the loop. */
+	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
+	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
+	case MPI_EVENT_LOGOUT:				/* 09 */
+	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
+	default:
+		break;
+	}
+
+	/*
+	 *  NOTE: pEvent->AckRequired handling now done in mptbase.c;
+	 *  Do NOT do it here now!
+	 */
+
+	return 1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_open(struct net_device *dev)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv;
+	int i;
+
+	mpt_lan_reset(dev);
+
+	priv->mpt_txfidx = kmalloc(priv->tx_max_out * sizeof(int), GFP_KERNEL);
+	if (priv->mpt_txfidx == NULL)
+		goto out;
+	priv->mpt_txfidx_tail = -1;
+
+	priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+				GFP_KERNEL);
+	if (priv->SendCtl == NULL)
+		goto out_mpt_txfidx;
+	for (i = 0; i < priv->tx_max_out; i++) {
+		memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+		priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
+	}
+
+	dprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
+
+	priv->mpt_rxfidx = kmalloc(priv->max_buckets_out * sizeof(int),
+				   GFP_KERNEL);
+	if (priv->mpt_rxfidx == NULL)
+		goto out_SendCtl;
+	priv->mpt_rxfidx_tail = -1;
+
+	priv->RcvCtl = kmalloc(priv->max_buckets_out *
+						sizeof(struct BufferControl),
+			       GFP_KERNEL);
+	if (priv->RcvCtl == NULL)
+		goto out_mpt_rxfidx;
+	for (i = 0; i < priv->max_buckets_out; i++) {
+		memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+		priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
+	}
+
+/**/	dprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
+/**/	for (i = 0; i < priv->tx_max_out; i++)
+/**/		dprintk((" %xh", priv->mpt_txfidx[i]));
+/**/	dprintk(("\n"));
+
+	dprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n"));
+
+	mpt_lan_post_receive_buckets(dev);
+	printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev));
+
+	if (mpt_event_register(LanCtx, mpt_lan_event_process) != 0) {
+		/* FIXME! */
+	}
+
+	netif_start_queue(dev);
+	dprintk((KERN_INFO MYNAM "/lo: Done.\n"));
+
+	return 0;
+out_mpt_rxfidx:
+	kfree(priv->mpt_rxfidx);
+	priv->mpt_rxfidx = NULL;
+out_SendCtl:
+	kfree(priv->SendCtl);
+	priv->SendCtl = NULL;
+out_mpt_txfidx:
+	kfree(priv->mpt_txfidx);
+	priv->mpt_txfidx = NULL;
+out:	return -ENOMEM;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_reset(struct net_device *dev)
+{
+	MPT_FRAME_HDR *mf;
+	LANResetRequest_t *pResetReq;
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *)dev->priv;
+
+	mf = mpt_get_msg_frame(LanCtx, priv->mpt_dev->id);
+
+	if (mf == NULL) {
+/*		dprintk((KERN_ERR MYNAM "/reset: Evil funkiness abounds! "
+		"Unable to allocate a request frame.\n"));
+*/
+		return -1;
+	}
+
+	pResetReq = (LANResetRequest_t *) mf;
+
+	pResetReq->Function	= MPI_FUNCTION_LAN_RESET;
+	pResetReq->ChainOffset	= 0;
+	pResetReq->Reserved	= 0;
+	pResetReq->PortNumber	= priv->pnum;
+	pResetReq->MsgFlags	= 0;
+	pResetReq->Reserved2	= 0;
+
+	mpt_put_msg_frame(LanCtx, priv->mpt_dev->id, mf);
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_close(struct net_device *dev)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	unsigned int timeout;
+	int i;
+
+	dprintk((KERN_INFO MYNAM ": mpt_lan_close called\n"));
+
+	mpt_event_deregister(LanCtx);
+
+	dprintk((KERN_INFO MYNAM ":lan_close: Posted %d buckets "
+		  "since driver was loaded, %d still out\n",
+		  priv->total_posted,atomic_read(&priv->buckets_out)));
+
+	netif_stop_queue(dev);
+
+	mpt_lan_reset(dev);
+
+	timeout = 2 * HZ;
+	while (atomic_read(&priv->buckets_out) && --timeout) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+
+	for (i = 0; i < priv->max_buckets_out; i++) {
+		if (priv->RcvCtl[i].skb != NULL) {
+/**/			dprintk((KERN_INFO MYNAM "/lan_close: bucket %05x "
+/**/				  "is still out\n", i));
+			pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[i].dma,
+				 	 priv->RcvCtl[i].len,
+					 PCI_DMA_FROMDEVICE);
+ 			dev_kfree_skb(priv->RcvCtl[i].skb);
+		}
+	}
+
+	kfree (priv->RcvCtl);
+	kfree (priv->mpt_rxfidx);
+
+	for (i = 0; i < priv->tx_max_out; i++) {
+ 		if (priv->SendCtl[i].skb != NULL) {
+			pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[i].dma,
+					 priv->SendCtl[i].len,
+					 PCI_DMA_TODEVICE);
+ 			dev_kfree_skb(priv->SendCtl[i].skb);
+		}
+	}
+
+	kfree(priv->SendCtl);
+	kfree(priv->mpt_txfidx);
+
+	atomic_set(&priv->buckets_out, 0);
+
+	printk(KERN_INFO MYNAM ": %s/%s: interface down & inactive\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev));
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static struct net_device_stats *
+mpt_lan_get_stats(struct net_device *dev)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *)dev->priv;
+
+	return (struct net_device_stats *) &priv->stats;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* Tx timeout handler. */
+static void
+mpt_lan_tx_timeout(struct net_device *dev)
+{
+	netif_wake_queue(dev);  
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+//static inline int
+static int
+mpt_lan_send_turbo(struct net_device *dev, u32 tmsg)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	struct sk_buff *sent;
+	unsigned long flags;
+	u32 ctx;
+
+	ctx = GET_LAN_BUFFER_CONTEXT(tmsg);
+	sent = priv->SendCtl[ctx].skb;
+
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += sent->len;
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev),
+			__FUNCTION__, sent));
+
+	priv->SendCtl[ctx].skb = NULL;
+	pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
+			 priv->SendCtl[ctx].len, PCI_DMA_TODEVICE);
+	dev_kfree_skb_irq(sent);
+
+	spin_lock_irqsave(&priv->txfidx_lock, flags);
+	priv->mpt_txfidx[++priv->mpt_txfidx_tail] = ctx;
+	spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+
+	netif_wake_queue(dev);
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	struct sk_buff *sent;
+	unsigned long flags;
+	int FreeReqFrame = 0;
+	u32 *pContext;
+	u32 ctx;
+	u8 count;
+
+	count = pSendRep->NumberOfContexts;
+
+	dioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n",
+		 le16_to_cpu(pSendRep->IOCStatus)));
+
+	/* Add check for Loginfo Flag in IOCStatus */
+
+	switch (le16_to_cpu(pSendRep->IOCStatus)) {
+	case MPI_IOCSTATUS_SUCCESS:
+		priv->stats.tx_packets += count;
+		break;
+
+	case MPI_IOCSTATUS_LAN_CANCELED:
+	case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED:
+		break;
+
+	case MPI_IOCSTATUS_INVALID_SGL:
+		priv->stats.tx_errors += count;
+		printk (KERN_ERR MYNAM ": %s/%s: ERROR - Invalid SGL sent to IOC!\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev));
+		goto out;
+
+	default:
+		priv->stats.tx_errors += count;
+		break;
+	}
+
+	pContext = &pSendRep->BufferContext;
+
+	spin_lock_irqsave(&priv->txfidx_lock, flags);
+	while (count > 0) {
+		ctx = GET_LAN_BUFFER_CONTEXT(le32_to_cpu(*pContext));
+
+		sent = priv->SendCtl[ctx].skb;
+		priv->stats.tx_bytes += sent->len;
+
+		dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev),
+				__FUNCTION__, sent));
+
+		priv->SendCtl[ctx].skb = NULL;
+		pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
+				 priv->SendCtl[ctx].len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(sent);
+
+		priv->mpt_txfidx[++priv->mpt_txfidx_tail] = ctx;
+
+		pContext++;
+		count--;
+	}
+	spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+
+out:
+	if (!(pSendRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY))
+		FreeReqFrame = 1;
+
+	netif_wake_queue(dev);
+	return FreeReqFrame;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
+{
+	struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	MPT_FRAME_HDR *mf;
+	LANSendRequest_t *pSendReq;
+	SGETransaction32_t *pTrans;
+	SGESimple64_t *pSimple;
+	dma_addr_t dma;
+	unsigned long flags;
+	int ctx;
+
+	dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
+			__FUNCTION__, skb));
+
+	spin_lock_irqsave(&priv->txfidx_lock, flags);
+	if (priv->mpt_txfidx_tail < 0) {
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+
+		printk (KERN_ERR "%s: no tx context available: %u\n",
+			__FUNCTION__, priv->mpt_txfidx_tail);
+		return 1;
+	}
+
+	mf = mpt_get_msg_frame(LanCtx, mpt_dev->id);
+	if (mf == NULL) {
+		netif_stop_queue(dev);
+		dev_kfree_skb(skb);
+		spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+
+		printk (KERN_ERR "%s: Unable to alloc request frame\n",
+			__FUNCTION__);
+		return 1;
+	}
+
+	ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--];
+	spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+
+//	dioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n",
+//			IOC_AND_NETDEV_NAMES_s_s(dev)));
+
+	pSendReq = (LANSendRequest_t *) mf;
+
+	/* Set the mac.raw pointer, since this apparently isn't getting
+	 * done before we get the skb. Pull the data pointer past the mac data.
+	 */
+	skb->mac.raw = skb->data;
+	skb_pull(skb, 12);
+
+        dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
+			     PCI_DMA_TODEVICE);
+
+	priv->SendCtl[ctx].skb = skb;
+	priv->SendCtl[ctx].dma = dma;
+	priv->SendCtl[ctx].len = skb->len;
+
+	/* Message Header */
+	pSendReq->Function    = MPI_FUNCTION_LAN_SEND;
+	pSendReq->ChainOffset = 0;
+	pSendReq->MsgFlags    = 0;
+	pSendReq->PortNumber  = priv->pnum;
+
+	/* Transaction Context Element */
+	pTrans = (SGETransaction32_t *) pSendReq->SG_List;
+
+	/* No Flags, 8 bytes of Details, 32bit Context (bloody turbo replies) */
+	pTrans->ContextSize   = sizeof(u32);
+	pTrans->DetailsLength = 2 * sizeof(u32);
+	pTrans->Flags         = 0;
+	pTrans->TransactionContext[0] = cpu_to_le32(ctx);
+
+//	dioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n",
+//			IOC_AND_NETDEV_NAMES_s_s(dev),
+//			ctx, skb, skb->data));
+
+	pTrans->TransactionDetails[0] = cpu_to_le32((0x1000          << 16) |
+						    (skb->mac.raw[0] <<  8) |
+						    (skb->mac.raw[1] <<  0));
+	pTrans->TransactionDetails[1] = cpu_to_le32((skb->mac.raw[2] << 24) |
+						    (skb->mac.raw[3] << 16) |
+						    (skb->mac.raw[4] <<  8) |
+						    (skb->mac.raw[5] <<  0));
+
+	pSimple = (SGESimple64_t *) &pTrans->TransactionDetails[2];
+
+	pSimple->FlagsLength = cpu_to_le32(
+			((MPI_SGE_FLAGS_END_OF_BUFFER |
+			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+			  MPI_SGE_FLAGS_64_BIT_ADDRESSING |
+			  MPI_SGE_FLAGS_END_OF_LIST) << MPI_SGE_FLAGS_SHIFT) |
+			skb->len);
+	pSimple->Address.Low = cpu_to_le32((u32) dma);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		pSimple->Address.High = cpu_to_le32((u32) ((u64) dma >> 32));
+	else
+		pSimple->Address.High = 0;
+
+	mpt_put_msg_frame (LanCtx, mpt_dev->id, mf);
+	dev->trans_start = jiffies;
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n",
+		 	IOC_AND_NETDEV_NAMES_s_s(dev),
+		       	le32_to_cpu(pSimple->FlagsLength)));
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static inline void
+mpt_lan_wake_post_buckets_task(struct net_device *dev)
+{
+	struct mpt_lan_priv *priv = dev->priv;
+
+	if (test_and_set_bit(0, &priv->post_buckets_active) == 0) {
+		queue_task(&priv->post_buckets_task, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+		dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev) ));
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static inline int
+mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb)
+{
+	struct mpt_lan_priv *priv = dev->priv;
+
+	skb->protocol = mpt_lan_type_trans(skb, dev);
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) " 
+		 "delivered to upper level.\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev), skb->len));
+
+	priv->stats.rx_bytes += skb->len;
+	priv->stats.rx_packets++;
+
+	skb->dev = dev;
+	netif_rx(skb);
+
+	dioprintk((MYNAM "/receive_skb: %d buckets remaining\n",
+		 atomic_read(&priv->buckets_out)));
+
+	if (atomic_read(&priv->buckets_out) < priv->bucketthresh)
+		mpt_lan_wake_post_buckets_task(dev);
+
+	dioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets "
+		  "remaining, %d received back since sod\n",
+		  atomic_read(&priv->buckets_out), priv->total_received));
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+//static inline int
+static int
+mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg)
+{
+	struct mpt_lan_priv *priv = dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	struct sk_buff *skb, *old_skb;
+	unsigned long flags;
+	u32 ctx, len;
+
+	ctx = GET_LAN_BUCKET_CONTEXT(tmsg);
+	skb = priv->RcvCtl[ctx].skb;
+
+	len = GET_LAN_PACKET_LENGTH(tmsg);
+
+	if (len < MPT_LAN_RX_COPYBREAK) {
+		old_skb = skb;
+
+		skb = (struct sk_buff *)dev_alloc_skb(len);
+		if (!skb) {
+			printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n",
+					IOC_AND_NETDEV_NAMES_s_s(dev),
+					__FILE__, __LINE__);
+			return -ENOMEM;
+		}
+
+		pci_dma_sync_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma,
+				    priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE);
+
+		memcpy(skb_put(skb, len), old_skb->data, len);
+
+		goto out;
+	}
+
+	skb_put(skb, len);
+
+	priv->RcvCtl[ctx].skb = NULL;
+
+	pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma,
+			 priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE);
+
+out:
+	spin_lock_irqsave(&priv->rxfidx_lock, flags);
+	priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+	spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+	atomic_dec(&priv->buckets_out);
+	priv->total_received++;
+
+	return mpt_lan_receive_skb(dev, skb);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_receive_post_free(struct net_device *dev,
+			  LANReceivePostReply_t *pRecvRep)
+{
+	struct mpt_lan_priv *priv = dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	unsigned long flags;
+	struct sk_buff *skb;
+	u32 ctx;
+	u8 count;
+	int i;
+
+	count = pRecvRep->NumberOfContexts;
+
+/**/	dprintk((KERN_INFO MYNAM "/receive_post_reply: "
+		  "IOC returned %d buckets, freeing them...\n", count));
+
+	spin_lock_irqsave(&priv->rxfidx_lock, flags);
+	for (i = 0; i < count; i++) {
+		ctx = le32_to_cpu(pRecvRep->BucketContext[i]);
+
+		skb = priv->RcvCtl[ctx].skb;
+
+//		dprintk((KERN_INFO MYNAM ": %s: dev_name = %s\n",
+//				IOC_AND_NETDEV_NAMES_s_s(dev)));
+//		dprintk((KERN_INFO MYNAM "@rpr[2], priv = %p, buckets_out addr = %p",
+//			  	priv, &(priv->buckets_out)));
+//		dprintk((KERN_INFO MYNAM "@rpr[2] TC + 3\n"));
+
+		priv->RcvCtl[ctx].skb = NULL;
+		pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma,
+				 priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+
+		priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+	}
+	spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+	atomic_sub(count, &priv->buckets_out);
+
+//	for (i = 0; i < priv->max_buckets_out; i++)
+//		if (priv->RcvCtl[i].skb != NULL)
+//			dprintk((KERN_INFO MYNAM "@rpr: bucket %03x "
+//				  "is still out\n", i));
+
+/*	dprintk((KERN_INFO MYNAM "/receive_post_reply: freed %d buckets\n",
+		  count));
+*/
+/**/	dprintk((KERN_INFO MYNAM "@receive_post_reply: %d buckets "
+/**/		  "remaining, %d received back since sod.\n",
+/**/		  atomic_read(&priv->buckets_out), priv->total_received));
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mpt_lan_receive_post_reply(struct net_device *dev,
+			   LANReceivePostReply_t *pRecvRep)
+{
+	struct mpt_lan_priv *priv = dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	struct sk_buff *skb, *old_skb;
+	unsigned long flags;
+	u32 len, ctx;
+	u32 offset;
+	u8 count;
+	int i, l;
+
+	dioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n"));
+	dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n",
+		 le16_to_cpu(pRecvRep->IOCStatus)));
+
+	if (le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_LAN_CANCELED)
+		return mpt_lan_receive_post_free(dev, pRecvRep);
+
+	len = le32_to_cpu(pRecvRep->PacketLength);
+	if (len == 0) {
+		printk (KERN_ERR MYNAM ": %s/%s: ERROR - Got a non-TURBO "
+			"ReceivePostReply w/ PacketLength zero!\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev));
+		printk (KERN_ERR MYNAM ": MsgFlags = %02x, IOCStatus = %04x\n",
+				pRecvRep->MsgFlags, le16_to_cpu(pRecvRep->IOCStatus));
+		return -1;
+	}
+
+	ctx    = le32_to_cpu(pRecvRep->BucketContext[0]);
+	count  = pRecvRep->NumberOfContexts;
+	skb    = priv->RcvCtl[ctx].skb;
+
+	offset = le32_to_cpu(pRecvRep->PacketOffset);
+//	if (offset != 0) {
+//		printk (KERN_INFO MYNAM ": %s/%s: Got a ReceivePostReply "
+//			"w/ PacketOffset %u\n",
+//				IOC_AND_NETDEV_NAMES_s_s(dev),
+//				offset);
+//	}
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev),
+			offset, len));
+
+	if (count > 1) {
+		int szrem = len;
+
+//		dioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned "
+//			"for single packet, concatenating...\n",
+//				IOC_AND_NETDEV_NAMES_s_s(dev)));
+
+		skb = (struct sk_buff *)dev_alloc_skb(len);
+		if (!skb) {
+			printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n",
+					IOC_AND_NETDEV_NAMES_s_s(dev),
+			       		__FILE__, __LINE__);
+			return -ENOMEM;
+		}
+
+		spin_lock_irqsave(&priv->rxfidx_lock, flags);
+		for (i = 0; i < count; i++) {
+
+			ctx = le32_to_cpu(pRecvRep->BucketContext[i]);
+			old_skb = priv->RcvCtl[ctx].skb;
+
+			l = priv->RcvCtl[ctx].len;
+			if (szrem < l)
+				l = szrem;
+
+//			dioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n",
+//					IOC_AND_NETDEV_NAMES_s_s(dev),
+//					i, l));
+
+			pci_dma_sync_single(mpt_dev->pcidev,
+					    priv->RcvCtl[ctx].dma,
+					    priv->RcvCtl[ctx].len,
+					    PCI_DMA_FROMDEVICE);
+			memcpy(skb_put(skb, l), old_skb->data, l);
+
+			priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+			szrem -= l;
+		}
+		spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+	} else if (len < MPT_LAN_RX_COPYBREAK) {
+
+		old_skb = skb;
+
+		skb = (struct sk_buff *)dev_alloc_skb(len);
+		if (!skb) {
+			printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n",
+					IOC_AND_NETDEV_NAMES_s_s(dev),
+			       		__FILE__, __LINE__);
+			return -ENOMEM;
+		}
+
+		pci_dma_sync_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma,
+				    priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE);
+
+		memcpy(skb_put(skb, len), old_skb->data, len);
+
+		spin_lock_irqsave(&priv->rxfidx_lock, flags);
+		priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+		spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+	} else {
+		spin_lock_irqsave(&priv->rxfidx_lock, flags);
+
+		priv->RcvCtl[ctx].skb = NULL;
+
+		pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma,
+				 priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE);
+		priv->RcvCtl[ctx].dma = 0;
+
+		priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+		spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+		skb_put(skb,len);
+	}
+
+	atomic_sub(count, &priv->buckets_out);
+	priv->total_received += count;
+
+	if (priv->mpt_rxfidx_tail >= MPT_LAN_MAX_BUCKETS_OUT) {
+		printk (KERN_ERR MYNAM ": %s/%s: Yoohoo! mpt_rxfidx_tail = %d, "
+			"MPT_LAN_MAX_BUCKETS_OUT = %d\n",
+				IOC_AND_NETDEV_NAMES_s_s(dev),
+				priv->mpt_rxfidx_tail,
+				MPT_LAN_MAX_BUCKETS_OUT);
+
+		panic("Damn it Jim! I'm a doctor, not a programmer! "
+				"Oh, wait a sec, I am a programmer. "
+				"And, who's Jim?!?!\n"
+				"Arrgghh! We've done it again!\n");
+	}
+
+#if 0
+	{
+		u32 remaining = le32_to_cpu(pRecvRep->BucketsRemaining);
+		if (remaining < priv->bucketthresh)
+			mpt_lan_wake_post_buckets_task(dev);
+
+		if (remaining == 0)
+			printk (KERN_WARNING MYNAM ": %s/%s: WARNING - IOC out of buckets! "
+				"(priv->buckets_out = %d)\n",
+					IOC_AND_NETDEV_NAMES_s_s(dev),
+					atomic_read(&priv->buckets_out));
+		else
+			printk (KERN_INFO MYNAM ": %s/%s: IOC says %d buckets left. "
+				"(priv->buckets_out = %d)\n",
+					IOC_AND_NETDEV_NAMES_s_s(dev),
+					remaining, atomic_read(&priv->buckets_out));
+	}
+#endif
+
+	return mpt_lan_receive_skb(dev, skb);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* Simple SGE's only at the moment */
+
+static void
+mpt_lan_post_receive_buckets(void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct mpt_lan_priv *priv = dev->priv;
+	MPT_ADAPTER *mpt_dev = priv->mpt_dev;
+	MPT_FRAME_HDR *mf;
+	LANReceivePostRequest_t *pRecvReq;
+	SGETransaction32_t *pTrans;
+	SGESimple64_t *pSimple;
+	struct sk_buff *skb;
+	dma_addr_t dma;
+	u32 curr, buckets, count, max;
+	u32 len = (dev->mtu + dev->hard_header_len + 4);
+	unsigned long flags;
+	int i;
+
+	curr = atomic_read(&priv->buckets_out);
+	buckets = (priv->max_buckets_out - curr);
+
+	dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
+			IOC_AND_NETDEV_NAMES_s_s(dev),
+			__FUNCTION__, buckets, curr));
+
+	max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) /
+			(MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t));
+
+	while (buckets) {
+		mf = mpt_get_msg_frame(LanCtx, mpt_dev->id);
+		if (mf == NULL) {
+			printk (KERN_ERR "%s: Unable to alloc request frame\n",
+				__FUNCTION__);
+			dioprintk((KERN_ERR "%s: %u buckets remaining\n",
+				 __FUNCTION__, buckets));
+			goto out;
+		}
+		pRecvReq = (LANReceivePostRequest_t *) mf;
+
+		count = buckets;
+		if (count > max)
+			count = max;
+
+		pRecvReq->Function    = MPI_FUNCTION_LAN_RECEIVE;
+		pRecvReq->ChainOffset = 0;
+		pRecvReq->MsgFlags    = 0;
+		pRecvReq->PortNumber  = priv->pnum;
+
+		pTrans = (SGETransaction32_t *) pRecvReq->SG_List;
+		pSimple = NULL;
+
+		for (i = 0; i < count; i++) {
+			int ctx;
+
+			spin_lock_irqsave(&priv->rxfidx_lock, flags);
+			if (priv->mpt_rxfidx_tail < 0) {
+				printk (KERN_ERR "%s: Can't alloc context\n",
+					__FUNCTION__);
+				spin_unlock_irqrestore(&priv->rxfidx_lock,
+						       flags);
+				break;
+			}
+
+			ctx = priv->mpt_rxfidx[priv->mpt_rxfidx_tail--];
+
+			skb = priv->RcvCtl[ctx].skb;
+			if (skb && (priv->RcvCtl[ctx].len != len)) {
+				pci_unmap_single(mpt_dev->pcidev,
+						 priv->RcvCtl[ctx].dma,
+						 priv->RcvCtl[ctx].len,
+						 PCI_DMA_FROMDEVICE);
+				dev_kfree_skb(priv->RcvCtl[ctx].skb);
+				skb = priv->RcvCtl[ctx].skb = NULL;
+			}
+
+			if (skb == NULL) {
+				skb = dev_alloc_skb(len);
+				if (skb == NULL) {
+/**/					printk (KERN_WARNING
+/**/						MYNAM "/%s: Can't alloc skb\n",
+/**/						__FUNCTION__);
+					priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+					spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+					break;
+				}
+
+		    		dma = pci_map_single(mpt_dev->pcidev, skb->data,
+						     len, PCI_DMA_FROMDEVICE);
+
+				priv->RcvCtl[ctx].skb = skb;
+				priv->RcvCtl[ctx].dma = dma;
+				priv->RcvCtl[ctx].len = len;
+			}
+
+			spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
+
+			pTrans->ContextSize   = sizeof(u32);
+			pTrans->DetailsLength = 0;
+			pTrans->Flags         = 0;
+			pTrans->TransactionContext[0] = cpu_to_le32(ctx);
+
+			pSimple = (SGESimple64_t *) pTrans->TransactionDetails;
+
+			pSimple->FlagsLength = cpu_to_le32(
+				((MPI_SGE_FLAGS_END_OF_BUFFER |
+				  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+				  MPI_SGE_FLAGS_64_BIT_ADDRESSING) << MPI_SGE_FLAGS_SHIFT) | len);
+			pSimple->Address.Low = cpu_to_le32((u32) priv->RcvCtl[ctx].dma);
+			if (sizeof(dma_addr_t) > sizeof(u32))
+				pSimple->Address.High = cpu_to_le32((u32) ((u64) priv->RcvCtl[ctx].dma >> 32));
+			else
+				pSimple->Address.High = 0;
+
+			pTrans = (SGETransaction32_t *) (pSimple + 1);
+		}
+
+		if (pSimple == NULL) {
+/**/			printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
+/**/				__FUNCTION__);
+			mpt_free_msg_frame(LanCtx, mpt_dev->id, mf);
+			goto out;
+		}
+
+		pSimple->FlagsLength |= cpu_to_le32(MPI_SGE_FLAGS_END_OF_LIST << MPI_SGE_FLAGS_SHIFT);
+
+		pRecvReq->BucketCount = cpu_to_le32(i);
+
+/*	printk(KERN_INFO MYNAM ": posting buckets\n   ");
+ *	for (i = 0; i < j + 2; i ++)
+ *	    printk (" %08x", le32_to_cpu(msg[i]));
+ *	printk ("\n");
+ */
+
+		mpt_put_msg_frame(LanCtx, mpt_dev->id, mf);
+
+		priv->total_posted += i;
+		buckets -= i;
+		atomic_add(i, &priv->buckets_out);
+	}
+
+out:
+	dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
+		  __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
+	dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
+	__FUNCTION__, priv->total_posted, priv->total_received)); 
+
+	clear_bit(0, &priv->post_buckets_active);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+struct net_device *
+mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
+{
+	struct net_device *dev = NULL;
+	struct mpt_lan_priv *priv = NULL;
+	u8 HWaddr[FC_ALEN], *a;
+
+	dev = init_fcdev(NULL, sizeof(struct mpt_lan_priv));
+	if (!dev)
+		return (NULL);
+	dev->mtu = MPT_LAN_MTU;
+
+	priv = (struct mpt_lan_priv *) dev->priv;
+
+	priv->mpt_dev = mpt_dev;
+	priv->pnum = pnum;
+
+	memset(&priv->post_buckets_task, 0, sizeof(struct tq_struct));
+	priv->post_buckets_task.routine = mpt_lan_post_receive_buckets;
+	priv->post_buckets_task.data = dev;
+	priv->post_buckets_active = 0;
+
+	dprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n",
+			__LINE__, dev->mtu + dev->hard_header_len + 4));
+
+	atomic_set(&priv->buckets_out, 0);
+	priv->total_posted = 0;
+	priv->total_received = 0;
+	priv->max_buckets_out = max_buckets_out;
+	if (mpt_dev->pfacts0.MaxLanBuckets < max_buckets_out)
+		priv->max_buckets_out = mpt_dev->pfacts0.MaxLanBuckets;
+
+	dprintk((KERN_INFO MYNAM "@%d: MaxLanBuckets=%d, max_buckets_out/priv=%d/%d\n",
+			__LINE__,
+			mpt_dev->pfacts0.MaxLanBuckets,
+			max_buckets_out,
+			priv->max_buckets_out));
+
+	priv->bucketthresh = priv->max_buckets_out * 2 / 3;
+	priv->txfidx_lock = SPIN_LOCK_UNLOCKED;
+	priv->rxfidx_lock = SPIN_LOCK_UNLOCKED;
+
+	memset(&priv->stats, 0, sizeof(priv->stats));
+
+	/*  Grab pre-fetched LANPage1 stuff. :-) */
+	a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
+
+	HWaddr[0] = a[5];
+	HWaddr[1] = a[4];
+	HWaddr[2] = a[3];
+	HWaddr[3] = a[2];
+	HWaddr[4] = a[1];
+	HWaddr[5] = a[0];
+
+	dev->addr_len = FC_ALEN;
+	memcpy(dev->dev_addr, HWaddr, FC_ALEN);
+	memset(dev->broadcast, 0xff, FC_ALEN);
+
+	/* The Tx queue is 127 deep on the 909.
+	 * Give ourselves some breathing room.
+	 */
+	priv->tx_max_out = (tx_max_out_p <= MPT_TX_MAX_OUT_LIM) ?
+			    tx_max_out_p : MPT_TX_MAX_OUT_LIM;
+
+	dev->open = mpt_lan_open;
+	dev->stop = mpt_lan_close;
+	dev->get_stats = mpt_lan_get_stats;
+	dev->set_multicast_list = NULL;
+	dev->change_mtu = mpt_lan_change_mtu;
+	dev->hard_start_xmit = mpt_lan_sdu_send;
+
+/* Not in 2.3.42. Need 2.3.45+ */
+	dev->tx_timeout = mpt_lan_tx_timeout;
+	dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
+
+	dprintk((KERN_INFO MYNAM ": Finished registering dev "
+		"and setting initial values\n"));
+
+	SET_MODULE_OWNER(dev);
+
+	return dev;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int __init
+mpt_lan_init (void)
+{
+	struct net_device *dev;
+	MPT_ADAPTER *curadapter;
+	int i = 0, j;
+
+	show_mptmod_ver(LANAME, LANVER);
+
+	if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) < 0) {
+		printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n");
+		return -EBUSY;
+	}
+
+	/* Set the callback index to be used by driver core for turbo replies */
+	mpt_lan_index = LanCtx;
+
+	dprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
+
+	for (j = 0; j < MPT_MAX_ADAPTERS; j++) {
+		mpt_landev[j] = NULL;
+	}
+	j = 0;
+
+	curadapter = mpt_adapter_find_first();
+	while (curadapter != NULL) {
+		for (i = 0; i < curadapter->facts0.NumberOfPorts; i++) {
+			printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n",
+					curadapter->name,
+					curadapter->pfacts0.PortNumber,
+					curadapter->pfacts0.ProtocolFlags,
+					MPT_PROTOCOL_FLAGS_c_c_c_c(curadapter->pfacts0.ProtocolFlags));
+
+			if (curadapter->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
+				dev = mpt_register_lan_device (curadapter, i);
+				if (dev != NULL) {
+					printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n",
+							curadapter->name, dev->name);
+					printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+							IOC_AND_NETDEV_NAMES_s_s(dev),
+							dev->dev_addr[0], dev->dev_addr[1],
+							dev->dev_addr[2], dev->dev_addr[3],
+							dev->dev_addr[4], dev->dev_addr[5]);
+//					printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",
+//							IOC_AND_NETDEV_NAMES_s_s(dev),
+//							NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out);
+					mpt_landev[j] = dev;
+					dprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n",
+							dev, j,  mpt_landev[j]));
+
+					j++;
+				} else {
+					printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n",
+							curadapter->name,
+							curadapter->pfacts0.PortNumber);
+				}
+			} else {
+				printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n",
+						curadapter->name);
+			}
+		}
+		curadapter = mpt_adapter_find_next(curadapter);
+	}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+void __init mpt_lan_exit(void)
+{
+	int i;
+
+	for (i = 0; mpt_landev[i] != NULL; i++) {
+		struct net_device *dev = mpt_landev[i];
+
+		printk (KERN_INFO MYNAM ": %s/%s: Fusion MPT LAN device unregistered\n",
+			       IOC_AND_NETDEV_NAMES_s_s(dev));
+		unregister_fcdev(dev);
+		mpt_landev[i] = (struct net_device *) 0xdeadbeef; /* Debug */
+	}
+
+	if (LanCtx >= 0) {
+		mpt_deregister(LanCtx);
+		LanCtx = -1;
+		mpt_lan_index = 0;
+	}
+
+	/* deregister any send/receive handler structs. I2Oism? */
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+MODULE_PARM(tx_max_out_p, "i");
+MODULE_PARM(max_buckets_out, "i"); // Debug stuff. FIXME!
+
+module_init(mpt_lan_init);
+module_exit(mpt_lan_exit);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static unsigned short
+mpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev) 
+{
+	struct mpt_lan_ohdr *fch = (struct mpt_lan_ohdr *)skb->data;
+	struct fcllc *fcllc;
+
+	skb->mac.raw = skb->data;
+	skb_pull(skb, sizeof(struct mpt_lan_ohdr));
+
+	if (fch->dtype == htons(0xffff)) {
+		u32 *p = (u32 *) fch;
+
+		swab32s(p + 0);
+		swab32s(p + 1);
+		swab32s(p + 2);
+		swab32s(p + 3);
+
+		printk (KERN_WARNING MYNAM ": %s: WARNING - Broadcast swap F/W bug detected!\n",
+				NETDEV_PTR_TO_IOC_NAME_s(dev));
+		printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       		fch->saddr[0], fch->saddr[1], fch->saddr[2],
+				fch->saddr[3], fch->saddr[4], fch->saddr[5]);
+	}
+
+	if (*fch->daddr & 1) {
+		if (!memcmp(fch->daddr, dev->broadcast, FC_ALEN)) {
+			skb->pkt_type = PACKET_BROADCAST;
+		} else {
+			skb->pkt_type = PACKET_MULTICAST;
+		}
+	} else {
+		if (memcmp(fch->daddr, dev->dev_addr, FC_ALEN)) {
+			skb->pkt_type = PACKET_OTHERHOST;
+		} else {
+			skb->pkt_type = PACKET_HOST;
+		}
+	}
+
+	/* Strip the SNAP header from ARP packets since we don't 
+	 * pass them through to the 802.2/SNAP layers.
+	 */
+	fcllc = (struct fcllc *)skb->data;
+
+	if (fcllc->dsap == EXTENDED_SAP &&
+		(fcllc->ethertype == htons(ETH_P_IP) ||
+		 fcllc->ethertype == htons(ETH_P_ARP))) {
+		skb_pull(skb, sizeof(struct fcllc));
+		return fcllc->ethertype;
+	}
+
+	return htons(ETH_P_802_2);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptlan.h linux/drivers/message/fusion/mptlan.h
--- linux-2.4.7-pre3/drivers/message/fusion/mptlan.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptlan.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,72 @@
+/* mptlan.h */
+
+#ifndef LINUX_MPTLAN_H_INCLUDED
+#define LINUX_MPTLAN_H_INCLUDED
+/*****************************************************************************/
+
+#if !defined(__GENKSYMS__)
+#include <linux/module.h>
+#endif
+
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+// #include <linux/etherdevice.h>
+#include <linux/fcdevice.h>
+// #include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/tqueue.h>
+// #include <linux/trdevice.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+    /* Override mptbase.h by pre-defining these! */
+    #define MODULEAUTHOR "Noah Romer, Eddie C. Dost"
+
+#include "mptbase.h"
+
+/*****************************************************************************/
+#define LANAME		"Fusion MPT LAN driver"
+#define LANVER		MPT_LINUX_VERSION_COMMON
+
+#ifdef MODULE
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(LANAME);
+#endif
+/*****************************************************************************/
+
+#define MPT_LAN_MAX_BUCKETS_OUT 256
+#define MPT_LAN_BUCKET_THRESH	18 /* 9 buckets in one message */
+#define MPT_LAN_RX_COPYBREAK	200
+#define MPT_LAN_TX_TIMEOUT 	(1*HZ)
+#define MPT_TX_MAX_OUT_LIM      127
+
+#define MPT_LAN_MIN_MTU		96		/* RFC2625 */
+#define MPT_LAN_MAX_MTU		65280		/* RFC2625 */
+#define MPT_LAN_MTU             16128		/* be nice to slab allocator */
+
+/* MPT LAN Reset and Suspend Resource Flags Defines */
+
+#define MPT_LAN_RESOURCE_FLAG_RETURN_POSTED_BUCKETS    0x01
+#define MPT_LAN_RESOURCE_FLAG_RETURN_PEND_TRANSMITS    0x02
+
+/*****************************************************************************/
+#ifdef MPT_LAN_IO_DEBUG
+#define dioprintk(x)  printk x
+#else
+#define dioprintk(x)
+#endif
+
+#define NETDEV_TO_LANPRIV_PTR(d)	((struct mpt_lan_priv *)(d)->priv)
+#define NETDEV_PTR_TO_IOC_NAME_s(d)	(NETDEV_TO_LANPRIV_PTR(d)->mpt_dev->name)
+#define IOC_AND_NETDEV_NAMES_s_s(d)	NETDEV_PTR_TO_IOC_NAME_s(d), (d)->name
+
+/*****************************************************************************/
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptscsih.c linux/drivers/message/fusion/mptscsih.c
--- linux-2.4.7-pre3/drivers/message/fusion/mptscsih.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptscsih.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,2508 @@
+/*
+ *  linux/drivers/message/fusion/mptscsih.c
+ *      High performance SCSI / Fibre Channel SCSI Host device driver.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *      This driver would not exist if not for Alan Cox's development
+ *      of the linux i2o driver.
+ *
+ *      A huge debt of gratitude is owed to David S. Miller (DaveM)
+ *      for fixing much of the stupid and broken stuff in the early
+ *      driver while porting to sparc64 platform.  THANK YOU!
+ *
+ *      (see mptbase.c)
+ *
+ *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Original author: Steven J. Ralston
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: mptscsih.c,v 1.24 2001/03/22 08:45:08 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/blk.h>		/* for io_request_lock (spinlock) decl */
+#include "../../scsi/scsi.h"
+#include "../../scsi/hosts.h"
+#include "../../scsi/sd.h"
+
+#include "mptbase.h"
+#include "mptscsih.h"
+#include "isense.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"Fusion MPT SCSI Host driver"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"mptscsih"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+typedef struct _BIG_SENSE_BUF {
+	u8		data[256];
+} BIG_SENSE_BUF;
+
+typedef struct _MPT_SCSI_HOST {
+	MPT_ADAPTER		 *ioc;
+	int			  port;
+	struct scsi_cmnd	**ScsiLookup;
+	u8			 *SgHunks;
+	dma_addr_t		  SgHunksDMA;
+	u32			  qtag_tick;
+	FCDEV_TRACKER		  TargetsQ;
+} MPT_SCSI_HOST;
+
+typedef struct _MPT_SCSI_DEV {
+	struct _MPT_SCSI_DEV	 *forw;
+	struct _MPT_SCSI_DEV	 *back;
+	MPT_ADAPTER		 *ioc;
+	int			  sense_sz;
+	BIG_SENSE_BUF		  CachedSense;
+	unsigned long		  io_cnt;
+	unsigned long		  read_cnt;
+} MPT_SCSI_DEV;
+
+/*
+ *  Other private/forward protos...
+ */
+
+static int	mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+static void	mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
+static int	mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+static int	mptscsih_io_direction(Scsi_Cmnd *cmd);
+static void	copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+static u32	SCPNT_TO_MSGCTX(Scsi_Cmnd *sc);
+
+static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+
+
+static int	mpt_scsi_hosts = 0;
+static atomic_t	queue_depth;
+
+static int	ScsiDoneCtx = -1;
+static int	ScsiTaskCtx = -1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
+static struct proc_dir_entry proc_mpt_scsihost =
+{
+	low_ino:	PROC_SCSI_MPT,
+	namelen:	8,
+	name:		"mptscsih",
+	mode:		S_IFDIR | S_IRUGO | S_IXUGO,
+	nlink:		2,
+};
+#endif
+
+#define SNS_LEN(scp)  sizeof((scp)->sense_buffer)
+
+#ifndef MPT_SCSI_USE_NEW_EH
+/*
+ *  Stuff to handle single-threading SCSI TaskMgmt
+ *  (abort/reset) requests...
+ */
+static spinlock_t mpt_scsih_taskQ_lock = SPIN_LOCK_UNLOCKED;
+static MPT_Q_TRACKER mpt_scsih_taskQ = {
+	(MPT_FRAME_HDR*) &mpt_scsih_taskQ,
+	(MPT_FRAME_HDR*) &mpt_scsih_taskQ
+};
+static int mpt_scsih_taskQ_cnt = 0;
+static int mpt_scsih_taskQ_bh_active = 0;
+static MPT_FRAME_HDR *mpt_scsih_active_taskmgmt_mf = NULL;
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptscsih_io_done - Main SCSI IO callback routine registered to
+ *	Fusion MPT (base) driver
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@mf: Pointer to original MPT request frame
+ *	@r: Pointer to MPT reply frame (NULL if TurboReply)
+ *
+ *	This routine is called from mpt.c::mpt_interrupt() at the completion
+ *	of any SCSI IO request.
+ *	This routine is registered with the Fusion MPT (base) driver at driver
+ *	load/init time via the mpt_register() API call.
+ *
+ *	Returns 1 indicating alloc'd request frame ptr should be freed.
+ */
+static int
+mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r)
+{
+	Scsi_Cmnd	*sc;
+	MPT_SCSI_HOST	*hd;
+	MPT_SCSI_DEV	*mpt_sdev = NULL;
+	u16		 req_idx;
+
+	if ((mf == NULL) ||
+	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
+		printk(KERN_ERR MYNAM ": ERROR! NULL or BAD req frame ptr (=%p)!\n", mf);
+		return 1;
+	}
+
+	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+	sc = hd->ScsiLookup[req_idx];
+	hd->ScsiLookup[req_idx] = NULL;
+
+	dmfprintk((KERN_INFO MYNAM ": ScsiDone (req:sc:reply=%p:%p:%p)\n", mf, sc, r));
+
+	atomic_dec(&queue_depth);
+
+	/*
+	 *  Check for {1st} {IO} completion to "new" device.
+	 *  How do we know it's a new device?
+	 *  If we haven't set SDpnt->hostdata I guess...
+	 */
+	if (sc && sc->device) {
+		mpt_sdev = (MPT_SCSI_DEV*)sc->device->hostdata;
+		if (!mpt_sdev) {
+			dprintk((KERN_INFO MYNAM ": *NEW* SCSI device (%d:%d:%d)!\n",
+					   sc->device->id, sc->device->lun, sc->device->channel));
+			if ((sc->device->hostdata = kmalloc(sizeof(MPT_SCSI_DEV), GFP_ATOMIC)) == NULL) {
+				printk(KERN_ERR MYNAM ": ERROR: kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV));
+			} else {
+				memset(sc->device->hostdata, 0, sizeof(MPT_SCSI_DEV));
+				mpt_sdev = (MPT_SCSI_DEV *) sc->device->hostdata;
+				mpt_sdev->ioc = ioc;
+			}
+		} else {
+			if (++mpt_sdev->io_cnt && mptscsih_io_direction(sc) < 0) {
+				if (++mpt_sdev->read_cnt == 3) {
+					dprintk((KERN_INFO MYNAM ": 3rd DATA_IN, CDB[0]=%02x\n",
+							sc->cmnd[0]));
+				}
+			}
+#if 0
+			if (mpt_sdev->sense_sz) {
+				/*
+				 *  Completion of first IO down this path
+				 *  *should* invalidate device SenseData...
+				 */
+				mpt_sdev->sense_sz = 0;
+			}
+#endif
+		}
+	}
+
+#if 0
+{
+	MPT_FRAME_HDR	*mf_chk;
+
+	/* This, I imagine, is a costly check, but...
+	 *  If abort/reset active, check to see if this is a IO
+	 *  that completed while ABORT/RESET for it is waiting
+	 *  on our taskQ!
+	 */
+	if (! Q_IS_EMPTY(&mpt_scsih_taskQ)) {
+		/* If ABORT for this IO is queued, zap it! */
+		mf_chk = search_taskQ(1,sc,MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
+		if (mf_chk != NULL) {
+			sc->result = DID_ABORT << 16;
+			spin_lock_irqsave(&io_request_lock, flags);
+			sc->scsi_done(sc);
+			spin_unlock_irqrestore(&io_request_lock, flags);
+			return 1;
+		}
+	}
+}
+#endif
+
+	if (r != NULL && sc != NULL) {
+		SCSIIOReply_t	*pScsiReply;
+		SCSIIORequest_t *pScsiReq;
+		u16		 status;
+
+		pScsiReply = (SCSIIOReply_t *) r;
+		pScsiReq = (SCSIIORequest_t *) mf;
+
+		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+
+		dprintk((KERN_NOTICE MYNAM ": Uh-Oh!  (req:sc:reply=%p:%p:%p)\n", mf, sc, r));
+		dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
+				     ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
+				     status, pScsiReply->SCSIState, pScsiReply->SCSIStatus,
+				     le32_to_cpu(pScsiReply->IOCLogInfo)));
+
+		/*
+		 *  Look for + dump FCP ResponseInfo[]!
+		 */
+		if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
+			dprintk((KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
+					     le32_to_cpu(pScsiReply->ResponseInfo)));
+		}
+
+		switch(status) {
+		case MPI_IOCSTATUS_BUSY:			/* 0x0002 */
+			/*sc->result = DID_BUS_BUSY << 16;*/		/* YIKES! - Seems to
+									 * kill linux interrupt
+									 * handler
+									 */
+			sc->result = STS_BUSY;				/* Try SCSI BUSY! */
+			break;
+
+		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
+			/*  Not real sure here...  */
+			sc->result = DID_OK << 16;
+			break;
+
+		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */
+		case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:	/* 0x0042 */
+			sc->result = DID_BAD_TARGET << 16;
+			break;
+
+		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
+			/*  Spoof to SCSI Selection Timeout!  */
+			sc->result = DID_NO_CONNECT << 16;
+			break;
+
+		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
+			/*
+			 *  YIKES!  I just discovered that SCSI IO which
+			 *  returns check condition, SenseKey=05 (ILLEGAL REQUEST)
+			 *  and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific),
+			 *  comes down this path!
+			 *  Do upfront check for valid SenseData and give it
+			 *  precedence!
+			 */
+			if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+				copy_sense_data(sc, hd, mf, pScsiReply);
+				sc->result = pScsiReply->SCSIStatus;
+				break;
+			}
+
+			dprintk((KERN_NOTICE MYNAM ": sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow));
+			dprintk((KERN_NOTICE MYNAM ": ActBytesXferd=%02xh\n", le32_to_cpu(pScsiReply->TransferCount)));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+			sc->resid = sc->request_bufflen - le32_to_cpu(pScsiReply->TransferCount);
+			dprintk((KERN_NOTICE MYNAM ": SET sc->resid=%02xh\n", sc->resid));
+#endif
+
+#if 0
+			if (sc->underflow && (le32_to_cpu(pScsiReply->TransferCount) < sc->underflow)) {
+				sc->result = DID_ERROR << 16;
+				sc->resid = sc->request_bufflen - le32_to_cpu(pScsiReply->TransferCount);
+			} else {
+				sc->result = 0;
+			}
+#endif
+
+			/* workaround attempts... */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+			if (sc->resid >= 0x200) {
+				/* GRRRRR...
+				 *   //sc->result = DID_SOFT_ERROR << 16;
+				 * Try spoofing to BUSY
+				 */
+				sc->result = STS_BUSY;
+			} else {
+				sc->result = 0;
+			}
+#else
+			sc->result = 0;
+#endif
+			break;
+
+		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
+			sc->result = DID_ABORT << 16;
+			break;
+
+		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
+		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
+			sc->result = DID_RESET << 16;
+			break;
+
+		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
+			sc->result = pScsiReply->SCSIStatus;
+
+			if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+				copy_sense_data(sc, hd, mf, pScsiReply);
+
+				/*  If running agains circa 200003dd 909 MPT f/w,
+				 *  may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
+				 *  (QUEUE_FULL) returned from device!	--> get 0x0000?128
+				 *  and with SenseBytes set to 0.
+				 */
+				if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
+					mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
+			}
+			else if (pScsiReply->SCSIState & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
+				/*
+				 *  What to do?
+				 */
+				sc->result = DID_SOFT_ERROR << 16;
+			}
+			else if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
+				/*  Not real sure here either...  */
+				sc->result = DID_ABORT << 16;
+			}
+
+			if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
+				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
+
+			break;
+
+		case MPI_IOCSTATUS_INVALID_FUNCTION:		/* 0x0001 */
+		case MPI_IOCSTATUS_INVALID_SGL:			/* 0x0003 */
+		case MPI_IOCSTATUS_INTERNAL_ERROR:		/* 0x0004 */
+		case MPI_IOCSTATUS_RESERVED:			/* 0x0005 */
+		case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:	/* 0x0006 */
+		case MPI_IOCSTATUS_INVALID_FIELD:		/* 0x0007 */
+		case MPI_IOCSTATUS_INVALID_STATE:		/* 0x0008 */
+		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
+		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
+		case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
+		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
+		case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:	/* 0x004A */
+		default:
+			/*
+			 *  What to do?
+			 */
+			sc->result = DID_SOFT_ERROR << 16;
+			break;
+
+		}	/* switch(status) */
+
+		dprintk((KERN_NOTICE MYNAM ": sc->result set to %08xh\n", sc->result));
+	}
+
+	if (sc != NULL) {
+		unsigned long flags;
+
+		/* Unmap the DMA buffers, if any. */
+		if (sc->use_sg) {
+			pci_unmap_sg(ioc->pcidev,
+				     (struct scatterlist *) sc->request_buffer,
+				     sc->use_sg,
+				     scsi_to_pci_dma_dir(sc->sc_data_direction));
+		} else if (sc->request_bufflen) {
+			pci_unmap_single(ioc->pcidev,
+					 (dma_addr_t)((long)sc->SCp.ptr),
+					 sc->request_bufflen,
+					 scsi_to_pci_dma_dir(sc->sc_data_direction));
+		}
+
+		spin_lock_irqsave(&io_request_lock, flags);
+		sc->scsi_done(sc);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+	}
+
+	return 1;
+}
+
+#ifndef MPT_SCSI_USE_NEW_EH
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	search_taskQ - Search SCSI task mgmt request queue for specific
+ *			request type
+ *	@remove: (Boolean) Should request be removed if found?
+ *	@sc: Pointer to Scsi_Cmnd structure
+ *	@task_type: Task type to search for
+ *
+ *	Returns pointer to MPT request frame if found, or %NULL if request
+ *	was not found.
+ */
+static MPT_FRAME_HDR *
+search_taskQ(int remove, Scsi_Cmnd *sc, u8 task_type)
+{
+	MPT_FRAME_HDR *mf = NULL;
+	unsigned long flags;
+	int count = 0;
+	int list_sz;
+
+	dslprintk((KERN_INFO MYNAM ": spinlock#1\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	list_sz = mpt_scsih_taskQ_cnt;
+	if (! Q_IS_EMPTY(&mpt_scsih_taskQ)) {
+		mf = mpt_scsih_taskQ.head;
+		do {
+			count++;
+			if (mf->u.frame.linkage.argp1 == sc &&
+			    mf->u.frame.linkage.arg1 == task_type) {
+				if (remove) {
+					Q_DEL_ITEM(&mf->u.frame.linkage);
+					mpt_scsih_taskQ_cnt--;
+				}
+				break;
+			}
+		} while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&mpt_scsih_taskQ);
+		if (mf == (MPT_FRAME_HDR*)&mpt_scsih_taskQ) {
+			mf = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+	if (list_sz) {
+		dprintk((KERN_INFO MYNAM ": search_taskQ(%d,%p,%d) results=%p (%sFOUND%s)!\n",
+				   remove, sc, task_type,
+				   mf,
+				   mf ? "" : "NOT_",
+				   (mf && remove) ? "+REMOVED" : "" ));
+		dprintk((KERN_INFO MYNAM ": (searched thru %d of %d items on taskQ)\n",
+				   count,
+				   list_sz ));
+	}
+
+	return mf;
+}
+
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ *  Hack!  I'd like to report if a device is returning QUEUE_FULL
+ *  but maybe not each and every time...
+ */
+static long last_queue_full = 0;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptscsih_report_queue_full - Report QUEUE_FULL status returned
+ *	from a SCSI target device.
+ *	@sc: Pointer to Scsi_Cmnd structure
+ *	@pScsiReply: Pointer to SCSIIOReply_t
+ *	@pScsiReq: Pointer to original SCSI request
+ *
+ *	This routine periodically reports QUEUE_FULL status returned from a
+ *	SCSI target device.  It reports this to the console via kernel
+ *	printk() API call, not more than once every 10 seconds.
+ */
+static void
+mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
+{
+	long time = jiffies;
+
+	if (time - last_queue_full > 10 * HZ) {
+		printk(KERN_WARNING MYNAM ": Device reported QUEUE_FULL!  SCSI bus:target:lun = %d:%d:%d\n",
+				0, sc->target, sc->lun);
+		last_queue_full = time;
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int BeenHereDoneThat = 0;
+
+/*  SCSI fops start here...  */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
+ *	linux scsi mid-layer.
+ *	@tpnt: Pointer to Scsi_Host_Template structure
+ *
+ *	(linux Scsi_Host_Template.detect routine)
+ *
+ *	Returns number of SCSI host adapters that were successfully
+ *	registered with the linux scsi mid-layer via the scsi_register()
+ *	API call.
+ */
+int
+mptscsih_detect(Scsi_Host_Template *tpnt)
+{
+	struct Scsi_Host	*sh = NULL;
+	MPT_SCSI_HOST		*hd = NULL;
+	MPT_ADAPTER		*this;
+	unsigned long		 flags;
+	int			 sz;
+	u8			*mem;
+
+	if (! BeenHereDoneThat++) {
+		show_mptmod_ver(my_NAME, my_VERSION);
+
+		ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
+		ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
+
+#ifndef MPT_SCSI_USE_NEW_EH
+		Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);
+		spin_lock_init(&mpt_scsih_taskQ_lock);
+#endif
+
+		if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
+			dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
+		} else {
+			/* FIXME! */
+		}
+	}
+
+	dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));
+
+	this = mpt_adapter_find_first();
+	while (this != NULL) {
+		/* FIXME!  Multi-port (aka FC929) support...
+		 * for (i = 0; i < this->facts.NumberOfPorts; i++)
+		 */
+
+		/* 20010215 -sralston
+		 *  Added sanity check on SCSI Initiator-mode enabled
+		 *  for this MPT adapter.
+		 */
+		if (!(this->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
+			printk(KERN_ERR MYNAM ": Skipping %s because SCSI Initiator mode is NOT enabled!\n",
+					this->name);
+			this = mpt_adapter_find_next(this);
+			continue;
+		}
+
+		/* 20010202 -sralston
+		 *  Added sanity check on readiness of the MPT adapter.
+		 */
+		if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
+			printk(KERN_ERR MYNAM ": ERROR - Skipping %s because it's not operational!\n",
+					this->name);
+			this = mpt_adapter_find_next(this);
+			continue;
+		}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+		tpnt->proc_dir = &proc_mpt_scsihost;
+#endif
+		sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
+		if (sh != NULL) {
+			save_flags(flags);
+			cli();
+			sh->io_port = 0;
+			sh->n_io_port = 0;
+			sh->irq = 0;
+
+			/* Yikes!  This is important!
+			 * Otherwise, by default, linux only scans target IDs 0-7!
+			 */
+			sh->max_id = this->pfacts0.MaxDevices - 1;
+
+			sh->this_id = this->pfacts0.PortSCSIID;
+
+			restore_flags(flags);
+
+			hd = (MPT_SCSI_HOST *) sh->hostdata;
+			hd->ioc = this;
+			hd->port = 0;		/* FIXME! */
+
+			/* SCSI needs Scsi_Cmnd lookup table!
+			 * (with size equal to req_depth*PtrSz!)
+			 */
+			sz = hd->ioc->req_depth * sizeof(void *);
+			mem = kmalloc(sz, GFP_KERNEL);
+			if (mem == NULL)
+				return mpt_scsi_hosts;
+
+			memset(mem, 0, sz);
+			hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+			dprintk((KERN_INFO MYNAM ": ScsiLookup @ %p, sz=%d\n",
+				 hd->ScsiLookup, sz));
+
+			/* SCSI also needs SG buckets/hunk management!
+			 * (with size equal to N * req_sz * req_depth!)
+			 * (where N is number of SG buckets per hunk)
+			 */
+			sz = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;
+			mem = pci_alloc_consistent(hd->ioc->pcidev, sz,
+						   &hd->SgHunksDMA);
+			if (mem == NULL)
+				return mpt_scsi_hosts;
+
+			memset(mem, 0, sz);
+			hd->SgHunks = (u8*)mem;
+
+			dprintk((KERN_INFO MYNAM ": SgHunks    @ %p(%08x), sz=%d\n",
+				 hd->SgHunks, hd->SgHunksDMA, sz));
+
+			hd->qtag_tick = jiffies;
+
+			this->sh = sh;
+			mpt_scsi_hosts++;
+		}
+		this = mpt_adapter_find_next(this);
+	}
+
+	return mpt_scsi_hosts;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+    static char *info_kbuf = NULL;
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_release - Unregister SCSI host from linux scsi mid-layer
+ *	@host: Pointer to Scsi_Host structure
+ *
+ *	(linux Scsi_Host_Template.release routine)
+ *	This routine releases all resources associated with the SCSI host
+ *	adapter.
+ *
+ *	Returns 0 for success.
+ */
+int
+mptscsih_release(struct Scsi_Host *host)
+{
+	MPT_SCSI_HOST	*hd;
+#ifndef MPT_SCSI_USE_NEW_EH
+	unsigned long	 flags;
+
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	if (mpt_scsih_taskQ_bh_active) {
+		int count = 10 * HZ;
+
+		dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));
+
+		/* Zap the taskQ! */
+		Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);
+		spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+		while(mpt_scsih_taskQ_bh_active && --count) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(1);
+		}
+		if (!count)
+			printk(KERN_ERR MYNAM ": ERROR! TaskMgmt thread still active!\n");
+	}
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+#endif
+
+	hd = (MPT_SCSI_HOST *) host->hostdata;
+	if (hd != NULL) {
+		int sz1, sz2;
+
+		sz1 = sz2 = 0;
+		if (hd->ScsiLookup != NULL) {
+			sz1 = hd->ioc->req_depth * sizeof(void *);
+			kfree(hd->ScsiLookup);
+			hd->ScsiLookup = NULL;
+		}
+
+		if (hd->SgHunks != NULL) {
+
+			sz2 = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;
+			pci_free_consistent(hd->ioc->pcidev, sz2,
+					    hd->SgHunks, hd->SgHunksDMA);
+			hd->SgHunks = NULL;
+		}
+		dprintk((KERN_INFO MYNAM ": Free'd ScsiLookup (%d) and SgHunks (%d) memory\n", sz1, sz2));
+	}
+
+	if (mpt_scsi_hosts) {
+		if (--mpt_scsi_hosts == 0) {
+#if 0
+			mptscsih_flush_pending();
+#endif
+			mpt_event_deregister(ScsiDoneCtx);
+			dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
+
+			mpt_deregister(ScsiDoneCtx);
+			mpt_deregister(ScsiTaskCtx);
+
+			if (info_kbuf != NULL)
+				kfree(info_kbuf);
+		}
+	}
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_info - Return information about MPT adapter
+ *	@SChost: Pointer to Scsi_Host structure
+ *
+ *	(linux Scsi_Host_Template.info routine)
+ *
+ *	Returns pointer to buffer where information was written.
+ */
+const char *
+mptscsih_info(struct Scsi_Host *SChost)
+{
+	MPT_SCSI_HOST *h;
+	int size = 0;
+
+	if (info_kbuf == NULL)
+		if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+			return info_kbuf;
+
+	h = (MPT_SCSI_HOST *)SChost->hostdata;
+	info_kbuf[0] = '\0';
+	mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0);
+	info_kbuf[size-1] = '\0';
+
+	return info_kbuf;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+	static int max_qd = 1;
+#ifdef MPT_DEBUG
+	static int max_sges = 0;
+	static int max_xfer = 0;
+#endif
+#if 0
+	static int max_num_sges = 0;
+	static int max_sgent_len = 0;
+#endif
+#if 0
+static int index_log[128];
+static int index_ent = 0;
+static __inline__ void ADD_INDEX_LOG(int req_ent)
+{
+	int i = index_ent++;
+
+	index_log[i & (128 - 1)] = req_ent;
+}
+#else
+#define ADD_INDEX_LOG(req_ent)	do { } while(0)
+#endif
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
+ *	@SCpnt: Pointer to Scsi_Cmnd structure
+ *	@done: Pointer SCSI mid-layer IO completion function
+ *
+ *	(linux Scsi_Host_Template.queuecommand routine)
+ *	This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
+ *	from a linux Scsi_Cmnd request and send it to the IOC.
+ *
+ *	Returns 0. (rtn value discarded by linux scsi mid-layer)
+ */
+int
+mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+{
+	struct Scsi_Host	*host;
+	MPT_SCSI_HOST		*hd;
+	MPT_FRAME_HDR		*mf;
+	SCSIIORequest_t		*pScsiReq;
+	int	 datadir;
+	u32	 len;
+	u32	 sgdir;
+	u32	 scsictl;
+	u32	 scsidir;
+	u32	 qtag;
+	u32	*mptr;
+	int	 sge_spill1;
+	int	 frm_sz;
+	int	 sges_left;
+	u32	 chain_offset;
+	int	 my_idx;
+	int	 i;
+
+	dmfprintk((KERN_INFO MYNAM "_qcmd: SCpnt=%p, done()=%p\n",
+		    SCpnt, done));
+
+	host = SCpnt->host;
+	hd = (MPT_SCSI_HOST *) host->hostdata;
+	
+#if 0
+	if (host->host_busy >= 60) {
+		MPT_ADAPTER *ioc = hd->ioc;
+		u16 pci_command, pci_status;
+
+		/* The IOC is probably hung, investigate status. */
+		printk("MPI: IOC probably hung IOCSTAT[%08x] INTSTAT[%08x] REPLYFIFO[%08x]\n",
+		       readl(&ioc->chip.fc9xx->DoorbellValue),
+		       readl(&ioc->chip.fc9xx->IntStatus),
+		       readl(&ioc->chip.fc9xx->ReplyFifo));
+		pci_read_config_word(ioc->pcidev, PCI_COMMAND, &pci_command);
+		pci_read_config_word(ioc->pcidev, PCI_STATUS, &pci_status);
+		printk("MPI: PCI command[%04x] status[%04x]\n", pci_command, pci_status);
+		{
+			/* DUMP req index logger. */
+			int begin, end;
+
+			begin = (index_ent - 65) & (128 - 1);
+			end = index_ent & (128 - 1);
+			printk("MPI: REQ_INDEX_HIST[");
+			while (begin != end) {
+				printk("(%04x)", index_log[begin]);
+				begin = (begin + 1) & (128 - 1);
+			}
+			printk("\n");
+		}
+		sti();
+		while(1)
+			barrier();
+	}
+#endif
+
+	SCpnt->scsi_done = done;
+
+	/* 20000617 -sralston
+	 *  GRRRRR...  Shouldn't have to do this but...
+	 *  Do explicit check for REQUEST_SENSE and cached SenseData.
+	 *  If yes, return cached SenseData.
+	 */
+#ifdef MPT_SCSI_CACHE_AUTOSENSE
+	{
+		MPT_SCSI_DEV	*mpt_sdev;
+
+		mpt_sdev = (MPT_SCSI_DEV *) SCpnt->device->hostdata;
+		if (mpt_sdev && SCpnt->cmnd[0] == REQUEST_SENSE) {
+			u8 *dest = NULL;
+
+			if (!SCpnt->use_sg)
+				dest = SCpnt->request_buffer;
+			else {
+				struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+				if (sg)
+					dest = (u8 *) (unsigned long)sg_dma_address(sg);
+			}
+
+			if (dest && mpt_sdev->sense_sz) {
+				memcpy(dest, mpt_sdev->CachedSense.data, mpt_sdev->sense_sz);
+#ifdef MPT_DEBUG
+				{
+					int  i;
+					u8  *sb;
+
+					sb = mpt_sdev->CachedSense.data;
+					if (sb && ((sb[0] & 0x70) == 0x70)) {
+						printk(KERN_WARNING MYNAM ": Returning last cached SCSI (hex) SenseData:\n");
+						printk(KERN_WARNING " ");
+						for (i = 0; i < (8 + sb[7]); i++)
+							printk("%s%02x", i == 13 ? "-" : " ", sb[i]);
+						printk("\n");
+					}
+				}
+#endif
+			}
+			SCpnt->resid = SCpnt->request_bufflen - mpt_sdev->sense_sz;
+			SCpnt->result = 0;
+/*			spin_lock(&io_request_lock);	*/
+			SCpnt->scsi_done(SCpnt);
+/*			spin_unlock(&io_request_lock);	*/
+			return 0;
+		}
+	}
+#endif
+
+	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+/*		return 1;				*/
+		return 0;
+	}
+	pScsiReq = (SCSIIORequest_t *) mf;
+
+	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+
+	ADD_INDEX_LOG(my_idx);
+
+	/* Map the data portion, if any. */
+	sges_left = SCpnt->use_sg;
+	if (sges_left) {
+		sges_left = pci_map_sg(hd->ioc->pcidev,
+				       (struct scatterlist *) SCpnt->request_buffer,
+				       sges_left,
+				       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+	} else if (SCpnt->request_bufflen) {
+		dma_addr_t buf_dma_addr;
+
+		buf_dma_addr = pci_map_single(hd->ioc->pcidev,
+					      SCpnt->request_buffer,
+					      SCpnt->request_bufflen,
+					      scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+
+		/* We hide it here for later unmap. */
+		SCpnt->SCp.ptr = (char *)(unsigned long) buf_dma_addr;
+	}
+
+	/*
+	 *  Put together a MPT SCSI request...
+	 */
+
+	/* Assume SimpleQ, NO DATA XFER for now */
+
+	len = SCpnt->request_bufflen;
+	sgdir = 0x00000000;		/* SGL IN  (host<--ioc) */
+	scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
+
+	/*
+	 *  The scsi layer should be handling this stuff
+	 *  (In 2.3.x it does -DaveM)
+	 */
+
+	/*  BUG FIX!  19991030 -sralston
+	 *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
+	 *    Seems we may receive a buffer (len>0) even when there
+	 *    will be no data transfer!  GRRRRR...
+	 */
+	datadir = mptscsih_io_direction(SCpnt);
+	if (datadir < 0) {
+		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */
+	} else if (datadir > 0) {
+		sgdir	= 0x04000000;			/* SGL OUT  (host-->ioc) */
+		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */
+	} else {
+		len = 0;
+	}
+
+	qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+
+	/*
+	 *  Attach tags to the devices
+	 */
+	if (SCpnt->device->tagged_supported) {
+		/*
+		 *  Some drives are too stupid to handle fairness issues
+		 *  with tagged queueing. We throw in the odd ordered
+		 *  tag to stop them starving themselves.
+		 */
+		if ((jiffies - hd->qtag_tick) > (5*HZ)) {
+			qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
+			hd->qtag_tick = jiffies;
+
+#if 0
+			/* These are ALWAYS zero!
+			 * (Because this is a place for the device driver to dynamically
+			 *  assign tag numbers any way it sees fit.  That's why -DaveM)
+			 */
+			dprintk((KERN_DEBUG MYNAM ": sc->device->current_tag = %08x\n",
+					SCpnt->device->current_tag));
+			dprintk((KERN_DEBUG MYNAM ": sc->tag                 = %08x\n",
+					SCpnt->tag));
+#endif
+		}
+#if 0
+		else {
+			/* Hmmm...  I always see value of 0 here,
+			 *  of which {HEAD_OF, ORDERED, SIMPLE} are NOT!  -sralston
+			 * (Because this is a place for the device driver to dynamically
+			 *  assign tag numbers any way it sees fit.  That's why -DaveM)
+			 *
+			 * if (SCpnt->tag == HEAD_OF_QUEUE_TAG)
+			 */
+			if (SCpnt->device->current_tag == HEAD_OF_QUEUE_TAG)
+				qtag = MPI_SCSIIO_CONTROL_HEADOFQ;
+			else if (SCpnt->tag == ORDERED_QUEUE_TAG)
+				qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
+		}
+#endif
+	}
+
+	scsictl = scsidir | qtag;
+
+	frm_sz = hd->ioc->req_sz;
+
+	/* Ack!
+	 * sge_spill1 = 9;
+	 */
+	sge_spill1 = (frm_sz - (sizeof(SCSIIORequest_t) - sizeof(SGEIOUnion_t) + sizeof(SGEChain32_t))) / 8;
+	/*  spill1: for req_sz == 128 (128-48==80, 80/8==10 SGEs max, first time!), --> use 9
+	 *  spill1: for req_sz ==  96 ( 96-48==48, 48/8== 6 SGEs max, first time!), --> use 5
+	 */
+	dsgprintk((KERN_INFO MYNAM ": SG: %x     spill1 = %d\n",
+		   my_idx, sge_spill1));
+
+#ifdef MPT_DEBUG
+	if (sges_left > max_sges) {
+		max_sges = sges_left;
+		dprintk((KERN_INFO MYNAM ": MPT_MaxSges = %d\n", max_sges));
+	}
+#endif
+#if 0
+	if (sges_left > max_num_sges) {
+		max_num_sges = sges_left;
+		printk(KERN_INFO MYNAM ": MPT_MaxNumSges = %d\n", max_num_sges);
+	}
+#endif
+
+	dsgprintk((KERN_INFO MYNAM ": SG: %x     sges_left = %d (initially)\n",
+		   my_idx, sges_left));
+
+	chain_offset = 0;
+	if (sges_left > (sge_spill1+1)) {
+#if 0
+		chain_offset = 0x1E;
+#endif
+		chain_offset = (frm_sz - 8) / 4;
+	}
+
+	pScsiReq->TargetID = SCpnt->target;
+	pScsiReq->Bus = hd->port;
+	pScsiReq->ChainOffset = chain_offset;
+	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+	pScsiReq->CDBLength = SCpnt->cmd_len;
+
+/* We have 256 bytes alloc'd per IO; let's use it. */
+/*	pScsiReq->SenseBufferLength = SNS_LEN(SCpnt);	*/
+	pScsiReq->SenseBufferLength = 255;
+
+	pScsiReq->Reserved = 0;
+	pScsiReq->MsgFlags = 0;
+	pScsiReq->LUN[0] = 0;
+	pScsiReq->LUN[1] = SCpnt->lun;
+	pScsiReq->LUN[2] = 0;
+	pScsiReq->LUN[3] = 0;
+	pScsiReq->LUN[4] = 0;
+	pScsiReq->LUN[5] = 0;
+	pScsiReq->LUN[6] = 0;
+	pScsiReq->LUN[7] = 0;
+	pScsiReq->Control = cpu_to_le32(scsictl);
+
+	/*
+	 *  Write SCSI CDB into the message
+	 */
+	for (i = 0; i < 12; i++)
+		pScsiReq->CDB[i] = SCpnt->cmnd[i];
+	for (i = 12; i < 16; i++)
+		pScsiReq->CDB[i] = 0;
+
+	/* DataLength */
+	pScsiReq->DataLength = cpu_to_le32(len);
+
+	/* SenseBuffer low address */
+	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_pool_dma + (my_idx * 256));
+
+	mptr = (u32 *) &pScsiReq->SGL;
+
+	/*
+	 *  Now fill in the SGList...
+	 *  NOTES: For 128 byte req_sz, we can hold up to 10 simple SGE's
+	 *  in the remaining request frame.  We -could- do unlimited chains
+	 *  but each chain buffer can only be req_sz bytes in size, and
+	 *  we lose one SGE whenever we chain.
+	 *  For 128 req_sz, we can hold up to 16 SGE's per chain buffer.
+	 *  For practical reasons, limit ourselves to 1 overflow chain buffer;
+	 *  giving us 9 + 16 == 25 SGE's max.
+	 *  At 4 Kb per SGE, that yields 100 Kb max transfer.
+	 *
+	 *  (This code needs to be completely changed when/if 64-bit DMA
+	 *   addressing is used, since we will be able to fit much less than
+	 *   10 embedded SG entries. -DaveM)
+	 */
+	if (sges_left) {
+		struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+		u32  v1, v2;
+		int  sge_spill2;
+		int  sge_cur_spill;
+		int  sgCnt;
+		u8  *pSgBucket;
+		int  chain_sz;
+
+		len = 0;
+
+		/*	sge_spill2 = 15;
+		 *  spill2: for req_sz == 128 (128/8==16 SGEs max, first time!), --> use 15
+		 *  spill2: for req_sz ==  96 ( 96/8==12 SGEs max, first time!), --> use 11
+		 */
+		sge_spill2 = frm_sz / 8 - 1;
+		dsgprintk((KERN_INFO MYNAM ": SG: %x     spill2 = %d\n",
+			   my_idx, sge_spill2));
+
+		pSgBucket = NULL;
+		sgCnt = 0;
+		sge_cur_spill = sge_spill1;
+		while (sges_left) {
+#if 0
+			if (sg_dma_len(sg) > max_sgent_len) {
+				max_sgent_len = sg_dma_len(sg);
+				printk(KERN_INFO MYNAM ": MPT_MaxSgentLen = %d\n", max_sgent_len);
+			}
+#endif
+			/* Write one simple SGE */
+			v1 = sgdir | 0x10000000 | sg_dma_len(sg);
+			len += sg_dma_len(sg);
+			v2 = sg_dma_address(sg);
+			dsgprintk((KERN_INFO MYNAM ": SG: %x     Writing SGE @%p: %08x %08x, sges_left=%d\n",
+				   my_idx, mptr, v1, v2, sges_left));
+			*mptr++ = cpu_to_le32(v1);
+			*mptr++ = cpu_to_le32(v2);
+			sg++;
+			sgCnt++;
+
+			if (--sges_left == 0) {
+				/* re-write 1st word of previous SGE with SIMPLE,
+				 * LE, EOB, and EOL bits!
+				 */
+				v1 = 0xD1000000 | sgdir | sg_dma_len(sg-1);
+				dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (VERY LAST SGE!)\n",
+					   my_idx, mptr-2, v1));
+				*(mptr - 2) = cpu_to_le32(v1);
+			} else {
+				if ((sges_left > 1) && ((sgCnt % sge_cur_spill) == 0)) {
+					dsgprintk((KERN_INFO MYNAM ": SG: %x     SG spill at modulo 0!\n",
+						   my_idx));
+
+					/* Fixup previous SGE with LE bit! */
+					v1 = sgdir | 0x90000000 | sg_dma_len(sg-1);
+					dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (LAST BUCKET SGE!)\n",
+						   my_idx, mptr-2, v1));
+					*(mptr - 2) = cpu_to_le32(v1);
+
+					chain_offset = 0;
+					/* Going to need another chain? */
+					if (sges_left > (sge_spill2+1)) {
+#if 0
+						chain_offset = 0x1E;
+#endif
+						chain_offset = (frm_sz - 8) / 4;
+						chain_sz = frm_sz;
+					} else {
+						chain_sz = sges_left * 8;
+					}
+
+					/* write chain SGE at mptr. */
+					v1 = 0x30000000 | chain_offset<<16 | chain_sz;
+					if (pSgBucket == NULL) {
+						pSgBucket = hd->SgHunks
+							+ (my_idx * frm_sz * MPT_SG_BUCKETS_PER_HUNK);
+					} else {
+						pSgBucket += frm_sz;
+					}
+					v2 = (hd->SgHunksDMA +
+					      ((u8 *)pSgBucket - (u8 *)hd->SgHunks));
+					dsgprintk((KERN_INFO MYNAM ": SG: %x     Writing SGE @%p: %08x %08x (CHAIN!)\n",
+						   my_idx, mptr, v1, v2));
+					*(mptr++) = cpu_to_le32(v1);
+					*(mptr) = cpu_to_le32(v2);
+
+					mptr = (u32 *) pSgBucket;
+					sgCnt = 0;
+					sge_cur_spill = sge_spill2;
+				}
+			}
+		}
+	} else {
+		dsgprintk((KERN_INFO MYNAM ": SG: non-SG for %p, len=%d\n",
+			   SCpnt, SCpnt->request_bufflen));
+
+		if (len > 0) {
+			dma_addr_t buf_dma_addr;
+
+			buf_dma_addr = (dma_addr_t) (unsigned long)SCpnt->SCp.ptr;
+			*(mptr++) = cpu_to_le32(0xD1000000|sgdir|SCpnt->request_bufflen);
+			*(mptr++) = cpu_to_le32(buf_dma_addr);
+		}
+	}
+
+#ifdef MPT_DEBUG
+	/* if (SCpnt->request_bufflen > max_xfer) */
+	if (len > max_xfer) {
+		max_xfer = len;
+		dprintk((KERN_INFO MYNAM ": MPT_MaxXfer = %d\n", max_xfer));
+	}
+#endif
+
+	hd->ScsiLookup[my_idx] = SCpnt;
+
+	/* Main banana... */
+	mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+
+	atomic_inc(&queue_depth);
+	if (atomic_read(&queue_depth) > max_qd) {
+		max_qd = atomic_read(&queue_depth);
+		dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));
+	}
+
+	mb();
+	dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt));
+
+	return 0;
+}
+
+#ifdef MPT_SCSI_USE_NEW_EH		/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    mptscsih_abort
+    Returns: 0=SUCCESS, else FAILED
+*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
+ *
+ *	(linux Scsi_Host_Template.eh_abort_handler routine)
+ *
+ *	Returns SUCCESS or FAILED.  
+ */
+int
+mptscsih_abort(Scsi_Cmnd * SCpnt)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	MPT_SCSI_HOST	*hd;
+	u32		*msg;
+	u32		 ctx2abort;
+	int		 i;
+
+	printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
+
+	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+		return FAILED;
+	}
+
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	msg = (u32 *) mf;
+
+	pScsiTm->TargetID = SCpnt->target;
+	pScsiTm->Bus = hd->port;
+	pScsiTm->ChainOffset = 0;
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+
+	pScsiTm->Reserved = 0;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+	pScsiTm->Reserved1 = 0;
+	pScsiTm->MsgFlags = 0;
+
+	for (i = 0; i < 8; i++) {
+		u8 val = 0;
+		if (i == 1)
+			val = SCpnt->lun;
+		pScsiTm->LUN[i] = val;
+	}
+
+	for (i = 0; i < 7; i++)
+		pScsiTm->Reserved2[i] = 0;
+
+	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
+	 * (the IO to be ABORT'd)
+	 *
+	 * NOTE: Since we do not byteswap MsgContext, we do not
+	 *	 swap it here either.  It is an opaque cookie to
+	 *	 the controller, so it does not matter. -DaveM
+	 */
+	ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
+	dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
+	pScsiTm->TaskMsgContext = ctx2abort;
+
+	wmb();
+
+/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
+	mpt_put_msg_frame(hd->ioc->id, mf);
+*/
+/* FIXME!  Check return status! */
+	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
+
+	wmb();
+
+	return SUCCESS;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *
+ *	(linux Scsi_Host_Template.eh_bus_reset_handler routine)
+ *
+ *	Returns SUCCESS or FAILED.
+ */
+int
+mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	MPT_SCSI_HOST	*hd;
+	u32		*msg;
+	int		 i;
+
+	printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
+
+	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+		return FAILED;
+	}
+
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	msg = (u32 *) mf;
+
+	pScsiTm->TargetID = SCpnt->target;
+	pScsiTm->Bus = hd->port;
+	pScsiTm->ChainOffset = 0;
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+
+	pScsiTm->Reserved = 0;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
+	pScsiTm->Reserved1 = 0;
+	pScsiTm->MsgFlags = 0;
+
+	for (i = 0; i < 8; i++)
+		pScsiTm->LUN[i] = 0;
+
+	/* Control: No data direction, set task mgmt bit? */
+	for (i = 0; i < 7; i++)
+		pScsiTm->Reserved2[i] = 0;
+
+	pScsiTm->TaskMsgContext = cpu_to_le32(0);
+
+	wmb();
+
+/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
+	mpt_put_msg_frame(hd->ioc->id, mf);
+*/
+/* FIXME!  Check return status! */
+	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
+
+	wmb();
+
+	return SUCCESS;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *
+ *	(linux Scsi_Host_Template.eh_dev_reset_handler routine)
+ *
+ *	Returns SUCCESS or FAILED.
+ */
+int
+mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	MPT_SCSI_HOST	*hd;
+	u32		*msg;
+	int		 i;
+
+	printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
+
+	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+		return FAILED;
+	}
+
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	msg = (u32*)mf;
+
+	pScsiTm->TargetID = SCpnt->target;
+	pScsiTm->Bus = hd->port;
+	pScsiTm->ChainOffset = 0;
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+
+	pScsiTm->Reserved = 0;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+	pScsiTm->Reserved1 = 0;
+	pScsiTm->MsgFlags = 0;
+
+	/* _TARGET_RESET goes to LUN 0 always! */
+	for (i = 0; i < 8; i++)
+		pScsiTm->LUN[i] = 0;
+
+	/* Control: No data direction, set task mgmt bit? */
+	for (i = 0; i < 7; i++)
+		pScsiTm->Reserved2[i] = 0;
+
+	pScsiTm->TaskMsgContext = cpu_to_le32(0);
+
+	wmb();
+
+/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
+	mpt_put_msg_frame(hd->ioc->id, mf);
+*/
+/* FIXME!  Check return status! */
+	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
+
+	wmb();
+
+	return SUCCESS;
+}
+
+#if 0	/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_host_reset - Perform a SCSI host adapter RESET!
+ *	new_eh variant
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *
+ *	(linux Scsi_Host_Template.eh_host_reset_handler routine)
+ *
+ *	Returns SUCCESS or FAILED.
+ */
+int
+mptscsih_host_reset(Scsi_Cmnd * SCpnt)
+{
+	return FAILED;
+}
+#endif	/* } */
+
+#else		/* MPT_SCSI old EH stuff... */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_old_abort - Abort linux Scsi_Cmnd routine
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
+ *
+ *	(linux Scsi_Host_Template.abort routine)
+ *
+ *	Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}.
+ */
+int
+mptscsih_old_abort(Scsi_Cmnd *SCpnt)
+{
+	MPT_SCSI_HOST		*hd;
+	MPT_FRAME_HDR		*mf;
+	struct tq_struct	*ptaskfoo;
+	unsigned long		 flags;
+
+	printk(KERN_WARNING MYNAM ": Scheduling _ABORT SCSI IO (=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
+		SCpnt->result = DID_ABORT << 16;
+		SCpnt->scsi_done(SCpnt);
+		return SCSI_ABORT_SUCCESS;
+	}
+
+	/*
+	 *  Check to see if there's already an ABORT queued for this guy.
+	 */
+	mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
+	if (mf != NULL) {
+		return SCSI_ABORT_PENDING;
+	}
+
+	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+		return SCSI_ABORT_BUSY;
+	}
+
+	/*
+	 *  Add ourselves to (end of) mpt_scsih_taskQ.
+	 *  Check to see if our _bh is running.  If NOT, schedule it.
+	 */
+	dslprintk((KERN_INFO MYNAM ": spinlock#2\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+	mpt_scsih_taskQ_cnt++;
+	/* Yikes - linkage! */
+/*	SCpnt->host_scribble = (unsigned char *)mf;	*/
+	mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+	mf->u.frame.linkage.argp1 = SCpnt;
+	if (! mpt_scsih_taskQ_bh_active) {
+		mpt_scsih_taskQ_bh_active = 1;
+		/*
+		 *  Oh how cute, no alloc/free/mgmt needed if we use
+		 *  (bottom/unused portion of) MPT request frame.
+		 */
+		ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo));
+		ptaskfoo->sync = 0;
+		ptaskfoo->routine = mptscsih_taskmgmt_bh;
+		ptaskfoo->data = SCpnt;
+
+		SCHEDULE_TASK(ptaskfoo);
+	}
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+	return SCSI_ABORT_PENDING;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_old_reset - Perform a SCSI BUS_RESET!
+ *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *	@reset_flags: (not used?)
+ *
+ *	(linux Scsi_Host_Template.reset routine)
+ *
+ *	Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}.
+ */
+int
+mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+{
+	MPT_SCSI_HOST		*hd;
+	MPT_FRAME_HDR		*mf;
+	struct tq_struct	*ptaskfoo;
+	unsigned long		 flags;
+
+	printk(KERN_WARNING MYNAM ": Scheduling _BUS_RESET (=%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
+		SCpnt->result = DID_RESET << 16;
+		SCpnt->scsi_done(SCpnt);
+		return SCSI_RESET_SUCCESS;
+	}
+
+	/*
+	 *  Check to see if there's already a BUS_RESET queued for this guy.
+	 */
+	mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS);
+	if (mf != NULL) {
+		return SCSI_RESET_PENDING;
+	}
+
+	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+/*		SCpnt->result = DID_SOFT_ERROR << 16;	*/
+		SCpnt->result = STS_BUSY;
+		SCpnt->scsi_done(SCpnt);
+		return SCSI_RESET_PUNT;
+	}
+
+	/*
+	 *  Add ourselves to (end of) mpt_scsih_taskQ.
+	 *  Check to see if our _bh is running.  If NOT, schedule it.
+	 */
+	dslprintk((KERN_INFO MYNAM ": spinlock#3\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+	mpt_scsih_taskQ_cnt++;
+	/* Yikes - linkage! */
+/*	SCpnt->host_scribble = (unsigned char *)mf;	*/
+	mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
+	mf->u.frame.linkage.argp1 = SCpnt;
+	if (! mpt_scsih_taskQ_bh_active) {
+		mpt_scsih_taskQ_bh_active = 1;
+		/*
+		 *  Oh how cute, no alloc/free/mgmt needed if we use
+		 *  (bottom/unused portion of) MPT request frame.
+		 */
+		ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo));
+		ptaskfoo->sync = 0;
+		ptaskfoo->routine = mptscsih_taskmgmt_bh;
+		ptaskfoo->data = SCpnt;
+
+		SCHEDULE_TASK(ptaskfoo);
+	}
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+	return SCSI_RESET_PENDING;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler
+ *	@sc: (unused)
+ *
+ *	This routine (thread) is active whenever there are any outstanding
+ *	SCSI task management requests for a SCSI host adapter.
+ *	IMPORTANT!  This routine is scheduled therefore should never be
+ *	running in ISR context.  i.e., it's safe to sleep here.
+ */
+void
+mptscsih_taskmgmt_bh(void *sc)
+{
+	Scsi_Cmnd	*SCpnt;
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	MPT_SCSI_HOST	*hd;
+	u32		 ctx2abort = 0;
+	int		 i;
+	unsigned long	 flags;
+	u8		 task_type;
+
+	dslprintk((KERN_INFO MYNAM ": spinlock#4\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	mpt_scsih_taskQ_bh_active = 1;
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+	while (1) {
+		/*
+		 *  We MUST remove item from taskQ *before* we format the
+		 *  frame as a SCSITaskMgmt request and send it down to the IOC.
+		 */
+		dslprintk((KERN_INFO MYNAM ": spinlock#5\n"));
+		spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+		if (Q_IS_EMPTY(&mpt_scsih_taskQ)) {
+			spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+			break;
+		}
+		mf = mpt_scsih_taskQ.head;
+		Q_DEL_ITEM(&mf->u.frame.linkage);
+		mpt_scsih_taskQ_cnt--;
+		mpt_scsih_active_taskmgmt_mf = mf;
+		spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+		SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
+		if (SCpnt == NULL) {
+			printk(KERN_ERR MYNAM ": ERROR: TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt);
+			continue;
+		}
+		pScsiTm = (SCSITaskMgmt_t *) mf;
+
+		for (i = 0; i < 8; i++) {
+			pScsiTm->LUN[i] = 0;
+		}
+
+		task_type = mf->u.frame.linkage.arg1;
+		if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+		{
+			printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf:sc=%p:%p)\n", mf, SCpnt);
+
+			/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
+			 * (the IO to be ABORT'd)
+			 *
+			 * NOTE: Since we do not byteswap MsgContext, we do not
+			 *	 swap it here either.  It is an opaque cookie to
+			 *	 the controller, so it does not matter. -DaveM
+			 */
+			ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
+			pScsiTm->LUN[1] = SCpnt->lun;
+		}
+		else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
+		{
+			printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf:sc=%p:%p)\n", mf, SCpnt);
+		}
+#if 0
+		else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {}
+		else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {}
+#endif
+
+		printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
+
+		hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
+
+		pScsiTm->TargetID = SCpnt->target;
+		pScsiTm->Bus = hd->port;
+		pScsiTm->ChainOffset = 0;
+		pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+
+		pScsiTm->Reserved = 0;
+		pScsiTm->TaskType = task_type;
+		pScsiTm->Reserved1 = 0;
+		pScsiTm->MsgFlags = 0;
+
+		for (i = 0; i < 7; i++)
+			pScsiTm->Reserved2[i] = 0;
+
+		dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
+		pScsiTm->TaskMsgContext = ctx2abort;
+
+		/* Control: No data direction, set task mgmt bit? */
+
+		/*
+		 *  As of MPI v0.10 this request can NOT be sent (normally)
+		 *  via FIFOs.	So we can't:
+		 *		mpt_put_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+		 *  SCSITaskMgmt requests MUST be sent ONLY via
+		 *  Doorbell/handshake now.   :-(
+		 *
+		 *  FIXME!  Check return status!
+		 */
+		(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), (u32*)mf);
+
+		/* Spin-Wait for TaskMgmt complete!!! */
+		while (mpt_scsih_active_taskmgmt_mf != NULL) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/2);
+		}
+	}
+
+	dslprintk((KERN_INFO MYNAM ": spinlock#6\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	mpt_scsih_taskQ_bh_active = 0;
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+
+	return;
+}
+
+#endif		/* } */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_taskmgmt_complete - Callback routine, gets registered to
+ *	Fusion MPT base	driver
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@mf: Pointer to SCSI task mgmt request frame
+ *	@r: Pointer to SCSI task mgmt reply frame
+ *
+ *	This routine is called from mptbase.c::mpt_interrupt() at the completion
+ *	of any SCSI task management request.
+ *	This routine is registered with the MPT (base) driver at driver
+ *	load/init time via the mpt_register() API call.
+ *
+ *	Returns 1 indicating alloc'd request frame ptr should be freed.
+ */
+static int
+mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r)
+{
+	SCSITaskMgmtReply_t	*pScsiTmReply;
+	SCSITaskMgmt_t		*pScsiTmReq;
+	u8			 tmType;
+#ifndef MPT_SCSI_USE_NEW_EH
+	unsigned long		 flags;
+#endif
+
+	dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt completed mf=%p, r=%p\n",
+		 mf, r));
+
+#ifndef MPT_SCSI_USE_NEW_EH
+	dslprintk((KERN_INFO MYNAM ": spinlock#7\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	/* It better be the active one! */
+	if (mf != mpt_scsih_active_taskmgmt_mf) {
+		printk(KERN_ERR MYNAM ": ERROR! Non-active TaskMgmt (=%p) completed!\n", mf);
+		mpt_scsih_active_taskmgmt_mf = NULL;
+		spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+		return 1;
+	}
+
+#ifdef MPT_DEBUG
+	if ((mf == NULL) ||
+	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
+		printk(KERN_ERR MYNAM ": ERROR! NULL or BAD TaskMgmt ptr (=%p)!\n", mf);
+		mpt_scsih_active_taskmgmt_mf = NULL;
+		spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+		return 1;
+	}
+#endif
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+#endif
+
+	if (r != NULL) {
+		pScsiTmReply = (SCSITaskMgmtReply_t*)r;
+		pScsiTmReq = (SCSITaskMgmt_t*)mf;
+
+		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
+		tmType = pScsiTmReq->TaskType;
+
+		dprintk((KERN_INFO MYNAM ": TaskType = %d\n", tmType));
+		dprintk((KERN_INFO MYNAM ": TerminationCount = %d\n",
+			 le32_to_cpu(pScsiTmReply->TerminationCount)));
+
+		/* Error?  (anything non-zero?) */
+		if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
+			dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt (%d) - Oops!\n", tmType));
+			dprintk((KERN_INFO MYNAM ": IOCStatus = %04xh\n",
+				 le16_to_cpu(pScsiTmReply->IOCStatus)));
+			dprintk((KERN_INFO MYNAM ": IOCLogInfo = %08xh\n",
+				 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+		} else {
+			dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt (%d) SUCCESS!\n", tmType));
+		}
+	}
+
+#ifndef MPT_SCSI_USE_NEW_EH
+	/*
+	 *  Signal to _bh thread that we finished.
+	 */
+	dslprintk((KERN_INFO MYNAM ": spinlock#8\n"));
+	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
+	mpt_scsih_active_taskmgmt_mf = NULL;
+	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
+#endif
+
+	return 1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	This is anyones guess quite frankly.
+ */
+
+int
+mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
+{
+	int size;
+
+	size = disk->capacity;
+	ip[0] = 64;				/* heads			*/
+	ip[1] = 32;				/* sectors			*/
+	if ((ip[2] = size >> 11) > 1024) {	/* cylinders, test for big disk */
+		ip[0] = 255;			/* heads			*/
+		ip[1] = 63;			/* sectors			*/
+		ip[2] = size / (255 * 63);	/* cylinders			*/
+	}
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Private routines...
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* 19991030 -sralston
+ *  Return absolute SCSI data direction:
+ *     1 = _DATA_OUT
+ *     0 = _DIR_NONE
+ *    -1 = _DATA_IN
+ */
+static int
+mptscsih_io_direction(Scsi_Cmnd *cmd)
+{
+	switch (cmd->cmnd[0]) {
+	/*  _DATA_OUT commands	*/
+	case WRITE_6:		case WRITE_10:		case WRITE_12:
+	case WRITE_LONG:	case WRITE_SAME:	case WRITE_BUFFER:
+	case WRITE_VERIFY:	case WRITE_VERIFY_12:
+	case COMPARE:		case COPY:		case COPY_VERIFY:
+	case SEARCH_EQUAL:	case SEARCH_HIGH:	case SEARCH_LOW:
+	case SEARCH_EQUAL_12:	case SEARCH_HIGH_12:	case SEARCH_LOW_12:
+	case MODE_SELECT:	case MODE_SELECT_10:	case LOG_SELECT:
+	case SEND_DIAGNOSTIC:	case CHANGE_DEFINITION: case UPDATE_BLOCK:
+	case SET_WINDOW:	case MEDIUM_SCAN:	case SEND_VOLUME_TAG:
+	case REASSIGN_BLOCKS:
+	case PERSISTENT_RESERVE_OUT:
+	case 0xea:
+		return 1;
+
+	/*  No data transfer commands  */
+	case SEEK_6:		case SEEK_10:
+	case RESERVE:		case RELEASE:
+	case TEST_UNIT_READY:
+	case START_STOP:
+	case ALLOW_MEDIUM_REMOVAL:
+		return 0;
+
+	/*  Conditional data transfer commands	*/
+	case FORMAT_UNIT:
+		if (cmd->cmnd[1] & 0x10)	/* FmtData (data out phase)? */
+			return 1;
+		else
+			return 0;
+
+	case VERIFY:
+		if (cmd->cmnd[1] & 0x02)	/* VERIFY:BYTCHK (data out phase)? */
+			return 1;
+		else
+			return 0;
+
+	case RESERVE_10:
+		if (cmd->cmnd[1] & 0x03)	/* RESERSE:{LongID|Extent} (data out phase)? */
+			return 1;
+		else
+			return 0;
+
+#if 0
+	case REZERO_UNIT:	/* (or REWIND) */
+	case SPACE:
+	case ERASE:		case ERASE_10:
+	case SYNCHRONIZE_CACHE:
+	case LOCK_UNLOCK_CACHE:
+#endif
+
+	/*  Must be data _IN!  */
+	default:
+		return -1;
+	}
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+{
+	MPT_SCSI_DEV	*mpt_sdev = NULL;
+	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
+	char		 devFoo[32];
+	IO_Info_t	 thisIo;
+
+	if (sc && sc->device)
+		mpt_sdev = (MPT_SCSI_DEV*) sc->device->hostdata;
+
+	if (sense_count) {
+		u8 *sense_data;
+		int req_index;
+
+		/* Copy the sense received into the scsi command block. */
+		req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+		sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * 256));
+		memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
+		/* Cache SenseData for this SCSI device! */
+		if (mpt_sdev) {
+			memcpy(mpt_sdev->CachedSense.data, sense_data, sense_count);
+			mpt_sdev->sense_sz = sense_count;
+		}
+	} else {
+		dprintk((KERN_INFO MYNAM ": Hmmm... SenseData len=0! (?)\n"));
+	}
+
+
+	thisIo.cdbPtr = sc->cmnd;
+	thisIo.sensePtr = sc->sense_buffer;
+	thisIo.SCSIStatus = pScsiReply->SCSIStatus;
+	thisIo.DoDisplay = 1;
+	sprintf(devFoo, "ioc%d,scsi%d:%d", hd->ioc->id, sc->target, sc->lun);
+	thisIo.DevIDStr = devFoo;
+/* fubar */
+	thisIo.dataPtr = NULL;
+	thisIo.inqPtr = NULL;
+	if (sc->device) {
+		thisIo.inqPtr = sc->device->vendor-8;		/* FIXME!!! */
+	}
+	(void) mpt_ScsiHost_ErrorReport(&thisIo);
+
+	return;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static u32
+SCPNT_TO_MSGCTX(Scsi_Cmnd *sc)
+{
+	MPT_SCSI_HOST *hd;
+	MPT_FRAME_HDR *mf;
+	int i;
+
+	hd = (MPT_SCSI_HOST *) sc->host->hostdata;
+
+	for (i = 0; i < hd->ioc->req_depth; i++) {
+		if (hd->ScsiLookup[i] == sc) {
+			mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
+			return mf->u.frame.hwhdr.msgctxu.MsgContext;
+		}
+	}
+
+	return -1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/* see mptscsih.h */
+
+#ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
+	static Scsi_Host_Template driver_template = MPT_SCSIHOST;
+#	include "../../scsi/scsi_module.c"
+#endif
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+
+	dprintk((KERN_INFO MYNAM ": MPT event (=%02Xh) routed to SCSI host driver!\n", event));
+
+	switch (event) {
+	case MPI_EVENT_UNIT_ATTENTION:			/* 03 */
+		/* FIXME! */
+		break;
+	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
+		/* FIXME! */
+		break;
+	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
+		/* FIXME! */
+		break;
+	case MPI_EVENT_LOGOUT:				/* 09 */
+		/* FIXME! */
+		break;
+
+		/*
+		 *  CHECKME! Don't think we need to do
+		 *  anything for these, but...
+		 */
+	case MPI_EVENT_RESCAN:				/* 06 */
+	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
+	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
+		/*
+		 *  CHECKME!  Falling thru...
+		 */
+
+	case MPI_EVENT_NONE:				/* 00 */
+	case MPI_EVENT_LOG_DATA:			/* 01 */
+	case MPI_EVENT_STATE_CHANGE:			/* 02 */
+	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
+	default:
+		dprintk((KERN_INFO MYNAM ": Ignoring event (=%02Xh)\n", event));
+		break;
+	}
+
+	return 1;		/* currently means nothing really */
+}
+
+#if 0		/* { */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	scsiherr.c - Fusion MPT SCSI Host driver error handling/reporting.
+ *
+ *	drivers/message/fusion/scsiherr.c
+ */
+
+//extern const char	**mpt_ScsiOpcodesPtr;	/* needed by mptscsih.c */
+//extern ASCQ_Table_t	 *mpt_ASCQ_TablePtr;
+//extern int		  mpt_ASCQ_TableSz;
+
+/*  Lie!  */
+#define MYNAM	"mptscsih"
+
+#endif		/* } */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Private data...
+ */
+static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* old symsense.c stuff... */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * Private data...
+ * To protect ourselves against those that would pass us bogus pointers
+ */
+static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
+    = { 0x1F, 0x00, 0x00, 0x00,
+	0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
+    = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00 };
+static u8 dummyCDB[16]
+    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static u8 dummyScsiData[16]
+    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+#if 0
+static const char *PeripheralDeviceTypeString[32] = {
+	"Direct-access",		/* 00h */
+	"Sequential-access",		/* 01h */
+	"Printer",			/* 02h */
+	"Processor",			/* 03h */
+			/*"Write-Once-Read-Multiple",*/	/* 04h */
+	"WORM",				/* 04h */
+	"CD-ROM",			/* 05h */
+	"Scanner",			/* 06h */
+	"Optical memory",		/* 07h */
+	"Media Changer",		/* 08h */
+	"Communications",		/* 09h */
+	"(Graphics arts pre-press)",	/* 0Ah */
+	"(Graphics arts pre-press)",	/* 0Bh */
+	"Array controller",		/* 0Ch */
+	"Enclosure services",		/* 0Dh */
+	"Simplified direct-access",	/* 0Eh */
+	"Reserved-0Fh",			/* 0Fh */
+	"Reserved-10h",			/* 10h */
+	"Reserved-11h",			/* 11h */
+	"Reserved-12h",			/* 12h */
+	"Reserved-13h",			/* 13h */
+	"Reserved-14h",			/* 14h */
+	"Reserved-15h",			/* 15h */
+	"Reserved-16h",			/* 16h */
+	"Reserved-17h",			/* 17h */
+	"Reserved-18h",			/* 18h */
+	"Reserved-19h",			/* 19h */
+	"Reserved-1Ah",			/* 1Ah */
+	"Reserved-1Bh",			/* 1Bh */
+	"Reserved-1Ch",			/* 1Ch */
+	"Reserved-1Dh",			/* 1Dh */
+	"Reserved-1Eh",			/* 1Eh */
+	"Unknown"			/* 1Fh */
+};
+#endif
+
+static char *ScsiStatusString[] = {
+	"GOOD",					/* 00h */
+	NULL,					/* 01h */
+	"CHECK CONDITION",			/* 02h */
+	NULL,					/* 03h */
+	"CONDITION MET",			/* 04h */
+	NULL,					/* 05h */
+	NULL,					/* 06h */
+	NULL,					/* 07h */
+	"BUSY",					/* 08h */
+	NULL,					/* 09h */
+	NULL,					/* 0Ah */
+	NULL,					/* 0Bh */
+	NULL,					/* 0Ch */
+	NULL,					/* 0Dh */
+	NULL,					/* 0Eh */
+	NULL,					/* 0Fh */
+	"INTERMEDIATE",				/* 10h */
+	NULL,					/* 11h */
+	NULL,					/* 12h */
+	NULL,					/* 13h */
+	"INTERMEDIATE-CONDITION MET",		/* 14h */
+	NULL,					/* 15h */
+	NULL,					/* 16h */
+	NULL,					/* 17h */
+	"RESERVATION CONFLICT",			/* 18h */
+	NULL,					/* 19h */
+	NULL,					/* 1Ah */
+	NULL,					/* 1Bh */
+	NULL,					/* 1Ch */
+	NULL,					/* 1Dh */
+	NULL,					/* 1Eh */
+	NULL,					/* 1Fh */
+	NULL,					/* 20h */
+	NULL,					/* 21h */
+	"COMMAND TERMINATED",			/* 22h */
+	NULL,					/* 23h */
+	NULL,					/* 24h */
+	NULL,					/* 25h */
+	NULL,					/* 26h */
+	NULL,					/* 27h */
+	"TASK SET FULL",			/* 28h */
+	NULL,					/* 29h */
+	NULL,					/* 2Ah */
+	NULL,					/* 2Bh */
+	NULL,					/* 2Ch */
+	NULL,					/* 2Dh */
+	NULL,					/* 2Eh */
+	NULL,					/* 2Fh */
+	"ACA ACTIVE",				/* 30h */
+	NULL
+};
+
+static const char *ScsiCommonOpString[] = {
+	"TEST UNIT READY",			/* 00h */
+	"REZERO UNIT (REWIND)",			/* 01h */
+	NULL,					/* 02h */
+	"REQUEST_SENSE",			/* 03h */
+	"FORMAT UNIT (MEDIUM)",			/* 04h */
+	"READ BLOCK LIMITS",			/* 05h */
+	NULL,					/* 06h */
+	"REASSIGN BLOCKS",			/* 07h */
+	"READ(6)",				/* 08h */
+	NULL,					/* 09h */
+	"WRITE(6)",				/* 0Ah */
+	"SEEK(6)",				/* 0Bh */
+	NULL,					/* 0Ch */
+	NULL,					/* 0Dh */
+	NULL,					/* 0Eh */
+	"READ REVERSE",				/* 0Fh */
+	"WRITE_FILEMARKS",			/* 10h */
+	"SPACE(6)",				/* 11h */
+	"INQUIRY",				/* 12h */
+	NULL
+};
+
+static const char *SenseKeyString[] = {
+	"NO SENSE",				/* 0h */
+	"RECOVERED ERROR",			/* 1h */
+	"NOT READY",				/* 2h */
+	"MEDIUM ERROR",				/* 3h */
+	"HARDWARE ERROR",			/* 4h */
+	"ILLEGAL REQUEST",			/* 5h */
+	"UNIT ATTENTION",			/* 6h */
+	"DATA PROTECT",				/* 7h */
+	"BLANK CHECK",				/* 8h */
+	"VENDOR-SPECIFIC",			/* 9h */
+	"ABORTED COPY",				/* Ah */
+	"ABORTED COMMAND",			/* Bh */
+	"EQUAL (obsolete)",			/* Ch */
+	"VOLUME OVERFLOW",			/* Dh */
+	"MISCOMPARE",				/* Eh */
+	"RESERVED",				/* Fh */
+	NULL
+};
+
+#define SPECIAL_ASCQ(c,q) \
+	(((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
+
+#if 0
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  Sense_Key_Specific() - If Sense_Key_Specific_Valid bit is set,
+ *			   then print additional information via
+ *			   a call to SDMS_SystemAlert().
+ *
+ *  Return: nothing
+ */
+static void Sense_Key_Specific(IO_Info_t *ioop, char *msg1)
+{
+	u8	*sd;
+	u8	 BadValue;
+	u8	 SenseKey;
+	int	 Offset;
+	int	 len = strlen(msg1);
+
+	sd = ioop->sensePtr;
+	if (SD_Additional_Sense_Length(sd) < 8)
+		return;
+
+	SenseKey = SD_Sense_Key(sd);
+
+	if (SD_Sense_Key_Specific_Valid(sd)) {
+		if (SenseKey == SK_ILLEGAL_REQUEST) {
+			Offset = SD_Bad_Byte(sd);
+			if (SD_Was_Illegal_Request(sd)) {
+				BadValue = ioop->cdbPtr[Offset];
+				len += sprintf(msg1+len, "\n  Illegal CDB value=%02Xh found at CDB ",
+						BadValue);
+		} else {
+			BadValue = ioop->dataPtr[Offset];
+			len += sprintf(msg1+len, "\n  Illegal DATA value=%02Xh found at DATA ",
+					BadValue);
+		}
+		len += sprintf(msg1+len, "byte=%02Xh", Offset);
+		if (SD_SKS_Bit_Pointer_Valid(sd))
+			len += sprintf(msg1+len, "/bit=%1Xh", SD_SKS_Bit_Pointer(sd));
+		} else if ((SenseKey == SK_RECOVERED_ERROR) ||
+			   (SenseKey == SK_HARDWARE_ERROR) ||
+			   (SenseKey == SK_MEDIUM_ERROR)) {
+			len += sprintf(msg1+len, "\n  Recovery algorithm Actual_Retry_Count=%02Xh",
+			SD_Actual_Retry_Count(sd));
+		}
+	}
+}
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int dump_cdb(char *foo, unsigned char *cdb)
+{
+	int i, grpCode, cdbLen;
+	int l = 0;
+
+	grpCode = cdb[0] >> 5;
+	if (grpCode < 1)
+		cdbLen = 6;
+	else if (grpCode < 3)
+		cdbLen = 10;
+	else if (grpCode == 5)
+		cdbLen = 12;
+	else
+		cdbLen = 16;
+
+	for (i=0; i < cdbLen; i++)
+		l += sprintf(foo+l, " %02X", cdb[i]);
+
+	return l;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int dump_sd(char *foo, unsigned char *sd)
+{
+	int snsLen = 8 + SD_Additional_Sense_Length(sd);
+	int l = 0;
+	int i;
+
+	for (i=0; i < MIN(snsLen,18); i++)
+		l += sprintf(foo+l, " %02X", sd[i]);
+	l += sprintf(foo+l, "%s", snsLen>18 ? " ..." : "");
+
+	return l;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*  Do ASC/ASCQ lookup/grindage to English readable string(s)  */
+static const char * ascq_set_strings_4max(
+		u8 ASC, u8 ASCQ,
+		const char **s1, const char **s2, const char **s3, const char **s4)
+{
+	static const char *asc_04_part1_string = "LOGICAL UNIT ";
+	static const char *asc_04_part2a_string = "NOT READY, ";
+	static const char *asc_04_part2b_string = "IS ";
+	static const char *asc_04_ascq_NN_part3_strings[] = {	/* ASC ASCQ (hex) */
+	  "CAUSE NOT REPORTABLE",				/* 04 00 */
+	  "IN PROCESS OF BECOMING READY",			/* 04 01 */
+	  "INITIALIZING CMD. REQUIRED",				/* 04 02 */
+	  "MANUAL INTERVENTION REQUIRED",			/* 04 03 */
+	  /* Add	" IN PROGRESS" to all the following... */
+	  "FORMAT",						/* 04 04 */
+	  "REBUILD",						/* 04 05 */
+	  "RECALCULATION",					/* 04 06 */
+	  "OPERATION",						/* 04 07 */
+	  "LONG WRITE",						/* 04 08 */
+	  "SELF-TEST",						/* 04 09 */
+	  NULL
+	};
+	static char *asc_04_part4_string = " IN PROGRESS";
+
+	static char *asc_29_ascq_NN_strings[] = {		/* ASC ASCQ (hex) */
+	  "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",	/* 29 00 */
+	  "POWER ON OCCURRED",					/* 29 01 */
+	  "SCSI BUS RESET OCCURRED",				/* 29 02 */
+	  "BUS DEVICE RESET FUNCTION OCCURRED",			/* 29 03 */
+	  "DEVICE INTERNAL RESET",				/* 29 04 */
+	  "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",		/* 29 05 */
+	  "TRANSCEIVER MODE CHANGED TO LVD",			/* 29 06 */
+	  NULL
+	};
+	static char *ascq_vendor_uniq = "(Vendor Unique)";
+	static char *ascq_noone = "(no matching ASC/ASCQ description found)";
+	int idx;
+
+	*s1 = *s2 = *s3 = *s4 = "";		/* set'em all to the empty "" string */
+
+	/* CHECKME! Need lock/sem?
+	 *  Update and examine for isense module presense.
+	 */
+	mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
+
+	if (mptscsih_ASCQ_TablePtr == NULL) {
+		/* 2nd chances... */
+		if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
+			*s1 = asc_04_part1_string;
+			*s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
+			*s3 = asc_04_ascq_NN_part3_strings[ASCQ];
+			/* check for " IN PROGRESS" ones */
+			if (ASCQ >= 0x04)
+				*s4 = asc_04_part4_string;
+		} else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
+			*s1 = asc_29_ascq_NN_strings[ASCQ];
+		/*
+		 *	else { leave all *s[1-4] values pointing to the empty "" string }
+		 */
+		return *s1;
+	}
+
+	/*
+	 *  Need to check ASC here; if it is "special," then
+	 *  the ASCQ is variable, and indicates failed component number.
+	 *  We must treat the ASCQ as a "don't care" while searching the
+	 *  mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
+	 *  on when we actually need to identify the failed component.
+	 */
+	if (SPECIAL_ASCQ(ASC,ASCQ))
+		ASCQ = 0xFF;
+
+	/*  OK, now search mptscsih_ASCQ_Table[] for a matching entry  */
+	for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
+		if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ))
+			return (*s1 = mptscsih_ASCQ_TablePtr[idx].Description);
+
+	if ((ASC >= 0x80) || (ASCQ >= 0x80))
+		*s1 = ascq_vendor_uniq;
+	else
+		*s1 = ascq_noone;
+
+	return *s1;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  SCSI Error Report; desired output format...
+ *---
+SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
+  SCSI_Status=02h (CHECK CONDITION)
+  Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
+  SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
+  SenseKey=6h (UNIT ATTENTION); FRU=03h
+  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
+ *---
+ */
+
+int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
+{
+	char		 foo[512];
+	char		 buf2[32];
+	char		*statstr;
+	const char	*opstr;
+	int		 sk		= SD_Sense_Key(ioop->sensePtr);
+	const char	*skstr		= SenseKeyString[sk];
+	unsigned char	 asc		= SD_ASC(ioop->sensePtr);
+	unsigned char	 ascq		= SD_ASCQ(ioop->sensePtr);
+	int		 l;
+
+	/*
+	 *  More quiet mode.
+	 *  Filter out common, repetitive, warning-type errors...  like:
+	 *    POWER ON (06,29/00 or 06,29/01),
+	 *    SPINNING UP (02,04/01),
+	 *    LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
+	 */
+	if (	(sk==SK_UNIT_ATTENTION	&& asc==0x29 && (ascq==0x00 || ascq==0x01))
+	     || (sk==SK_NOT_READY	&& asc==0x04 && ascq==0x01)
+	     || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
+	   )
+	{
+		/* Do nothing! */
+		return 0;
+	}
+
+	/*
+	 *  Protect ourselves...
+	 */
+	if (ioop->cdbPtr == NULL)
+		ioop->cdbPtr = dummyCDB;
+	if (ioop->sensePtr == NULL)
+		ioop->sensePtr = dummySenseData;
+	if (ioop->inqPtr == NULL)
+		ioop->inqPtr = dummyInqData;
+	if (ioop->dataPtr == NULL)
+		ioop->dataPtr = dummyScsiData;
+
+	statstr = NULL;
+	if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
+	    ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
+		(void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
+		statstr = buf2;
+	}
+
+	opstr = NULL;
+	if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
+		opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
+	else if (mpt_ScsiOpcodesPtr)
+		opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
+
+	l = sprintf(foo, "SCSI Error Report =-=-= (%s)\n"
+	  "  SCSI_Status=%02Xh (%s)\n"
+	  "  Original_CDB[]:",
+			ioop->DevIDStr,
+			ioop->SCSIStatus,
+			statstr);
+	l += dump_cdb(foo+l, ioop->cdbPtr);
+	if (opstr)
+		l += sprintf(foo+l, " - \"%s\"", opstr);
+	l += sprintf(foo+l, "\n  SenseData[%02Xh]:", 8+SD_Additional_Sense_Length(ioop->sensePtr));
+	l += dump_sd(foo+l, ioop->sensePtr);
+	l += sprintf(foo+l, "\n  SenseKey=%Xh (%s); FRU=%02Xh\n  ASC/ASCQ=%02Xh/%02Xh",
+			sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
+
+	{
+		const char	*x1, *x2, *x3, *x4;
+		x1 = x2 = x3 = x4 = "";
+		x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
+		if (x1 != NULL) {
+			if (x1[0] != '(')
+				l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
+			else
+				l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
+		}
+	}
+
+#if 0
+	if (SPECIAL_ASCQ(asc,ascq))
+		l += sprintf(foo+l, " (%02Xh)", ascq);
+#endif
+
+	PrintF(("%s\n", foo));
+
+	return l;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/mptscsih.h linux/drivers/message/fusion/mptscsih.h
--- linux-2.4.7-pre3/drivers/message/fusion/mptscsih.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/mptscsih.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,247 @@
+/*
+ *  linux/drivers/message/fusion/mptscsih.h
+ *      High performance SCSI / Fibre Channel SCSI Host device driver.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Credits:
+ *      This driver would not exist if not for Alan Cox's development
+ *      of the linux i2o driver.
+ *
+ *      A huge debt of gratitude is owed to David S. Miller (DaveM)
+ *      for fixing much of the stupid and broken stuff in the early
+ *      driver while porting to sparc64 platform.  THANK YOU!
+ *
+ *      (see also mptbase.c)
+ *
+ *  Copyright (c) 1999-2001 LSI Logic Corporation
+ *  Originally By: Steven J. Ralston
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: mptscsih.h,v 1.7 2001/01/11 16:56:43 sralston Exp $
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    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; version 2 of the License.
+
+    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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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
+*/
+
+#ifndef SCSIHOST_H_INCLUDED
+#define SCSIHOST_H_INCLUDED
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include "linux/version.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	SCSI Public stuff...
+ */
+
+#ifdef __sparc__
+#define MPT_SCSI_CAN_QUEUE	63
+#define MPT_SCSI_CMD_PER_LUN	63
+	/* FIXME!  Still investigating qd=64 hang on sparc64... */
+#else
+#define MPT_SCSI_CAN_QUEUE	64
+#define MPT_SCSI_CMD_PER_LUN	64
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	Various bits and pieces broke within the lk-2.4.0-testN series:-(
+ *	So here are various HACKS to work around them.
+ */
+
+/*
+ *	Conditionalizing with "#ifdef MODULE/#endif" around:
+ *		static Scsi_Host_Template driver_template = XX;
+ *		#include <../../scsi/scsi_module.c>
+ *	lines was REMOVED @ lk-2.4.0-test9
+ *	Issue discovered 20001213 by: sshirron
+ */
+#define MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS			1
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
+#	if LINUX_VERSION_CODE == KERNEL_VERSION(2,4,0)
+		/*
+		 *	Super HACK!  -by sralston:-(
+		 *	(good grief; heaven help me!)
+		 */
+#		include <linux/capability.h>
+#		if !defined(CAP_LEASE) && !defined(MODULE)
+#			undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
+#		endif
+#	else
+#		ifndef MODULE
+#			undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
+#		endif
+#	endif
+#endif
+
+/*
+ *	tq_scheduler disappeared @ lk-2.4.0-test12
+ *	(right when <linux/sched.h> newly defined TQ_ACTIVE)
+ */
+#define HAVE_TQ_SCHED	1
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#	include <linux/sched.h>
+#	ifdef TQ_ACTIVE
+#		undef HAVE_TQ_SCHED
+#	endif
+#endif
+#ifdef HAVE_TQ_SCHED
+#define SCHEDULE_TASK(x)		\
+	/*MOD_INC_USE_COUNT*/;		\
+	(x)->next = NULL;		\
+	queue_task(x, &tq_scheduler)
+#else
+#define SCHEDULE_TASK(x)		\
+	/*MOD_INC_USE_COUNT*/;		\
+	if (schedule_task(x) == 0) {	\
+		/*MOD_DEC_USE_COUNT*/;	\
+	}
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#define x_scsi_detect		mptscsih_detect
+#define x_scsi_release		mptscsih_release
+#define x_scsi_info		mptscsih_info
+#define x_scsi_queuecommand	mptscsih_qcmd
+#define x_scsi_abort		mptscsih_abort
+#define x_scsi_bus_reset	mptscsih_bus_reset
+#define x_scsi_dev_reset	mptscsih_dev_reset
+#define x_scsi_host_reset	mptscsih_host_reset
+#define x_scsi_bios_param	mptscsih_bios_param
+
+#define x_scsi_taskmgmt_bh	mptscsih_taskmgmt_bh
+#define x_scsi_old_abort	mptscsih_old_abort
+#define x_scsi_old_reset	mptscsih_old_reset
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	MPT SCSI Host / Initiator decls...
+ */
+extern	int		 x_scsi_detect(Scsi_Host_Template *);
+extern	int		 x_scsi_release(struct Scsi_Host *host);
+extern	const char	*x_scsi_info(struct Scsi_Host *);
+/*extern	int		 x_scsi_command(Scsi_Cmnd *);*/
+extern	int		 x_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+#ifdef MPT_SCSI_USE_NEW_EH
+extern	int		 x_scsi_abort(Scsi_Cmnd *);
+extern	int		 x_scsi_bus_reset(Scsi_Cmnd *);
+extern	int		 x_scsi_dev_reset(Scsi_Cmnd *);
+/*extern	int		 x_scsi_host_reset(Scsi_Cmnd *);*/
+#else
+extern	int		 x_scsi_old_abort(Scsi_Cmnd *);
+extern	int		 x_scsi_old_reset(Scsi_Cmnd *, unsigned int);
+#endif
+extern	int		 x_scsi_bios_param(Disk *, kdev_t, int *);
+extern	void		 x_scsi_taskmgmt_bh(void *);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#define PROC_SCSI_DECL
+#else
+#define PROC_SCSI_DECL  proc_name: "mptscsih",
+#endif
+
+#ifdef MPT_SCSI_USE_NEW_EH
+
+#define MPT_SCSIHOST {						\
+	next:				NULL,			\
+	PROC_SCSI_DECL						\
+	name:				"MPT SCSI Host",	\
+	detect:				x_scsi_detect,		\
+	release:			x_scsi_release,		\
+	info:				x_scsi_info,		\
+	command:			NULL,			\
+	queuecommand:			x_scsi_queuecommand,	\
+	eh_strategy_handler:		NULL,			\
+	eh_abort_handler:		x_scsi_abort,		\
+	eh_device_reset_handler:	x_scsi_dev_reset,	\
+	eh_bus_reset_handler:		x_scsi_bus_reset,	\
+	eh_host_reset_handler:		NULL,			\
+	bios_param:			x_scsi_bios_param,	\
+	can_queue:			MPT_SCSI_CAN_QUEUE,	\
+	this_id:			-1,			\
+	sg_tablesize:			25,			\
+	cmd_per_lun:			MPT_SCSI_CMD_PER_LUN,	\
+	unchecked_isa_dma:		0,			\
+	use_clustering:			ENABLE_CLUSTERING,	\
+	use_new_eh_code:		1			\
+}
+
+#else
+
+#define MPT_SCSIHOST {						\
+	next:				NULL,			\
+	PROC_SCSI_DECL						\
+	name:				"MPT SCSI Host",	\
+	detect:				x_scsi_detect,		\
+	release:			x_scsi_release,		\
+	info:				x_scsi_info,		\
+	command:			NULL,			\
+	queuecommand:			x_scsi_queuecommand,	\
+	abort:				x_scsi_old_abort,	\
+	reset:				x_scsi_old_reset,	\
+	bios_param:			x_scsi_bios_param,	\
+	can_queue:			MPT_SCSI_CAN_QUEUE,	\
+	this_id:			-1,			\
+	sg_tablesize:			25,			\
+	cmd_per_lun:			MPT_SCSI_CMD_PER_LUN,	\
+	unchecked_isa_dma:		0,			\
+	use_clustering:			ENABLE_CLUSTERING	\
+}
+#endif
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*  include/scsi/scsi.h may not be quite complete...  */
+#ifndef RESERVE_10
+#define RESERVE_10		0x56
+#endif
+#ifndef RELEASE_10
+#define RELEASE_10		0x57
+#endif
+#ifndef PERSISTENT_RESERVE_IN
+#define PERSISTENT_RESERVE_IN	0x5e
+#endif
+#ifndef PERSISTENT_RESERVE_OUT
+#define PERSISTENT_RESERVE_OUT	0x5f
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#endif
+
diff -urN linux-2.4.7-pre3/drivers/message/fusion/scsi3.h linux/drivers/message/fusion/scsi3.h
--- linux-2.4.7-pre3/drivers/message/fusion/scsi3.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/scsi3.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,700 @@
+/*
+ *  linux/drivers/message/fusion/scsi3.h
+ *      SCSI-3 definitions and macros.
+ *      (Ultimately) SCSI-3 definitions; for now, inheriting
+ *      SCSI-2 definitions.
+ *
+ *  Copyright (c) 1996-2001 Steven J. Ralston
+ *  Written By: Steven J. Ralston (19960517)
+ *  (mailto:Steve.Ralston@lsil.com)
+ *
+ *  $Id: scsi3.h,v 1.4 2001/01/06 15:54:25 sralston Exp $
+ */
+
+#ifndef SCSI3_H_INCLUDED
+#define SCSI3_H_INCLUDED
+/***************************************************************************/
+
+/****************************************************************************
+ *
+ *  Includes
+ */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+    #ifndef U_STUFF_DEFINED
+    #define U_STUFF_DEFINED
+    typedef unsigned char u8;
+    typedef unsigned short u16;
+    typedef unsigned int u32;
+    #endif
+#endif
+
+/****************************************************************************
+ *
+ *  Defines
+ */
+
+/*
+ *    SCSI Commands
+ */
+#define CMD_TestUnitReady      0x00
+#define CMD_RezeroUnit         0x01  /* direct-access devices */
+#define CMD_Rewind             0x01  /* sequential-access devices */
+#define CMD_RequestSense       0x03
+#define CMD_FormatUnit         0x04
+#define CMD_ReassignBlock      0x07
+#define CMD_Read6              0x08
+#define CMD_Write6             0x0A
+#define CMD_WriteFilemark      0x10
+#define CMD_Space              0x11
+#define CMD_Inquiry            0x12
+#define CMD_ModeSelect6        0x15
+#define CMD_ModeSense6         0x1A
+#define CMD_Reserve6           0x16
+#define CMD_Release6           0x17
+#define CMD_Erase              0x19
+#define CMD_StartStopUnit      0x1b  /* direct-access devices */
+#define CMD_LoadUnload         0x1b  /* sequential-access devices */
+#define CMD_ReceiveDiagnostic  0x1C
+#define CMD_SendDiagnostic     0x1D
+#define CMD_ReadCapacity       0x25
+#define CMD_Read10             0x28
+#define CMD_Write10            0x2A
+#define CMD_WriteVerify        0x2E
+#define CMD_Verify             0x2F
+#define CMD_ReadDefectData     0x37
+#define CMD_LogSelect          0x4C
+#define CMD_LogSense           0x4D
+#define CMD_ModeSelect10       0x55
+#define CMD_Reserve10          0x56
+#define CMD_Release10          0x57
+#define CMD_ModeSense10        0x5A
+#define CMD_ReportLuns         0xA0
+
+/*
+ *    Control byte field
+ */
+#define CONTROL_BYTE_NACA_BIT  0x04
+#define CONTROL_BYTE_Flag_BIT  0x02
+#define CONTROL_BYTE_Link_BIT  0x01
+
+/*
+ *    SCSI Messages
+ */
+#define MSG_COMPLETE             0x00
+#define MSG_EXTENDED             0x01
+#define MSG_SAVE_POINTERS        0x02
+#define MSG_RESTORE_POINTERS     0x03
+#define MSG_DISCONNECT           0x04
+#define MSG_IDERROR              0x05
+#define MSG_ABORT                0x06
+#define MSG_REJECT               0x07
+#define MSG_NOP                  0x08
+#define MSG_PARITY_ERROR         0x09
+#define MSG_LINKED_CMD_COMPLETE  0x0a
+#define MSG_LCMD_COMPLETE_W_FLG  0x0b
+#define MSG_BUS_DEVICE_RESET     0x0c
+#define MSG_ABORT_TAG            0x0d
+#define MSG_CLEAR_QUEUE          0x0e
+#define MSG_INITIATE_RECOVERY    0x0f
+
+#define MSG_RELEASE_RECOVRY      0x10
+#define MSG_TERMINATE_IO         0x11
+
+#define MSG_SIMPLE_QUEUE         0x20
+#define MSG_HEAD_OF_QUEUE        0x21
+#define MSG_ORDERED_QUEUE        0x22
+#define MSG_IGNORE_WIDE_RESIDUE  0x23
+
+#define MSG_IDENTIFY             0x80
+#define MSG_IDENTIFY_W_DISC      0xc0
+
+/*
+ *    SCSI Phases
+ */
+#define PHS_DATA_OUT  0x00
+#define PHS_DATA_IN   0x01
+#define PHS_COMMAND   0x02
+#define PHS_STATUS    0x03
+#define PHS_MSG_OUT   0x06
+#define PHS_MSG_IN    0x07
+
+/*
+ *    Statuses
+ */
+#define STS_GOOD                        0x00
+#define STS_CHECK_CONDITION             0x02
+#define STS_CONDITION_MET               0x04
+#define STS_BUSY                        0x08
+#define STS_INTERMEDIATE                0x10
+#define STS_INTERMEDIATE_CONDITION_MET  0x14
+#define STS_RESERVATION_CONFLICT        0x18
+#define STS_COMMAND_TERMINATED          0x22
+#define STS_TASK_SET_FULL               0x28
+#define    STS_QUEUE_FULL               0x28
+#define STS_ACA_ACTIVE                  0x30
+
+#define STS_VALID_MASK                  0x3e
+
+#define SCSI_STATUS(x)  ((x) & STS_VALID_MASK)
+
+/*
+ *    SCSI QTag Types
+ */
+#define QTAG_SIMPLE     0x20
+#define QTAG_HEAD_OF_Q  0x21
+#define QTAG_ORDERED    0x22
+
+/*
+ *    SCSI Sense Key Definitons
+ */
+#define SK_NO_SENSE         0x00
+#define SK_RECOVERED_ERROR  0x01
+#define SK_NOT_READY        0x02
+#define SK_MEDIUM_ERROR     0x03
+#define SK_HARDWARE_ERROR   0x04
+#define SK_ILLEGAL_REQUEST  0x05
+#define SK_UNIT_ATTENTION   0x06
+#define SK_DATA_PROTECT     0x07
+#define SK_BLANK_CHECK      0x08
+#define SK_VENDOR_SPECIFIC  0x09
+#define SK_COPY_ABORTED     0x0a
+#define SK_ABORTED_COMMAND  0x0b
+#define SK_EQUAL            0x0c
+#define SK_VOLUME_OVERFLOW  0x0d
+#define SK_MISCOMPARE       0x0e
+#define SK_RESERVED         0x0f
+
+
+
+#define SCSI_MAX_INQUIRY_BYTES  96
+#define SCSI_STD_INQUIRY_BYTES  36
+
+#undef USE_SCSI_COMPLETE_INQDATA
+/*
+ *      Structure definition for SCSI Inquiry Data
+ *
+ *  NOTE: The following structure is 96 bytes in size
+ *      iff USE_SCSI_COMPLETE_INQDATA IS defined above (i.e. w/ "#define").
+ *      If USE_SCSI_COMPLETE_INQDATA is NOT defined above (i.e. w/ "#undef")
+ *      then the following structure is only 36 bytes in size.
+ *  THE CHOICE IS YOURS!
+ */
+typedef struct SCSI_Inquiry_Data
+{
+#ifdef USE_SCSI_COMPLETE_INQDATA
+    u8   InqByte[SCSI_MAX_INQUIRY_BYTES];
+#else
+    u8   InqByte[SCSI_STD_INQUIRY_BYTES];
+#endif
+
+/*
+ * the following structure works only for little-endian (Intel,
+ * LSB first (1234) byte order) systems with 4-byte ints.
+ *
+        u32    Periph_Device_Type    : 5,
+               Periph_Qualifier      : 3,
+               Device_Type_Modifier  : 7,
+               Removable_Media       : 1,
+               ANSI_Version          : 3,
+               ECMA_Version          : 3,
+               ISO_Version           : 2,
+               Response_Data_Format  : 4,
+               reserved_0            : 3,
+               AERC                  : 1  ;
+        u32    Additional_Length     : 8,
+               reserved_1            :16,
+               SftReset              : 1,
+               CmdQue                : 1,
+               reserved_2            : 1,
+               Linked                : 1,
+               Sync                  : 1,
+               WBus16                : 1,
+               WBus32                : 1,
+               RelAdr                : 1  ;
+        u8     Vendor_ID[8];
+        u8     Product_ID[16];
+        u8     Revision_Level [4];
+#ifdef USE_SCSI_COMPLETE_INQDATA
+        u8     Vendor_Specific[20];
+        u8     reserved_3[40];
+#endif
+ *
+ */
+
+} SCSI_Inquiry_Data_t;
+
+#define INQ_PERIPHINFO_BYTE            0
+#define   INQ_Periph_Qualifier_MASK      0xe0
+#define   INQ_Periph_Device_Type_MASK    0x1f
+
+#define INQ_Peripheral_Qualifier(inqp) \
+    (int)((*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Qualifier_MASK) >> 5)
+#define INQ_Peripheral_Device_Type(inqp) \
+    (int)(*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Device_Type_MASK)
+
+
+#define INQ_DEVTYPEMOD_BYTE            1
+#define   INQ_RMB_BIT                    0x80
+#define   INQ_Device_Type_Modifier_MASK  0x7f
+
+#define INQ_Removable_Medium(inqp) \
+    (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_RMB_BIT)
+#define INQ_Device_Type_Modifier(inqp) \
+    (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_Device_Type_Modifier_MASK)
+
+
+#define INQ_VERSIONINFO_BYTE           2
+#define   INQ_ISO_Version_MASK           0xc0
+#define   INQ_ECMA_Version_MASK          0x38
+#define   INQ_ANSI_Version_MASK          0x07
+
+#define INQ_ISO_Version(inqp) \
+    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ISO_Version_MASK)
+#define INQ_ECMA_Version(inqp) \
+    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ECMA_Version_MASK)
+#define INQ_ANSI_Version(inqp) \
+    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ANSI_Version_MASK)
+
+
+#define INQ_BYTE3                      3
+#define   INQ_AERC_BIT                   0x80
+#define   INQ_TrmTsk_BIT                 0x40
+#define   INQ_NormACA_BIT                0x20
+#define   INQ_RDF_MASK                   0x0F
+
+#define INQ_AER_Capable(inqp) \
+    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_AERC_BIT)
+#define INQ_TrmTsk(inqp) \
+    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_TrmTsk_BIT)
+#define INQ_NormACA(inqp) \
+    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_NormACA_BIT)
+#define INQ_Response_Data_Format(inqp) \
+    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_RDF_MASK)
+
+
+#define INQ_CAPABILITY_BYTE            7
+#define   INQ_RelAdr_BIT                 0x80
+#define   INQ_WBus32_BIT                 0x40
+#define   INQ_WBus16_BIT                 0x20
+#define   INQ_Sync_BIT                   0x10
+#define   INQ_Linked_BIT                 0x08
+  /*      INQ_Reserved BIT               0x40 */
+#define   INQ_CmdQue_BIT                 0x02
+#define   INQ_SftRe_BIT                  0x01
+
+#define IS_RelAdr_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_RelAdr_BIT)
+#define IS_WBus32_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus32_BIT)
+#define IS_WBus16_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus16_BIT)
+#define IS_Sync_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Sync_BIT)
+#define IS_Linked_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Linked_BIT)
+#define IS_CmdQue_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_CmdQue_BIT)
+#define IS_SftRe_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_SftRe_BIT)
+
+#define INQ_Width_BITS \
+    (INQ_WBus32_BIT | INQ_WBus16_BIT)
+#define IS_Wide_DEV(inqp) \
+    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Width_BITS)
+
+
+/*
+ *      SCSI peripheral device types
+ */
+#define SCSI_TYPE_DAD               0x00  /* Direct Access Device */
+#define SCSI_TYPE_SAD               0x01  /* Sequential Access Device */
+#define SCSI_TYPE_TAPE  SCSI_TYPE_SAD
+#define SCSI_TYPE_PRT               0x02  /* Printer */
+#define SCSI_TYPE_PROC              0x03  /* Processor */
+#define SCSI_TYPE_WORM              0x04
+#define SCSI_TYPE_CDROM             0x05
+#define SCSI_TYPE_SCAN              0x06  /* Scanner */
+#define SCSI_TYPE_OPTICAL           0x07  /* Magneto/Optical */
+#define SCSI_TYPE_CHANGER           0x08
+#define SCSI_TYPE_COMM              0x09  /* Communications device */
+#define SCSI_TYPE_UNKNOWN           0x1f
+#define SCSI_TYPE_UNCONFIGURED_LUN  0x7f
+
+#define SCSI_TYPE_MAX_KNOWN         SCSI_TYPE_COMM
+
+/*
+ *      Peripheral Qualifiers
+ */
+#define DEVICE_PRESENT     0x00
+#define LUN_NOT_PRESENT    0x01
+#define LUN_NOT_SUPPORTED  0x03
+
+/*
+ *      ANSI Versions
+ */
+#ifndef SCSI_1
+#define SCSI_1  0x01
+#endif
+#ifndef SCSI_2
+#define SCSI_2  0x02
+#endif
+#ifndef SCSI_3
+#define SCSI_3  0x03
+#endif
+
+
+#define SCSI_MAX_SENSE_BYTES  255
+#define SCSI_STD_SENSE_BYTES   18
+#define SCSI_PAD_SENSE_BYTES      (SCSI_MAX_SENSE_BYTES - SCSI_STD_SENSE_BYTES)
+
+#undef USE_SCSI_COMPLETE_SENSE
+/*
+ *      Structure definition for SCSI Sense Data
+ *
+ *  NOTE: The following structure is 255 bytes in size
+ *      iiff USE_SCSI_COMPLETE_SENSE IS defined above (i.e. w/ "#define").
+ *      If USE_SCSI_COMPLETE_SENSE is NOT defined above (i.e. w/ "#undef")
+ *      then the following structure is only 19 bytes in size.
+ *  THE CHOICE IS YOURS!
+ *
+ */
+typedef struct SCSI_Sense_Data
+{
+#ifdef USE_SCSI_COMPLETE_SENSE
+    u8       SenseByte[SCSI_MAX_SENSE_BYTES];
+#else
+    u8       SenseByte[SCSI_STD_SENSE_BYTES];
+#endif
+
+/*
+ * the following structure works only for little-endian (Intel,
+ * LSB first (1234) byte order) systems with 4-byte ints.
+ *
+    u8     Error_Code                :4,            // 0x00
+           Error_Class               :3,
+           Valid                     :1
+     ;
+    u8     Segment_Number                           // 0x01
+     ;
+    u8     Sense_Key                 :4,            // 0x02
+           Reserved                  :1,
+           Incorrect_Length_Indicator:1,
+           End_Of_Media              :1,
+           Filemark                  :1
+     ;
+    u8     Information_MSB;                         // 0x03
+    u8     Information_Byte2;                       // 0x04
+    u8     Information_Byte1;                       // 0x05
+    u8     Information_LSB;                         // 0x06
+    u8     Additional_Length;                       // 0x07
+
+    u32    Command_Specific_Information;            // 0x08 - 0x0b
+
+    u8     Additional_Sense_Code;                   // 0x0c
+    u8     Additional_Sense_Code_Qualifier;         // 0x0d
+    u8     Field_Replaceable_Unit_Code;             // 0x0e
+    u8     Illegal_Req_Bit_Pointer   :3,            // 0x0f
+           Illegal_Req_Bit_Valid     :1,
+           Illegal_Req_Reserved      :2,
+           Illegal_Req_Cmd_Data      :1,
+           Sense_Key_Specific_Valid  :1
+     ;
+    u16    Sense_Key_Specific_Data;                 // 0x10 - 0x11
+
+#ifdef USE_SCSI_COMPLETE_SENSE
+    u8     Additional_Sense_Data[SCSI_PAD_SENSE_BYTES];
+#else
+    u8     Additional_Sense_Data[1];
+#endif
+ *
+ */
+
+} SCSI_Sense_Data_t;
+
+
+#define SD_ERRCODE_BYTE                0
+#define   SD_Valid_BIT                   0x80
+#define   SD_Error_Code_MASK             0x7f
+#define SD_Valid(sdp) \
+    (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Valid_BIT)
+#define SD_Error_Code(sdp) \
+    (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Error_Code_MASK)
+
+
+#define SD_SEGNUM_BYTE                 1
+#define SD_Segment_Number(sdp)  (int)(*((u8*)(sdp)+SD_SEGNUM_BYTE))
+
+
+#define SD_SENSEKEY_BYTE               2
+#define   SD_Filemark_BIT                0x80
+#define   SD_EOM_BIT                     0x40
+#define   SD_ILI_BIT                     0x20
+#define   SD_Sense_Key_MASK              0x0f
+#define SD_Filemark(sdp) \
+    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Filemark_BIT)
+#define SD_EOM(sdp) \
+    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_EOM_BIT)
+#define SD_ILI(sdp) \
+    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_ILI_BIT)
+#define SD_Sense_Key(sdp) \
+    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Sense_Key_MASK)
+
+
+#define SD_INFO3_BYTE                  3
+#define SD_INFO2_BYTE                  4
+#define SD_INFO1_BYTE                  5
+#define SD_INFO0_BYTE                  6
+#define SD_Information3(sdp)  (int)(*((u8*)(sdp)+SD_INFO3_BYTE))
+#define SD_Information2(sdp)  (int)(*((u8*)(sdp)+SD_INFO2_BYTE))
+#define SD_Information1(sdp)  (int)(*((u8*)(sdp)+SD_INFO1_BYTE))
+#define SD_Information0(sdp)  (int)(*((u8*)(sdp)+SD_INFO0_BYTE))
+
+
+#define SD_ADDL_LEN_BYTE               7
+#define SD_Additional_Sense_Length(sdp) \
+    (int)(*((u8*)(sdp)+SD_ADDL_LEN_BYTE))
+#define SD_Addl_Sense_Len  SD_Additional_Sense_Length
+
+
+#define SD_CMD_SPECIFIC3_BYTE          8
+#define SD_CMD_SPECIFIC2_BYTE          9
+#define SD_CMD_SPECIFIC1_BYTE         10
+#define SD_CMD_SPECIFIC0_BYTE         11
+#define SD_Cmd_Specific_Info3(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC3_BYTE))
+#define SD_Cmd_Specific_Info2(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC2_BYTE))
+#define SD_Cmd_Specific_Info1(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC1_BYTE))
+#define SD_Cmd_Specific_Info0(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC0_BYTE))
+
+
+#define SD_ADDL_SENSE_CODE_BYTE       12
+#define SD_Additional_Sense_Code(sdp) \
+    (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_BYTE))
+#define SD_Addl_Sense_Code  SD_Additional_Sense_Code
+#define SD_ASC  SD_Additional_Sense_Code
+
+
+#define SD_ADDL_SENSE_CODE_QUAL_BYTE  13
+#define SD_Additional_Sense_Code_Qualifier(sdp) \
+    (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_QUAL_BYTE))
+#define SD_Addl_Sense_Code_Qual  SD_Additional_Sense_Code_Qualifier
+#define SD_ASCQ  SD_Additional_Sense_Code_Qualifier
+
+
+#define SD_FIELD_REPL_UNIT_CODE_BYTE  14
+#define SD_Field_Replaceable_Unit_Code(sdp) \
+    (int)(*((u8*)(sdp)+SD_FIELD_REPL_UNIT_CODE_BYTE))
+#define SD_Field_Repl_Unit_Code  SD_Field_Replaceable_Unit_Code
+#define SD_FRUC  SD_Field_Replaceable_Unit_Code
+#define SD_FRU  SD_Field_Replaceable_Unit_Code
+
+
+/*
+ *  Sense-Key Specific offsets and macros.
+ */
+#define SD_SKS2_BYTE                  15
+#define   SD_SKS_Valid_BIT               0x80
+#define   SD_SKS_Cmd_Data_BIT            0x40
+#define   SD_SKS_Bit_Ptr_Valid_BIT       0x08
+#define   SD_SKS_Bit_Ptr_MASK            0x07
+#define SD_SKS1_BYTE                  16
+#define SD_SKS0_BYTE                  17
+#define SD_Sense_Key_Specific_Valid(sdp) \
+    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Valid_BIT)
+#define SD_SKS_Valid  SD_Sense_Key_Specific_Valid
+#define SD_SKS_CDB_Error(sdp)  \
+    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Cmd_Data_BIT)
+#define SD_Was_Illegal_Request  SD_SKS_CDB_Error
+#define SD_SKS_Bit_Pointer_Valid(sdp)  \
+    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_Valid_BIT)
+#define SD_SKS_Bit_Pointer(sdp)  \
+    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_MASK)
+#define SD_Field_Pointer(sdp)  \
+    (int)( ((u16)(*((u8*)(sdp)+SD_SKS1_BYTE)) << 8) \
+      + *((u8*)(sdp)+SD_SKS0_BYTE) )
+#define SD_Bad_Byte  SD_Field_Pointer
+#define SD_Actual_Retry_Count  SD_Field_Pointer
+#define SD_Progress_Indication  SD_Field_Pointer
+
+/*
+ *  Mode Sense Write Protect Mask
+ */
+#define WRITE_PROTECT_MASK      0X80
+
+/*
+ *  Medium Type Codes
+ */
+#define OPTICAL_DEFAULT                 0x00
+#define OPTICAL_READ_ONLY_MEDIUM        0x01
+#define OPTICAL_WRITE_ONCE_MEDIUM       0x02
+#define OPTICAL_READ_WRITABLE_MEDIUM    0x03
+#define OPTICAL_RO_OR_WO_MEDIUM         0x04
+#define OPTICAL_RO_OR_RW_MEDIUM         0x05
+#define OPTICAL_WO_OR_RW_MEDIUM         0x06
+
+
+
+/*
+ *    Structure definition for READ6, WRITE6 (6-byte CDB)
+ */
+typedef struct SCSI_RW6_CDB
+{
+    u32    OpCode      :8,
+           LBA_HI      :5,    /* 5 MSBit's of the LBA */
+           Lun         :3,
+           LBA_MID     :8,    /* NOTE: total of 21 bits in LBA */
+           LBA_LO      :8  ;  /* Max LBA = 0x001fffff          */
+    u8     BlockCount;
+    u8     Control;
+} SCSI_RW6_t;
+
+#define MAX_RW6_LBA  ((u32)0x001fffff)
+
+/*
+ *  Structure definition for READ10, WRITE10 (10-byte CDB)
+ *
+ *    NOTE: ParityCheck bit is applicable only for VERIFY and WRITE VERIFY for
+ *    the ADP-92 DAC only.  In the SCSI2 spec. this same bit is defined as a
+ *    FUA (forced unit access) bit for READs and WRITEs.  Since this driver
+ *    does not use the FUA, this bit is defined as it is used by the ADP-92.
+ *    Also, for READ CAPACITY, only the OpCode field is used.
+ */
+typedef struct SCSI_RW10_CDB
+{
+    u8     OpCode;
+    u8     Reserved1;
+    u32    LBA;
+    u8     Reserved2;
+    u16    BlockCount;
+    u8     Control;
+} SCSI_RW10_t;
+
+#define PARITY_CHECK  0x08    /* parity check bit - byte[1], bit 3 */
+
+    /*
+     *  Structure definition for data returned by READ CAPACITY cmd;
+     *  READ CAPACITY data
+     */
+    typedef struct READ_CAP_DATA
+    {
+        u32    MaxLBA;
+        u32    BlockBytes;
+    } SCSI_READ_CAP_DATA_t, *pSCSI_READ_CAP_DATA_t;
+
+
+/*
+ *  Structure definition for FORMAT UNIT CDB (6-byte CDB)
+ */
+typedef struct _SCSI_FORMAT_UNIT
+{
+    u8     OpCode;
+    u8     Reserved1;
+    u8     VendorSpecific;
+    u16    Interleave;
+    u8     Control;
+} SCSI_FORMAT_UNIT_t;
+
+/*
+ *    Structure definition for REQUEST SENSE (6-byte CDB)
+ */
+typedef struct _SCSI_REQUEST_SENSE
+{
+    u8     OpCode;
+    u8     Reserved1;
+    u8     Reserved2;
+    u8     Reserved3;
+    u8     AllocLength;
+    u8     Control;
+} SCSI_REQ_SENSE_t;
+
+/*
+ *  Structure definition for REPORT LUNS (12-byte CDB)
+ */
+typedef struct _SCSI_REPORT_LUNS
+{
+    u8     OpCode;
+    u8     Reserved1[5];
+    u32    AllocationLength;
+    u8     Reserved2;
+    u8     Control;
+} SCSI_REPORT_LUNS_t, *pSCSI_REPORT_LUNS_t;
+
+    /*
+     *  (per-level) LUN information bytes
+     */
+/*
+ *  Following doesn't work on ARMCC compiler
+ *  [apparently] because it pads every struct
+ *  to be multiple of 4 bytes!
+ *  So SCSI_LUN_LEVELS_t winds up being 16
+ *  bytes instead of 8!
+ *
+    typedef struct LUN_INFO
+    {
+        u8     AddrMethod_plus_LunOrBusNumber;
+        u8     LunOrTarget;
+    } SCSI_LUN_INFO_t, *pSCSI_LUN_INFO_t;
+
+    typedef struct LUN_LEVELS
+    {
+        SCSI_LUN_INFO_t  LUN_0;
+        SCSI_LUN_INFO_t  LUN_1;
+        SCSI_LUN_INFO_t  LUN_2;
+        SCSI_LUN_INFO_t  LUN_3;
+    } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t;
+*/
+    /*
+     *  All 4 levels (8 bytes) of LUN information
+     */
+    typedef struct LUN_LEVELS
+    {
+        u8     LVL1_AddrMethod_plus_LunOrBusNumber;
+        u8     LVL1_LunOrTarget;
+        u8     LVL2_AddrMethod_plus_LunOrBusNumber;
+        u8     LVL2_LunOrTarget;
+        u8     LVL3_AddrMethod_plus_LunOrBusNumber;
+        u8     LVL3_LunOrTarget;
+        u8     LVL4_AddrMethod_plus_LunOrBusNumber;
+        u8     LVL4_LunOrTarget;
+    } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t;
+
+    /*
+     *  Structure definition for data returned by REPORT LUNS cmd;
+     *  LUN reporting parameter list format
+     */
+    typedef struct LUN_REPORT
+    {
+        u32                LunListLength;
+        u32                Reserved;
+        SCSI_LUN_LEVELS_t  LunInfo[1];
+    } SCSI_LUN_REPORT_t, *pSCSI_LUN_REPORT_t;
+
+/****************************************************************************
+ *
+ *  Externals
+ */
+
+/****************************************************************************
+ *
+ *  Public Typedefs & Related Defines
+ */
+
+/****************************************************************************
+ *
+ *  Macros (embedded, above)
+ */
+
+/****************************************************************************
+ *
+ *  Public Variables
+ */
+
+/****************************************************************************
+ *
+ *  Public Prototypes (module entry points)
+ */
+
+
+/***************************************************************************/
+#endif
diff -urN linux-2.4.7-pre3/drivers/message/fusion/scsiops.c linux/drivers/message/fusion/scsiops.c
--- linux-2.4.7-pre3/drivers/message/fusion/scsiops.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/message/fusion/scsiops.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,309 @@
+
+static const char *ScsiOpcodeString[256] = {
+	"TEST UNIT READY\0\01",				/* 00h */
+	"REWIND\0\002"
+		"\001REZERO UNIT",			/* 01h */
+	"\0\0",						/* 02h */
+	"REQUEST SENSE\0\01",				/* 03h */
+	"FORMAT UNIT\0\03"
+		"\001FORMAT MEDIUM\0"
+		"\002FORMAT",				/* 04h */
+	"READ BLOCK LIMITS\0\1",			/* 05h */
+	"\0\0",						/* 06h */
+	"REASSIGN BLOCKS\0\02"
+		"\010INITIALIZE ELEMENT STATUS",	/* 07h */
+	"READ(06)\0\04"
+		"\001READ\0"
+		"\003RECEIVE\0"
+		"\011GET MESSAGE(06)",			/* 08h */
+	"\0\0",						/* 09h */
+	"WRITE(06)\0\05"
+		"\001WRITE\0"
+		"\002PRINT\0"
+		"\003SEND(6)\0"
+		"\011SEND MESSAGE(06)",			/* 0Ah */
+	"SEEK(06)\0\02"
+		"\003SLEW AND PRINT",			/* 0Bh */
+	"\0\0",						/* 0Ch */
+	"\0\0",						/* 0Dh */
+	"\0\0",						/* 0Eh */
+	"READ REVERSE\0\01",				/* 0Fh */
+	"WRITE FILEMARKS\0\02"
+		"\003SYNCRONIZE BUFFER",		/* 10h */
+	"SPACE(6)\0\01",				/* 11h */
+	"INQUIRY\0\01",					/* 12h */
+	"VERIFY\0\01",					/* 13h */
+	"RECOVER BUFFERED DATA\0\01",			/* 14h */
+	"MODE SELECT(06)\0\01",				/* 15h */
+	"RESERVE(06)\0\02"
+		"\010RESERVE ELEMENT(06)",		/* 16h */
+	"RELEASE(06)\0\02"
+		"\010RELEASE ELEMENT(06)",		/* 17h */
+	"COPY\0\01",					/* 18h */
+	"ERASE\0\01",					/* 19h */
+	"MODE SENSE(06)\0\01",				/* 1Ah */
+	"STOP START UNIT\0\04"
+		"\001LOAD UNLOAD\0"
+		"\002STOP PRINT\0"
+		"\006SCAN\0\002",			/* 1Bh */
+	"RECEIVE DIAGNOSTIC RESULTS\0\01",		/* 1Ch */
+	"SEND DIAGNOSTIC\0\01",				/* 1Dh */
+	"PREVENT ALLOW MEDIUM REMOVAL\0\01",		/* 1Eh */
+	"\0\0",						/* 1Fh */
+	"\0\0",						/* 20h */
+	"\0\0",						/* 21h */
+	"\0\0",						/* 22h */
+	"READ FORMAT CAPACITIES\0\01",			/* 23h */
+	"SET WINDOW\0\01",				/* 24h */
+	"READ CAPACITY\0\03"
+		"\006GET WINDOW\0"
+		"\037FREAD CARD CAPACITY",		/* 25h */
+	"\0\0",						/* 26h */
+	"\0\0",						/* 27h */
+	"READ(10)\0\02"
+		"\011GET MESSAGE(10)",			/* 28h */
+	"READ GENERATION\0\01",				/* 29h */
+	"WRITE(10)\0\03"
+		"\011SEND(10)\0"
+		"\011SEND MESSAGE(10)",			/* 2Ah */
+	"SEEK(10)\0\03"
+		"LOCATE(10)\0"
+		"POSITION TO ELEMENT",			/* 2Bh */
+	"ERASE(10)\0\01",				/* 2Ch */
+	"READ UPDATED BLOCK\0\01",			/* 2Dh */
+	"WRITE AND VERIFY(10)\0\01",			/* 2Eh */
+	"VERIFY(10)\0\01",				/* 2Fh */
+	"SEARCH DATA HIGH(10)\0\01",			/* 30h */
+	"SEARCH DATA EQUAL(10)\0\02"
+		"OBJECT POSITION",			/* 31h */
+	"SEARCH DATA LOW(10)\0\01",			/* 32h */
+	"SET LIMITS(10)\0\01",				/* 33h */
+	"PRE-FETCH(10)\0\03"
+		"READ POSITION\0"
+		"GET DATA BUFFER STATUS",		/* 34h */
+	"SYNCHRONIZE CACHE(10)\0\01",			/* 35h */
+	"LOCK UNLOCK CACHE(10)\0\01",			/* 36h */
+	"READ DEFECT DATA(10)\0\01",			/* 37h */
+	"MEDIUM SCAN\0\01",				/* 38h */
+	"COMPARE\0\01",					/* 39h */
+	"COPY AND VERIFY\0\01",				/* 3Ah */
+	"WRITE BUFFER\0\01",				/* 3Bh */
+	"READ BUFFER\0\01",				/* 3Ch */
+	"UPDATE BLOCK\0\01",				/* 3Dh */
+	"READ LONG\0\01",				/* 3Eh */
+	"WRITE LONG\0\01",				/* 3Fh */
+	"CHANGE DEFINITION\0\01",			/* 40h */
+	"WRITE SAME(10)\0\01",				/* 41h */
+	"READ SUB-CHANNEL\0\01",			/* 42h */
+	"READ TOC/PMA/ATIP\0\01",			/* 43h */
+	"REPORT DENSITY SUPPORT\0\01",			/* 44h */
+	"READ HEADER\0\01",				/* 44h */
+	"PLAY AUDIO(10)\0\01",				/* 45h */
+	"GET CONFIGURATION\0\01",			/* 46h */
+	"PLAY AUDIO MSF\0\01",				/* 47h */
+	"PLAY AUDIO TRACK INDEX\0\01",			/* 48h */
+	"PLAY TRACK RELATIVE(10)\0\01",			/* 49h */
+	"GET EVENT STATUS NOTIFICATION\0\01",		/* 4Ah */
+	"PAUSE/RESUME\0\01",				/* 4Bh */
+	"LOG SELECT\0\01",				/* 4Ch */
+	"LOG SENSE\0\01",				/* 4Dh */
+	"STOP PLAY/SCAN\0\01",				/* 4Eh */
+	"\0\0",						/* 4Fh */
+	"XDWRITE(10)\0\01",				/* 50h */
+	"XPWRITE(10)\0\02"
+		"READ DISC INFORMATION",		/* 51h */
+	"XDREAD(10)\0\01"
+		"READ TRACK INFORMATION",		/* 52h */
+	"RESERVE TRACK\0\01",				/* 53h */
+	"SEND OPC INFORMATION\0\01",			/* 54h */
+	"MODE SELECT(10)\0\01",				/* 55h */
+	"RESERVE(10)\0\02"
+		"RESERVE ELEMENT(10)",			/* 56h */
+	"RELEASE(10)\0\02"
+		"RELEASE ELEMENT(10)",			/* 57h */
+	"REPAIR TRACK\0\01",				/* 58h */
+	"READ MASTER CUE\0\01",				/* 59h */
+	"MODE SENSE(10)\0\01",				/* 5Ah */
+	"CLOSE TRACK/SESSION\0\01",			/* 5Bh */
+	"READ BUFFER CAPACITY\0\01",			/* 5Ch */
+	"SEND CUE SHEET\0\01",				/* 5Dh */
+	"PERSISTENT RESERVE IN\0\01",			/* 5Eh */
+	"PERSISTENT RESERVE OUT\0\01",			/* 5Fh */
+	"\0\0",						/* 60h */
+	"\0\0",						/* 61h */
+	"\0\0",						/* 62h */
+	"\0\0",						/* 63h */
+	"\0\0",						/* 64h */
+	"\0\0",						/* 65h */
+	"\0\0",						/* 66h */
+	"\0\0",						/* 67h */
+	"\0\0",						/* 68h */
+	"\0\0",						/* 69h */
+	"\0\0",						/* 6Ah */
+	"\0\0",						/* 6Bh */
+	"\0\0",						/* 6Ch */
+	"\0\0",						/* 6Dh */
+	"\0\0",						/* 6Eh */
+	"\0\0",						/* 6Fh */
+	"\0\0",						/* 70h */
+	"\0\0",						/* 71h */
+	"\0\0",						/* 72h */
+	"\0\0",						/* 73h */
+	"\0\0",						/* 74h */
+	"\0\0",						/* 75h */
+	"\0\0",						/* 76h */
+	"\0\0",						/* 77h */
+	"\0\0",						/* 78h */
+	"\0\0",						/* 79h */
+	"\0\0",						/* 7Ah */
+	"\0\0",						/* 7Bh */
+	"\0\0",						/* 7Ch */
+	"\0\0",						/* 7Eh */
+	"\0\0",						/* 7Eh */
+	"\0\0",						/* 7Fh */
+	"XDWRITE EXTENDED(16)\0\01",			/* 80h */
+	"REBUILD(16)\0\01",				/* 81h */
+	"REGENERATE(16)\0\01",				/* 82h */
+	"EXTENDED COPY\0\01",				/* 83h */
+	"RECEIVE COPY RESULTS\0\01",			/* 84h */
+	"ACCESS CONTROL IN  [proposed]\0\01",		/* 86h */
+	"ACCESS CONTROL OUT  [proposed]\0\01",		/* 87h */
+	"READ(16)\0\01",				/* 88h */
+	"DEVICE LOCKS  [proposed]\0\01",		/* 89h */
+	"WRITE(16)\0\01",				/* 8Ah */
+	"\0\0",						/* 8Bh */
+	"READ ATTRIBUTES [proposed]\0\01",		/* 8Ch */
+	"WRITE ATTRIBUTES [proposed]\0\01",		/* 8Dh */
+	"WRITE AND VERIFY(16)\0\01",			/* 8Eh */
+	"VERIFY(16)\0\01",				/* 8Fh */
+	"PRE-FETCH(16)\0\01",				/* 90h */
+	"SYNCHRONIZE CACHE(16)\0\02"
+		"SPACE(16) [1]",			/* 91h */
+	"LOCK UNLOCK CACHE(16)\0\02"
+		"LOCATE(16) [1]",			/* 92h */
+	"WRITE SAME(16)\0\01",				/* 93h */
+	"[usage proposed by SCSI Socket Services project]\0\01",	/* 94h */
+	"[usage proposed by SCSI Socket Services project]\0\01",	/* 95h */
+	"[usage proposed by SCSI Socket Services project]\0\01",	/* 96h */
+	"[usage proposed by SCSI Socket Services project]\0\01",	/* 97h */
+	"MARGIN CONTROL [proposed]\0\01",		/* 98h */
+	"\0\0",						/* 99h */
+	"\0\0",						/* 9Ah */
+	"\0\0",						/* 9Bh */
+	"\0\0",						/* 9Ch */
+	"\0\0",						/* 9Dh */
+	"SERVICE ACTION IN [proposed]\0\01",		/* 9Eh */
+	"SERVICE ACTION OUT [proposed]\0\01",		/* 9Fh */
+	"REPORT LUNS\0\01",				/* A0h */
+	"BLANK\0\01",					/* A1h */
+	"SEND EVENT\0\01",				/* A2h */
+	"MAINTENANCE (IN)\0\02"
+		"SEND KEY",				/* A3h */
+	"MAINTENANCE (OUT)\0\02"
+		"REPORT KEY",				/* A4h */
+	"MOVE MEDIUM\0\02"
+		"PLAY AUDIO(12)",			/* A5h */
+	"EXCHANGE MEDIUM\0\02"
+		"LOAD/UNLOAD C/DVD",			/* A6h */
+	"MOVE MEDIUM ATTACHED\0\02"
+		"SET READ AHEAD\0\01",			/* A7h */
+	"READ(12)\0\02"
+		"GET MESSAGE(12)",			/* A8h */
+	"PLAY TRACK RELATIVE(12)\0\01",			/* A9h */
+	"WRITE(12)\0\02"
+		"SEND MESSAGE(12)",			/* AAh */
+	"\0\0",						/* ABh */
+	"ERASE(12)\0\02"
+		"GET PERFORMANCE",			/* ACh */
+	"READ DVD STRUCTURE\0\01",			/* ADh */
+	"WRITE AND VERIFY(12)\0\01",			/* AEh */
+	"VERIFY(12)\0\01",				/* AFh */
+	"SEARCH DATA HIGH(12)\0\01",			/* B0h */
+	"SEARCH DATA EQUAL(12)\0\01",			/* B1h */
+	"SEARCH DATA LOW(12)\0\01",			/* B2h */
+	"SET LIMITS(12)\0\01",				/* B3h */
+	"READ ELEMENT STATUS ATTACHED\0\01",		/* B4h */
+	"REQUEST VOLUME ELEMENT ADDRESS\0\01",		/* B5h */
+	"SEND VOLUME TAG\0\02"
+		"SET STREAMING",			/* B6h */
+	"READ DEFECT DATA(12)\0\01",			/* B7h */
+	"READ ELEMENT STATUS\0\01",			/* B8h */
+	"READ CD MSF\0\01",				/* B9h */
+	"REDUNDANCY GROUP (IN)\0\02"
+		"SCAN",					/* BAh */
+	"REDUNDANCY GROUP (OUT)\0\02"
+		"SET CD-ROM SPEED",			/* BBh */
+	"SPARE (IN)\0\02"
+		"PLAY CD",				/* BCh */
+	"SPARE (OUT)\0\02"
+		"MECHANISM STATUS",			/* BDh */
+	"VOLUME SET (IN)\0\02"
+		"READ CD",				/* BEh */
+	"VOLUME SET (OUT)\0\0\02"
+		"SEND DVD STRUCTURE",			/* BFh */
+	"\0\0",						/* C0h */
+	"\0\0",						/* C1h */
+	"\0\0",						/* C2h */
+	"\0\0",						/* C3h */
+	"\0\0",						/* C4h */
+	"\0\0",						/* C5h */
+	"\0\0",						/* C6h */
+	"\0\0",						/* C7h */
+	"\0\0",						/* C8h */
+	"\0\0",						/* C9h */
+	"\0\0",						/* CAh */
+	"\0\0",						/* CBh */
+	"\0\0",						/* CCh */
+	"\0\0",						/* CDh */
+	"\0\0",						/* CEh */
+	"\0\0",						/* CFh */
+	"\0\0",						/* D0h */
+	"\0\0",						/* D1h */
+	"\0\0",						/* D2h */
+	"\0\0",						/* D3h */
+	"\0\0",						/* D4h */
+	"\0\0",						/* D5h */
+	"\0\0",						/* D6h */
+	"\0\0",						/* D7h */
+	"\0\0",						/* D8h */
+	"\0\0",						/* D9h */
+	"\0\0",						/* DAh */
+	"\0\0",						/* DBh */
+	"\0\0",						/* DCh */
+	"\0\0",						/* DEh */
+	"\0\0",						/* DEh */
+	"\0\0",						/* DFh */
+	"\0\0",						/* E0h */
+	"\0\0",						/* E1h */
+	"\0\0",						/* E2h */
+	"\0\0",						/* E3h */
+	"\0\0",						/* E4h */
+	"\0\0",						/* E5h */
+	"\0\0",						/* E6h */
+	"\0\0",						/* E7h */
+	"\0\0",						/* E8h */
+	"\0\0",						/* E9h */
+	"\0\0",						/* EAh */
+	"\0\0",						/* EBh */
+	"\0\0",						/* ECh */
+	"\0\0",						/* EDh */
+	"\0\0",						/* EEh */
+	"\0\0",						/* EFh */
+	"\0\0",						/* F0h */
+	"\0\0",						/* F1h */
+	"\0\0",						/* F2h */
+	"\0\0",						/* F3h */
+	"\0\0",						/* F4h */
+	"\0\0",						/* F5h */
+	"\0\0",						/* F6h */
+	"\0\0",						/* F7h */
+	"\0\0",						/* F8h */
+	"\0\0",						/* F9h */
+	"\0\0",						/* FAh */
+	"\0\0",						/* FBh */
+	"\0\0",						/* FEh */
+	"\0\0",						/* FEh */
+	"\0\0",						/* FEh */
+	"\0\0"						/* FFh */
+};
+
diff -urN linux-2.4.7-pre3/drivers/net/3c509.c linux/drivers/net/3c509.c
--- linux-2.4.7-pre3/drivers/net/3c509.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/net/3c509.c	Mon Dec  3 22:54:19 2001
@@ -174,7 +174,7 @@
 };
 #endif /* CONFIG_MCA */
 
-#ifdef CONFIG_ISAPNP
+#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -203,8 +203,8 @@
 MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
 
 static u16 el3_isapnp_phys_addr[8][3];
+#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
 static int nopnp;
-#endif /* CONFIG_ISAPNP */
 
 int __init el3_probe(struct net_device *dev)
 {
@@ -214,9 +214,9 @@
 	u16 phys_addr[3];
 	static int current_tag;
 	int mca_slot = -1;
-#ifdef CONFIG_ISAPNP
+#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
 	static int pnp_cards;
-#endif /* CONFIG_ISAPNP */
+#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
 
 	if (dev) SET_MODULE_OWNER(dev);
 
@@ -320,7 +320,7 @@
 	}
 #endif /* CONFIG_MCA */
 
-#ifdef CONFIG_ISAPNP
+#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
 	if (nopnp == 1)
 		goto no_pnp;
 
@@ -356,7 +356,7 @@
 		}
 	}
 no_pnp:
-#endif /* CONFIG_ISAPNP */
+#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
 
 	/* Select an open I/O location at 0x1*0 to do contention select. */
 	for ( ; id_port < 0x200; id_port += 0x10) {
@@ -402,7 +402,7 @@
 		phys_addr[i] = htons(id_read_eeprom(i));
 	}
 
-#ifdef CONFIG_ISAPNP
+#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
 	if (nopnp == 0) {
 		/* The ISA PnP 3c509 cards respond to the ID sequence.
 		   This check is needed in order not to register them twice. */
@@ -422,7 +422,7 @@
 			}
 		}
 	}
-#endif /* CONFIG_ISAPNP */
+#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
 
 	{
 		unsigned int iobase = id_read_eeprom(8);
diff -urN linux-2.4.7-pre3/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.4.7-pre3/drivers/net/8139too.c	Mon Jul  2 14:02:53 2001
+++ linux/drivers/net/8139too.c	Mon Dec  3 22:54:19 2001
@@ -137,7 +137,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.18-pre4"
+#define DRV_VERSION	"0.9.18"
 
 
 #include <linux/config.h>
@@ -209,7 +209,7 @@
 #define RX_BUF_PAD 16
 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
 #define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-#define RX_EARLY_THRESH 2
+#define RX_EARLY_THRESH 14
 
 /* Number of Tx descriptor registers. */
 #define NUM_TX_DESC	4
diff -urN linux-2.4.7-pre3/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.4.7-pre3/drivers/net/Config.in	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 22:54:19 2001
@@ -207,6 +207,7 @@
 
 dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC $CONFIG_PCI
 dep_mbool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I $CONFIG_ACENIC
+dep_tristate 'D-Link 2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI
 dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS
 dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
 dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.7-pre3/drivers/net/Makefile linux/drivers/net/Makefile
--- linux-2.4.7-pre3/drivers/net/Makefile	Wed Jun 20 11:13:18 2001
+++ linux/drivers/net/Makefile	Mon Dec  3 22:54:19 2001
@@ -207,6 +207,7 @@
 obj-$(CONFIG_MACMACE) += macmace.o
 obj-$(CONFIG_MAC89x0) += mac89x0.o
 obj-$(CONFIG_TUN) += tun.o
+obj-$(CONFIG_DL2K) += dl2k.o
 
 ifeq ($(CONFIG_ARCH_ACORN),y)
 mod-subdirs	+= ../acorn/net
diff -urN linux-2.4.7-pre3/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- linux-2.4.7-pre3/drivers/net/dl2k.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/dl2k.c	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,1443 @@
+/*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
+/*
+    Copyright (c) 2001 by D-Link Corporation
+    Written by Edward Peng.<edward_peng@dlink.com.tw>
+    Created 03-May-2001, base on Linux' sundance.c.
+
+    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.
+*/
+/*
+    Rev		Date		Description
+    ==========================================================================
+    0.01	2001/05/03	Create DL2000-based linux driver
+    0.02	2001/05/21	Add VLAN and hardware checksum support.
+    1.00	2001/06/26	Add jumbo frame support.
+*/
+
+#include "dl2k.h"
+
+
+static char version[] __devinitdata =
+KERN_INFO "D-Link DL2000-based linux driver v1.00 2001/06/26\n";
+
+
+
+#define MAX_UNITS 8
+static int mtu[MAX_UNITS];
+static int vlan[MAX_UNITS];
+static int jumbo[MAX_UNITS];
+static char *media[MAX_UNITS];
+static int copy_thresh;
+
+MODULE_AUTHOR ("Edward Peng");
+MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
+MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
+MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
+MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
+MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i");
+MODULE_PARM (copy_thresh, "i");
+
+/* Enable the default interrupts */
+#define EnableInt() \
+writew(RxComplete| RxDMAComplete | HostError | IntRequested | TxComplete| \
+       TxDMAComplete| UpdateStats | LinkEvent, ioaddr + IntEnable)
+static int max_intrloop = 25;
+static int multicast_filter_limit = 0x40;
+
+static int rio_open (struct net_device *dev);
+static void tx_timeout (struct net_device *dev);
+static void alloc_list (struct net_device *dev);
+static int start_xmit (struct sk_buff *skb, struct net_device *dev);
+static void rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static void tx_error (struct net_device *dev, int tx_status);
+static int receive_packet (struct net_device *dev);
+static void rio_error (struct net_device *dev, int int_status);
+static int change_mtu (struct net_device *dev, int new_mtu);
+static void set_multicast (struct net_device *dev);
+static struct net_device_stats *get_stats (struct net_device *dev);
+static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static int rio_close (struct net_device *dev);
+static int find_miiphy (struct net_device *dev);
+static int parse_eeprom (struct net_device *dev);
+static int read_eeprom (long ioaddr, int eep_addr);
+static unsigned get_crc (unsigned char *p, int len);
+static int mii_wait_link (struct net_device *dev, int wait);
+static int mii_set_media (struct net_device *dev);
+static int mii_get_media (struct net_device *dev);
+static int mii_read (struct net_device *dev, int phy_addr, int reg_num);
+static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
+		      u16 data);
+#ifdef RIO_DEBUG
+static int rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata);
+#endif
+
+static int __devinit
+rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	struct netdev_private *np;
+	static int card_idx;
+	int chip_idx = ent->driver_data;
+	int err, irq = pdev->irq;
+	long ioaddr;
+	static int version_printed;
+
+	if (!version_printed++)
+		printk ("%s", version);
+
+	err = pci_enable_device (pdev);
+	if (err)
+		return err;
+
+	err = pci_request_regions (pdev, "dl2k");
+	if (err)
+		goto err_out_disable;
+
+	pci_set_master (pdev);
+
+	dev = alloc_etherdev (sizeof (*np));
+	if (!dev) {
+		err = -ENOMEM;
+		goto err_out_res;
+	}
+	SET_MODULE_OWNER (dev);
+
+#ifdef USE_IO_OPS
+	ioaddr = pci_resource_start (pdev, 0);
+#else
+	ioaddr = pci_resource_start (pdev, 1);
+	ioaddr = (long) ioremap (ioaddr, RIO_IO_SIZE);
+	if (!ioaddr) {
+		err = -ENOMEM;
+		goto err_out_dev;
+	}
+#endif
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	np = dev->priv;
+	np->chip_id = chip_idx;
+	spin_lock_init (&np->lock);
+
+	/* Parse manual configuration */
+	np->an_enable = 1;
+	if (card_idx < MAX_UNITS) {
+		if (media[card_idx] != NULL) {
+			np->an_enable = 0;
+			if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
+			    strcmp (media[card_idx], "4") == 0) {
+				np->speed = 100;
+				np->full_duplex = 1;
+			} else if (strcmp (media[card_idx], "100mbps_hd") == 0
+				   || strcmp (media[card_idx], "3") == 0) {
+				np->speed = 100;
+				np->full_duplex = 0;
+			} else if (strcmp (media[card_idx], "10mbps_fd") == 0 ||
+				   strcmp (media[card_idx], "2") == 0) {
+				np->speed = 10;
+				np->full_duplex = 1;
+			} else if (strcmp (media[card_idx], "10mbps_hd") == 0 ||
+				   strcmp (media[card_idx], "1") == 0) {
+				np->speed = 10;
+				np->full_duplex = 0;
+			}
+			/* Auto-Negotiation is mandatory for 1000BASE-T,
+			   IEEE 802.3ab Annex 28D page 14 */
+			else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
+				 strcmp (media[card_idx], "5") == 0 ||
+				 strcmp (media[card_idx], "1000mbps_hd") == 0 ||
+				 strcmp (media[card_idx], "6") == 0) {
+				np->speed = 1000;
+				np->full_duplex = 1;
+				np->an_enable = 1;
+			} else {
+				np->an_enable = 1;
+			}
+		}
+		if (jumbo[card_idx] != 0) {
+			np->jumbo = 1;
+			dev->mtu = 9000;
+		} else {
+			np->jumbo = 0;
+			if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE)
+				dev->mtu = mtu[card_idx];
+		}
+		np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
+		    vlan[card_idx] : 0;
+	}
+	dev->open = &rio_open;
+	dev->hard_start_xmit = &start_xmit;
+	dev->stop = &rio_close;
+	dev->get_stats = &get_stats;
+	dev->set_multicast_list = &set_multicast;
+	dev->do_ioctl = &rio_ioctl;
+	dev->tx_timeout = &tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->change_mtu = &change_mtu;
+#ifdef TX_HW_CHECKSUM
+	dev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+#endif
+	pci_set_drvdata (pdev, dev);
+
+	/* Parse eeprom data */
+	parse_eeprom (dev);
+
+	/* Find PHY address */
+	err = find_miiphy (dev);
+	if (err)
+		goto err_out_unmap;
+
+	/* Set media and reset PHY */
+	mii_set_media (dev);
+
+	/* Reset all logic functions */
+	writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
+		ioaddr + ASICCtrl + 2);
+
+	err = register_netdev (dev);
+	if (err)
+		goto err_out_unmap;
+
+	card_idx++;
+
+	printk (KERN_INFO "%s: %s, %2x:%2x:%2x:%2x:%2x:%2x, IRQ %d\n",
+		dev->name, np->name,
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5],
+		irq);
+	return 0;
+
+err_out_unmap:
+#ifndef USE_IO_OPS
+	iounmap ((void *) ioaddr);
+
+err_out_dev:
+#endif
+	kfree (dev);
+
+err_out_res:
+	pci_release_regions (pdev);
+
+err_out_disable:
+	pci_disable_device (pdev);
+	return err;
+}
+
+int
+find_miiphy (struct net_device *dev)
+{
+	int i, phy_found = 0;
+	struct netdev_private *np;
+	long ioaddr;
+	np = dev->priv;
+	ioaddr = dev->base_addr;
+	np->phy_addr = 1;
+
+	for (i = 31; i >= 0; i--) {
+		int mii_status = mii_read (dev, i, 1);
+		if (mii_status != 0xffff && mii_status != 0x0000) {
+			np->phy_addr = i;
+			phy_found++;
+		}
+	}
+	if (!phy_found) {
+		printk (KERN_ERR "%s: No MII PHY found!\n", dev->name);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+int
+parse_eeprom (struct net_device *dev)
+{
+	int i, j;
+	int ioaddr = dev->base_addr;
+	u8 sromdata[256];
+	u8 *psib;
+	u32 crc;
+	PSROM_t psrom = (PSROM_t) sromdata;
+	struct netdev_private *np = dev->priv;
+
+	int cid, next;
+
+	/* Read eeprom */
+	for (i = 0; i < 128; i++) {
+		((u16 *) sromdata)[i] = le16_to_cpu (read_eeprom (ioaddr, i));
+	}
+
+	/* Check CRC */
+	crc = ~get_crc (sromdata, 256 - 4);
+	if (psrom->crc != ~get_crc (sromdata, 256 - 4)) {
+		printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
+		return -1;
+	}
+
+	/* Set MAC address */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = psrom->mac_addr[i];
+
+	/* Parse Software Infomation Block */
+	i = 0x30;
+	psib = (u8 *) sromdata;
+	do {
+		cid = psib[i++];
+		next = psib[i++];
+		if ((cid == 0 && next == 0) || (cid == 0xff && next == 0xff)) {
+			printk (KERN_ERR "Cell data error\n");
+			return -1;
+		}
+		switch (cid) {
+		case 0:	/* Format version */
+			break;
+		case 1:	/* End of cell */
+			return 0;
+		case 2:	/* Duplex Polarity */
+			np->duplex_polarity = psib[i];
+			writeb (readb (ioaddr + PhyCtrl) | psib[i],
+				ioaddr + PhyCtrl);
+			break;
+		case 3:	/* Wake Polarity */
+			np->wake_polarity = psib[i];
+			break;
+		case 9:	/* Adapter description */
+			j = (next - i > 255) ? 255 : next - i;
+			memcpy (np->name, &(psib[i]), j);
+			break;
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:	/* Reversed */
+			break;
+		default:	/* Unknown cell */
+			return -1;
+		}
+		i = next;
+	} while (1);
+
+	return 0;
+}
+
+static int
+rio_open (struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	int i;
+
+	i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
+	if (i)
+		return i;
+
+	/* DebugCtrl bit 4, 5, 9 must set */
+	writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
+
+	/* Jumbo frame */
+	if (jumbo != 0)
+		writew (9014, ioaddr + MaxFrameSize);
+
+	alloc_list (dev);
+
+	/* Get station address */
+	for (i = 0; i < 6; i++)
+		writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i);
+
+	set_multicast (dev);
+
+	/* Set RIO to poll every N*320nsec. */
+	writeb (0xff, ioaddr + RxDMAPollPeriod);
+	writeb (0xff, ioaddr + TxDMAPollPeriod);
+	netif_start_queue (dev);
+	writel (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl);
+
+	/* VLAN supported */
+	if (np->vlan) {
+		/* priority field in RxDMAIntCtrl  */
+		writel (0x7 << 10, ioaddr + RxDMAIntCtrl);
+		/* VLANId */
+		writew (np->vlan, ioaddr + VLANId);
+		/* Length/Type should be 0x8100 */
+		writel (0x8100 << 16 | np->vlan, ioaddr + VLANTag);
+		/* Enable AutoVLANuntagging, but disable AutoVLANtagging.
+		   VLAN information tagged by TFC' VID, CFI fields. */
+		writel (readl (ioaddr + MACCtrl) | AutoVLANuntagging,
+			ioaddr + MACCtrl);
+	}
+
+	/* Enable default interrupts */
+	EnableInt ();
+
+	/* clear statistics */
+	get_stats (dev);
+	return 0;
+}
+
+static void
+tx_timeout (struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	printk (KERN_WARNING "%s: Transmit timed out, TxStatus %4.4x.\n",
+		dev->name, readl (ioaddr + TxStatus));
+	dev->if_port = 0;
+	dev->trans_start = jiffies;
+	np->stats.tx_errors++;
+	if (!np->tx_full)
+		netif_wake_queue (dev);
+}
+
+ /* allocate and initialize Tx and Rx descriptors */
+static void
+alloc_list (struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	np->tx_full = 0;
+	np->cur_rx = np->cur_tx = 0;
+	np->old_rx = np->old_tx = 0;
+	np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32);
+	np->rx_head_desc = &np->rx_ring[0];
+
+	/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		np->tx_skbuff[i] = 0;
+		np->tx_ring[i].status = 0;
+	}
+
+	/* Initialize Rx descriptors */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].next_desc =
+		    virt_to_le64desc (&np->rx_ring[i + 1]);
+		np->rx_ring[i].status = 0;
+		np->rx_ring[i].fraginfo = 0;
+		np->rx_skbuff[i] = 0;
+	}
+
+	/* Chain the next pointer to the top */
+	np->rx_ring[i - 1].next_desc = virt_to_le64desc (&np->rx_ring[0]);
+
+	/* Allocate the rx buffers */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		/* Allocated fixed size of skbuff */
+		struct sk_buff *skb = dev_alloc_skb (np->rx_buf_sz);
+		np->rx_skbuff[i] = skb;
+		if (skb == NULL) {
+			printk (KERN_ERR
+				"%s: alloc_list: allocate Rx buffer error! ",
+				dev->name);
+			break;
+		}
+		skb->dev = dev;	/* Mark as being used by this device. */
+		skb_reserve (skb, 2);	/* 16 byte align the IP header. */
+		/* Rubicon now supports 40 bits of addressing space. */
+		np->rx_ring[i].fraginfo = virt_to_le64desc (skb->tail);
+		np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
+	}
+
+	/* Set RFDListPtr */
+	writel (cpu_to_le32 (virt_to_bus (&np->rx_ring[0])),
+		dev->base_addr + RFDListPtr0);
+	writel (0, dev->base_addr + RFDListPtr1);
+
+	return;
+}
+
+static int
+start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	struct netdev_desc *txdesc;
+	unsigned entry;
+	u32 ioaddr;
+
+	ioaddr = dev->base_addr;
+	entry = np->cur_tx % TX_RING_SIZE;
+	np->tx_skbuff[entry] = skb;
+	txdesc = &np->tx_ring[entry];
+	txdesc->next_desc = 0;
+
+	/* Set TFDDone to avoid TxDMA gather this descriptor */
+	txdesc->status = cpu_to_le64 (TFDDone);
+	txdesc->status |=
+	    cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift));
+#ifdef TX_HW_CHECKSUM
+	if (skb->ip_summed == CHECKSUM_HW) {
+		txdesc->status |=
+		    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
+				 IPChecksumEnable);
+	}
+#endif
+	if (np->vlan) {
+		txdesc->status |= cpu_to_le64 (VLANTagInsert |
+					       cpu_to_le64 (vlan) << 32 |
+					       cpu_to_le64 (skb->
+							    priority) << 45);
+	}
+
+	/* Send one packet each time at 10Mbps mode */
+	if (entry % 0x08 == 0 || np->speed == 10)
+		txdesc->status |= cpu_to_le64 (TxIndicate);
+	txdesc->fraginfo = virt_to_le64desc (skb->data);
+	txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
+
+	/* Chain the last descriptor's pointer to this one */
+	if (np->last_tx)
+		np->last_tx->next_desc = virt_to_le64desc (txdesc);
+	np->last_tx = txdesc;
+
+	/* Clear TFDDone, then TxDMA start to send this descriptor */
+	txdesc->status &= ~cpu_to_le64 (TFDDone);
+
+	DEBUG_TFD_DUMP (np);
+
+	/* TxDMAPollNow */
+	writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl);
+	np->cur_tx++;
+
+	if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) {
+		/* do nothing */
+	} else {
+		np->tx_full = 1;
+		netif_stop_queue (dev);
+	}
+
+	/* The first TFDListPtr */
+	if (readl (dev->base_addr + TFDListPtr0) == 0) {
+		writel (virt_to_bus (&np->tx_ring[entry]),
+			dev->base_addr + TFDListPtr0);
+		writel (0, dev->base_addr + TFDListPtr1);
+	}
+
+	/* NETDEV WATCHDOG timer */
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+static void
+rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
+{
+	struct net_device *dev = dev_instance;
+	struct netdev_private *np;
+	unsigned int_status;
+	long ioaddr;
+	int cnt = max_intrloop;
+
+	ioaddr = dev->base_addr;
+	np = dev->priv;
+	spin_lock (&np->lock);
+	while (1) {
+		int_status = readw (ioaddr + IntStatus);
+		writew (int_status & (HostError | TxComplete | RxComplete |
+				      IntRequested | UpdateStats | LinkEvent |
+				      TxDMAComplete | RxDMAComplete | RFDListEnd
+				      | RxDMAPriority), ioaddr + IntStatus);
+		if (int_status == 0)
+			break;
+		/* Processing received packets */
+		receive_packet (dev);
+		/* TxComplete interrupt */
+		if (int_status & TxComplete) {
+			int cnt = 20;
+			int tx_status = readl (ioaddr + TxStatus);
+			while (tx_status & 0x80) {	/* TxComplete */
+				/* Handle TxError */
+				if (tx_status & 0x01)
+					tx_error (dev, tx_status);
+				tx_status = readl (ioaddr + TxStatus);
+				/* too much TxError */
+				if (--cnt < 0)
+					break;
+			}
+			/* Send one packet each time at 10Mbps mode */
+			if (np->speed == 10) {
+				np->tx_full = 0;
+				netif_wake_queue (dev);
+			}
+		}
+		/* Free used tx skbuffs */
+		for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+			int entry = np->old_tx % TX_RING_SIZE;
+			if (!(np->tx_ring[entry].status & TFDDone))
+				break;
+			dev_kfree_skb_irq (np->tx_skbuff[entry]);
+			np->tx_skbuff[entry] = 0;
+		}
+		/* If the ring is no longer full, clear tx_full and 
+		   call netif_wake_queue() */
+		if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
+			np->tx_full = 0;
+			netif_wake_queue (dev);
+		}
+
+		/* Handle uncommon events */
+		if (int_status &
+		    (IntRequested | HostError | LinkEvent | UpdateStats))
+			rio_error (dev, int_status);
+		/* If too much interrupts here, disable all interrupts except 
+		   IntRequest. When CountDown down to 0, IntRequest will 
+		   be caught by rio_error() to recovery the interrupts */
+		if (--cnt < 0) {
+			get_stats (dev);
+			writel (1000, ioaddr + CountDown);
+			writew (IntRequested, ioaddr + IntEnable);
+			break;
+		}
+	}
+	spin_unlock (&np->lock);
+}
+
+static void
+tx_error (struct net_device *dev, int tx_status)
+{
+	struct netdev_private *np;
+	long ioaddr = dev->base_addr;
+	int frame_id;
+	int i;
+
+	np = dev->priv;
+
+	frame_id = (tx_status & 0xffff0000) >> 16;
+	printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
+		dev->name, tx_status, frame_id);
+	np->stats.tx_errors++;
+	np->stats.tx_dropped++;
+	/* Ttransmit Underrun */
+	if (tx_status & 0x10) {
+		np->stats.tx_fifo_errors++;
+		/* Transmit Underrun need to set TxReset, DMARest, FIFOReset */
+		writew (TxReset | DMAReset | FIFOReset, ioaddr + ASICCtrl + 2);
+		/* Wait for ResetBusy bit clear */
+		for (i = 50; i > 0; i--) {
+			if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
+				break;
+			mdelay (1);
+		}
+		/* Reset TFDListPtr */
+		writel (virt_to_bus (&np->tx_ring[frame_id]),
+			dev->base_addr + TFDListPtr0);
+		writel (0, dev->base_addr + TFDListPtr1);
+
+		/* Let TxStartThresh stay default value */
+	}
+	/* Late Collision */
+	if (tx_status & 0x04) {
+		np->stats.tx_fifo_errors++;
+		/* TxReset and clear FIFO */
+		writew (TxReset | FIFOReset, ioaddr + ASICCtrl + 2);
+		/* Wait reset done */
+		for (i = 50; i > 0; i--) {
+			if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
+				break;
+			mdelay (1);
+		}
+		/* Let TxStartThresh stay default value */
+	}
+	/* Maximum Collisions */
+#ifdef ETHER_STATS
+	if (tx_status & 0x08)
+		np->stats.collisions16++;
+#else
+	if (tx_status & 0x08)
+		np->stats.collisions++;
+#endif
+
+	/* Restart the Tx. */
+	writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
+}
+
+/* Every interrupts go into here to see if any packet need to process, this
+   ensure Rx rings keep full in a critical cases of Rx rings ran out */
+static int
+receive_packet (struct net_device *dev)
+{
+	struct netdev_private *np = (struct netdev_private *) dev->priv;
+	int entry = np->cur_rx % RX_RING_SIZE;
+	int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx;
+
+	DEBUG_RFD_DUMP (np, 1);
+	/* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */
+	while (np->rx_head_desc->status & RFDDone &&
+	       np->rx_head_desc->status & FrameStart &&
+	       np->rx_head_desc->status & FrameEnd) {
+		struct netdev_desc *desc = np->rx_head_desc;
+		u64 frame_status = le64_to_cpu (desc->status);
+		int pkt_len = le64_to_cpu (desc->status & 0xffff);	/* Chip omits the CRC. */
+
+		if (--cnt < 0)
+			break;
+		DEBUG_PKT_DUMP (np, pkt_len);
+		/* Update rx error statistics, drop packet. */
+		if (frame_status & 0x003f0000) {
+			np->stats.rx_errors++;
+			if (frame_status & 0x00100000)
+				np->stats.rx_length_errors++;
+			if (frame_status & 0x00010000)
+				np->stats.rx_fifo_errors++;
+			if (frame_status & 0x00060000)
+				np->stats.rx_frame_errors++;
+			if (frame_status & 0x00080000)
+				np->stats.rx_crc_errors++;
+		} else {
+			struct sk_buff *skb;
+			/* Small skbuffs for short packets */
+			if (pkt_len > copy_thresh) {
+				skb_put (skb = np->rx_skbuff[entry], pkt_len);
+				np->rx_skbuff[entry] = NULL;
+			} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
+				skb->dev = dev;
+				skb_reserve (skb, 2);	/* 16 byte align the IP header */
+				eth_copy_and_sum (skb,
+						  np->rx_skbuff[entry]->tail,
+						  pkt_len, 0);
+				skb_put (skb, pkt_len);
+			}
+			skb->protocol = eth_type_trans (skb, dev);
+#ifdef RX_HW_CHECKSUM
+			/* Checksum done by hw, but csum value unavailable. */
+			if (!(frame_status & (TCPError | UDPError | IPError))) {
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			}
+#endif
+			netif_rx (skb);
+			dev->last_rx = jiffies;
+		}
+		entry = (++np->cur_rx) % RX_RING_SIZE;
+		np->rx_head_desc = &np->rx_ring[entry];
+	}
+
+	/* Re-allocate skbuffs to fill the descriptor ring */
+	for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
+		struct sk_buff *skb;
+		entry = np->old_rx % RX_RING_SIZE;
+		/* Dropped packets don't need to re-allocate */
+		if (np->rx_skbuff[entry] == NULL) {
+			skb = dev_alloc_skb (np->rx_buf_sz);
+			if (skb == NULL) {
+				np->rx_ring[entry].fraginfo = 0;
+				printk (KERN_ERR
+					"%s: Allocate Rx buffer error!",
+					dev->name);
+				break;
+			}
+			np->rx_skbuff[entry] = skb;
+			skb->dev = dev;
+			skb_reserve (skb, 2);	/* 16 byte align the IP header */
+			np->rx_ring[entry].fraginfo =
+			    virt_to_le64desc (skb->tail);
+		}
+		np->rx_ring[entry].fraginfo |=
+		    cpu_to_le64 (np->rx_buf_sz) << 48;
+		np->rx_ring[entry].status = 0;
+	}
+	/* RxDMAPollNow */
+	writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
+		dev->base_addr + DMACtrl);
+
+	DEBUG_RFD_DUMP (np, 2);
+	return 0;
+}
+
+static void
+rio_error (struct net_device *dev, int int_status)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+
+	/* Stop the down counter and recovery the interrupt */
+	if (int_status & IntRequested) {
+
+		writew (0, ioaddr + IntEnable);
+		writel (0, ioaddr + CountDown);
+		/* Enable default interrupts */
+		EnableInt ();
+	}
+
+	/* Link change event */
+	if (int_status & LinkEvent) {
+		if (mii_wait_link (dev, 10) == 0) {
+			printk (KERN_INFO "%s: Link up\n", dev->name);
+			if (np->an_enable) {
+				/* Auto-Negotiation mode */
+				mii_get_media (dev);
+				if (np->full_duplex) {
+					writew (readw (dev->base_addr + MACCtrl)
+						| DuplexSelect,
+						ioaddr + MACCtrl);
+				}
+			}
+		} else {
+			printk (KERN_INFO "%s: Link off\n", dev->name);
+		}
+	}
+
+	/* UpdateStats statistics registers */
+	if (int_status & UpdateStats) {
+		get_stats (dev);
+	}
+
+	/* PCI Error, a catastronphic error related to the bus interface 
+	   occurs, set GlobalReset and HostReset to reset. */
+	if (int_status & HostError) {
+		printk (KERN_ERR "%s: PCI Error! IntStatus %4.4x.\n",
+			dev->name, int_status);
+		writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
+		mdelay (500);
+	}
+}
+
+static struct net_device_stats *
+get_stats (struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+	u16 temp1;
+	u16 temp2;
+	int i;
+	/* All statistics registers need to acknowledge,
+	   else overflow could cause some problem */
+	np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
+	np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
+	np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
+	np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);
+	temp1 = readw (ioaddr + FrameLostRxError);
+	np->stats.rx_errors += temp1;
+	np->stats.rx_missed_errors += temp1;
+	np->stats.tx_dropped += readw (ioaddr + FramesAbortXSColls);
+	temp1 = readl (ioaddr + SingleColFrames) +
+	    readl (ioaddr + MultiColFrames) + readl (ioaddr + LateCollisions);
+	temp2 = readw (ioaddr + CarrierSenseErrors);
+	np->stats.tx_carrier_errors += temp2;
+	np->stats.tx_errors += readw (ioaddr + FramesWEXDeferal) +
+	    readl (ioaddr + FramesWDeferredXmt) + temp2;
+
+	/* detailed rx_error */
+	np->stats.rx_length_errors += readw (ioaddr + InRangeLengthErrors) +
+	    readw (ioaddr + FrameTooLongErrors);
+	np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
+
+	/* Clear all other statistic register. */
+	readw (ioaddr + MacControlFramesXmtd);
+	readw (ioaddr + BcstFramesXmtdOk);
+	readl (ioaddr + McstFramesXmtdOk);
+	readl (ioaddr + BcstOctetXmtOk);
+	readl (ioaddr + McstOctetXmtOk);
+	readw (ioaddr + MacControlFramesRcvd);
+	readw (ioaddr + BcstFramesRcvOk);
+	readl (ioaddr + McstFramesRcvOk);
+	readl (ioaddr + BcstOctetRcvOk);
+
+	for (i = 0x100; i <= 0x150; i += 4)
+		readl (ioaddr + i);
+	readw (ioaddr + TxJumboFrames);
+	readw (ioaddr + RxJumboFrames);
+	readw (ioaddr + TCPCheckSumErrors);
+	readw (ioaddr + UDPCheckSumErrors);
+	readw (ioaddr + IPCheckSumErrors);
+	return &np->stats;
+}
+
+int
+change_mtu (struct net_device *dev, int new_mtu)
+{
+	int max = (jumbo) ? 9000 : 1536;
+
+	if ((new_mtu < 68) || (new_mtu > max)) {
+		return -EINVAL;
+	}
+
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
+#define CRC_POLY 0xedb88320
+static unsigned
+get_crc (unsigned char *p, int len)
+{
+	int bit;
+	unsigned char byte;
+	unsigned crc = 0xffffffff;
+
+	while (--len >= 0) {
+		byte = *p++;
+		for (bit = 0; bit < 8; bit++, byte >>= 1) {
+			crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? CRC_POLY : 0);
+		}
+	}
+	return crc;
+}
+
+static void
+set_multicast (struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	u32 hash_table[2];
+	u16 rx_mode = 0;
+	int i;
+	struct dev_mc_list *mclist;
+	struct netdev_private *np = dev->priv;
+
+	/* Default: receive broadcast and unicast */
+	rx_mode = ReceiveBroadcast | ReceiveUnicast;
+	if (dev->flags & IFF_PROMISC) {
+		/* Receive all frames promiscuously. */
+		rx_mode |= ReceiveAllFrames;
+	} else
+	    if (((dev->flags & IFF_MULTICAST)
+		 && (dev->mc_count > multicast_filter_limit))
+		|| (dev->flags & IFF_ALLMULTI)) {
+		/* Receive broadcast and multicast frames */
+		rx_mode |= ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
+	} else if ((dev->flags & IFF_MULTICAST) & (dev->mc_count > 0)) {
+		/* Receive broadcast frames and multicast frames filtering by Hashtable */
+		rx_mode |=
+		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
+	}
+	if (np->vlan) {
+		/* ReceiveVLANMatch field in ReceiveMode */
+		rx_mode |= ReceiveVLANMatch;
+	}
+	hash_table[0] = 0x00000000;
+	hash_table[1] = 0x00000000;
+
+	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+	     i++, mclist = mclist->next) {
+		set_bit (get_crc (mclist->dmi_addr, ETH_ALEN) & 0x3f,
+			 hash_table);
+	}
+	writel (hash_table[0], ioaddr + HashTable0);
+	writel (hash_table[1], ioaddr + HashTable1);
+	writew (rx_mode, ioaddr + ReceiveMode);
+}
+
+static int
+rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int phy_addr;
+	struct netdev_private *np = dev->priv;
+	struct mii_data *miidata = (struct mii_data *) &rq->ifr_data;
+#ifdef RIO_DEBUG
+	struct ioctl_data *iodata = (struct ioctl_data *) (rq->ifr_data);
+#endif
+	u16 *data = (u16 *) & rq->ifr_data;
+	struct netdev_desc *desc;
+	int i;
+
+	phy_addr = np->phy_addr;
+	switch (cmd) {
+	case SIOCDEVPRIVATE:
+#ifdef RIO_DEBUG
+		if (rio_ioctl_ext (dev, iodata) != 0)
+			return -EOPNOTSUPP;
+		break;
+#else
+		return -EOPNOTSUPP;
+#endif
+	case SIOCDEVPRIVATE + 1:
+		miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
+		break;
+	case SIOCDEVPRIVATE + 2:
+		mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
+		break;
+	case SIOCDEVPRIVATE + 3:
+		np->rx_debug = (data[0] <= 7) ? data[0] : 0;
+		printk ("rx_debug = %d\n", np->rx_debug);
+		break;
+	case SIOCDEVPRIVATE + 4:
+		np->tx_debug = (data[0] <= 7) ? data[0] : 0;
+		printk ("tx_debug = %d\n", np->tx_debug);
+		break;
+	case SIOCDEVPRIVATE + 5:
+		np->tx_full = 1;
+		netif_stop_queue (dev);
+		break;
+	case SIOCDEVPRIVATE + 6:
+		np->tx_full = 0;
+		netif_wake_queue (dev);
+		break;
+	case SIOCDEVPRIVATE + 7:
+		printk ("tx_full=%x cur_tx=%x old_tx=%x cur_rx=%x old_rx=%x\n",
+			(u32) np->tx_full, (u32) np->cur_tx, (u32) np->old_tx,
+			(u32) np->cur_rx, (u32) np->old_rx);
+		break;
+	case SIOCDEVPRIVATE + 8:
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			desc = &np->tx_ring[i];
+			printk
+			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
+			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
+			     (u32) desc->fraginfo);
+			printk ("\n");
+		}
+		printk ("\n");
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+#ifdef RIO_DEBUG
+int
+rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata)
+{
+	struct netdev_private *np = dev->priv;
+	int phy_addr = np->phy_addr;
+	u32 hi, lo;
+	int i;
+	BMCR_t bmcr;
+	BMSR_t bmsr;
+
+	if (iodata == NULL)
+		goto invalid_cmd;
+	if (strcmp (iodata->signature, "rio") != 0)
+		goto invalid_cmd;
+
+	switch (iodata->cmd) {
+	case 0:
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			hi = np->tx_ring[i].status >> 32;
+			lo = np->tx_ring[i].status;
+			printk ("TFC=%08x %08x \n", hi, lo);
+
+		}
+		break;
+	case 1:
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			hi = np->rx_ring[i].status >> 32;
+			lo = np->rx_ring[i].status;
+			printk ("RFS=%08x %08x \n", hi, lo);
+		}
+		break;
+	case 2:
+		break;
+	case 3:
+		if (iodata->data != NULL)
+			np->tx_debug = iodata->data[0];
+		break;
+	case 4:
+		/* Soft reset PHY */
+		mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
+		bmcr.image = 0;
+		bmcr.bits.an_enable = 1;
+		bmcr.bits.reset = 1;
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+		break;
+	case 5:
+		mii_write (dev, phy_addr, MII_BMCR, 0x1940);
+		mdelay (10);
+		mii_write (dev, phy_addr, MII_BMCR, 0x1940);
+		mdelay (100);	/* wait a certain time */
+		break;
+	case 6:
+		/* 5) Set media and Power Up */
+		bmcr.image = 0;
+		bmcr.bits.power_down = 1;
+		if (np->an_enable) {
+			bmcr.bits.an_enable = 1;
+		} else {
+			if (np->speed == 100) {
+				bmcr.bits.speed100 = 1;
+				bmcr.bits.speed1000 = 0;
+				printk ("Manual 100 Mbps, ");
+			} else if (np->speed == 10) {
+				bmcr.bits.speed100 = 0;
+				bmcr.bits.speed1000 = 0;
+				printk ("Manual 10 Mbps, ");
+			}
+			if (np->full_duplex) {
+				bmcr.bits.duplex_mode = 1;
+				printk ("Full duplex. \n");
+			} else {
+				bmcr.bits.duplex_mode = 0;
+				printk ("Half duplex.\n");
+			}
+		}
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+		break;
+	case 7:
+		bmcr.image = mii_read (dev, phy_addr, MII_BMCR);
+		bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
+		printk ("BMCR=%x BMSR=%x LinkUp=%d\n",
+			bmcr.image, bmsr.image, bmsr.bits.link_status);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+
+invalid_cmd:
+	return -1;
+}
+#endif
+#define EEP_READ 0x0200
+#define EEP_BUSY 0x8000
+/* Read the EEPROM word */
+int
+read_eeprom (long ioaddr, int eep_addr)
+{
+	int i = 1000;
+	writew (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl);
+	while (i-- > 0) {
+		if (!(readw (ioaddr + EepromCtrl) & EEP_BUSY)) {
+			return readw (ioaddr + EepromData);
+		}
+	}
+	return 0;
+}
+
+enum phy_ctrl_bits {
+	MII_READ = 0x00, MII_CLK = 0x01, MII_DATA1 = 0x02, MII_WRITE = 0x04,
+	MII_DUPLEX = 0x08,
+};
+
+#define mii_delay() readb(ioaddr)
+static void
+mii_sendbit (struct net_device *dev, u32 data)
+{
+	int ioaddr = dev->base_addr + PhyCtrl;
+	data = (data) ? MII_DATA1 : 0;
+	data |= MII_WRITE;
+	data |= (readb (ioaddr) & 0xf8) | MII_WRITE;
+	writeb (data, ioaddr);
+	mii_delay ();
+	writeb (data | MII_CLK, ioaddr);
+	mii_delay ();
+}
+
+static int
+mii_getbit (struct net_device *dev)
+{
+	int ioaddr = dev->base_addr + PhyCtrl;
+	u8 data;
+
+	data = (readb (ioaddr) & 0xf8) | MII_READ;
+	writeb (data, ioaddr);
+	mii_delay ();
+	writeb (data | MII_CLK, ioaddr);
+	mii_delay ();
+	return ((readb (ioaddr) >> 1) & 1);
+}
+
+static void
+mii_send_bits (struct net_device *dev, u32 data, int len)
+{
+	int i;
+	for (i = len - 1; i >= 0; i--) {
+		mii_sendbit (dev, data & (1 << i));
+	}
+}
+
+static int
+mii_read (struct net_device *dev, int phy_addr, int reg_num)
+{
+	u32 cmd;
+	int i;
+	u32 retval = 0;
+
+	/* Preamble */
+	mii_send_bits (dev, 0xffffffff, 32);
+	/* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */
+	/* ST,OP = 0110'b for read operation */
+	cmd = (0x06 << 10 | phy_addr << 5 | reg_num);
+	mii_send_bits (dev, cmd, 14);
+	/* Turnaround */
+	if (mii_getbit (dev))
+		goto err_out;
+	/* Read data */
+	for (i = 0; i < 16; i++) {
+		retval |= mii_getbit (dev);
+		retval <<= 1;
+	}
+	/* End cycle */
+	mii_getbit (dev);
+	return (retval >> 1) & 0xffff;
+
+err_out:
+	return 0;
+}
+static int
+mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data)
+{
+	u32 cmd;
+
+	/* Preamble */
+	mii_send_bits (dev, 0xffffffff, 32);
+	/* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */
+	/* ST,OP,AAAAA,RRRRR,TA = 0101xxxxxxxxxx10'b = 0x0502 for write */
+	cmd = (0x5002 << 16) | (phy_addr << 23) | (reg_num << 18) | data;
+	mii_send_bits (dev, cmd, 32);
+	/* End cycle */
+	mii_getbit (dev);
+	return 0;
+}
+static int
+mii_wait_link (struct net_device *dev, int wait)
+{
+	BMSR_t bmsr;
+	int phy_addr;
+	struct netdev_private *np;
+
+	np = dev->priv;
+	phy_addr = np->phy_addr;
+
+	do {
+		bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
+		if (bmsr.bits.link_status)
+			return 0;
+		mdelay (1);
+	} while (--wait > 0);
+	return -1;
+}
+static int
+mii_get_media (struct net_device *dev)
+{
+	ANAR_t negotiate;
+	BMSR_t bmsr;
+	BMCR_t bmcr;
+	MSCR_t mscr;
+	MSSR_t mssr;
+	int phy_addr;
+	struct netdev_private *np;
+
+	np = dev->priv;
+	phy_addr = np->phy_addr;
+
+	bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
+	if (np->an_enable) {
+		if (!bmsr.bits.an_complete) {
+			/* Auto-Negotiation not completed */
+			return -1;
+		}
+		negotiate.image = mii_read (dev, phy_addr, MII_ANAR) &
+		    mii_read (dev, phy_addr, MII_ANLPAR);
+		mscr.image = mii_read (dev, phy_addr, MII_MSCR);
+		mssr.image = mii_read (dev, phy_addr, MII_MSSR);
+		if (mscr.bits.media_1000BT_FD & mssr.bits.lp_1000BT_FD) {
+			np->speed = 1000;
+			np->full_duplex = 1;
+			printk (KERN_INFO "Auto 1000BaseT, Full duplex.\n");
+		} else if (mscr.bits.media_1000BT_HD & mssr.bits.lp_1000BT_HD) {
+			np->speed = 1000;
+			np->full_duplex = 0;
+			printk (KERN_INFO "Auto 1000BaseT, Half duplex.\n");
+		} else if (negotiate.bits.media_100BX_FD) {
+			np->speed = 100;
+			np->full_duplex = 1;
+			printk (KERN_INFO "Auto 100BaseT, Full duplex.\n");
+		} else if (negotiate.bits.media_100BX_HD) {
+			np->speed = 100;
+			np->full_duplex = 0;
+			printk (KERN_INFO "Auto 100BaseT, Half duplex.\n");
+		} else if (negotiate.bits.media_10BT_FD) {
+			np->speed = 10;
+			np->full_duplex = 1;
+			printk (KERN_INFO "Auto 10BaseT, Full duplex.\n");
+		} else if (negotiate.bits.media_10BT_HD) {
+			np->speed = 10;
+			np->full_duplex = 0;
+			printk (KERN_INFO "Auto 10BaseT, Half duplex.\n");
+		}
+	} else {
+		bmcr.image = mii_read (dev, phy_addr, MII_BMCR);
+		if (bmcr.bits.speed100 == 1 && bmcr.bits.speed1000 == 0) {
+			printk (KERN_INFO "Operating at 100 Mbps, ");
+		} else if (bmcr.bits.speed100 == 0 && bmcr.bits.speed1000 == 0) {
+			printk (KERN_INFO "Operating at 10 Mbps, ");
+		} else if (bmcr.bits.speed100 == 0 && bmcr.bits.speed1000 == 1) {
+			printk (KERN_INFO "Operating at 1000 Mbps, ");
+		}
+		if (bmcr.bits.duplex_mode) {
+			printk ("Full duplex.\n");
+		} else {
+			printk ("Half duplex.\n");
+		}
+	}
+	return 0;
+}
+
+static int
+mii_set_media (struct net_device *dev)
+{
+	PHY_SCR_t pscr;
+	BMCR_t bmcr;
+	BMSR_t bmsr;
+	ANAR_t anar;
+	int phy_addr;
+	struct netdev_private *np;
+	np = dev->priv;
+	phy_addr = np->phy_addr;
+
+	/* Does user set speed? */
+	if (np->an_enable) {
+		/* Reset to enable Auto-Negotiation */
+		bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
+		anar.image = mii_read (dev, phy_addr, MII_ANAR);
+		anar.bits.media_100BX_FD = bmsr.bits.media_100BX_FD;
+		anar.bits.media_100BX_HD = bmsr.bits.media_100BX_HD;
+		anar.bits.media_100BT4 = bmsr.bits.media_100BT4;
+		anar.bits.media_10BT_FD = bmsr.bits.media_10BT_FD;
+		anar.bits.media_10BT_HD = bmsr.bits.media_10BT_HD;
+		mii_write (dev, phy_addr, MII_ANAR, anar.image);
+
+		/* Enable Auto crossover */
+		pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR);
+		pscr.bits.mdi_crossover_mode = 3;	/* 11'b */
+		mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image);
+		/* Soft reset PHY */
+		mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
+		bmcr.image = 0;
+		bmcr.bits.an_enable = 1;
+		bmcr.bits.reset = 1;
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+		/* Wait for Link up, link up need a certain time */
+		if (mii_wait_link (dev, 3200) != 0) {
+			printk (KERN_INFO "Link time out\n");
+		}
+		mdelay (1);
+		mii_get_media (dev);
+	} else {
+		/* Force speed setting */
+		/* 1) Disable Auto crossover */
+		pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR);
+		pscr.bits.mdi_crossover_mode = 0;
+		mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image);
+
+		/* 2) PHY Reset */
+		bmcr.image = mii_read (dev, phy_addr, MII_BMCR);
+		bmcr.bits.reset = 1;
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+
+		/* 3) Power Down */
+		bmcr.image = 0x1940;	/* must be 0x1940 */
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+		mdelay (10);	/* wait a certain time */
+
+		/* 4) Advertise nothing */
+		mii_write (dev, phy_addr, MII_ANAR, 0);
+
+		/* 5) Set media and Power Up */
+		bmcr.image = 0;
+		bmcr.bits.power_down = 1;
+		if (np->speed == 100) {
+			bmcr.bits.speed100 = 1;
+			bmcr.bits.speed1000 = 0;
+			printk (KERN_INFO "Manual 100 Mbps, ");
+		} else if (np->speed == 10) {
+			bmcr.bits.speed100 = 0;
+			bmcr.bits.speed1000 = 0;
+			printk (KERN_INFO "Manual 10 Mbps, ");
+		}
+		if (np->full_duplex) {
+			bmcr.bits.duplex_mode = 1;
+			printk ("Full duplex. \n");
+		} else {
+			bmcr.bits.duplex_mode = 0;
+			printk ("Half duplex.\n");
+		}
+#if 0
+		/* Set 1000BaseT Master/Slave setting */
+		mscr.image = mii_read (dev, phy_addr, MII_MSCR);
+		mscr.bits.cfg_enable = 1;
+		mscr.bits.cfg_value = 0;
+#endif
+		mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
+
+		/* Wait for Link up, link up need a certain time */
+		if (mii_wait_link (dev, 3200) != 0) {
+			printk (KERN_INFO "Link time out\n");
+		}
+		mii_get_media (dev);
+	}
+	return 0;
+}
+
+static int
+rio_close (struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	netif_stop_queue (dev);
+
+	/* Disable interrupts */
+	writew (0, ioaddr + IntEnable);
+
+	/* Stop Tx and Rx logics */
+	writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
+	synchronize_irq ();
+	free_irq (dev->irq, dev);
+
+	/* Free all the skbuffs in the queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].status = 0;
+		np->rx_ring[i].fraginfo = 0;
+		if (np->rx_skbuff[i]) {
+			dev_kfree_skb (np->rx_skbuff[i]);
+		}
+		np->rx_skbuff[i] = 0;
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (np->tx_skbuff[i])
+			dev_kfree_skb (np->tx_skbuff[i]);
+		np->tx_skbuff[i] = 0;
+	}
+	return 0;
+}
+
+static void __devexit
+rio_remove1 (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	if (dev) {
+		unregister_netdev (dev);
+#ifndef USE_IO_OPS
+		iounmap ((char *) (dev->base_addr));
+#endif
+		kfree (dev);
+		pci_release_regions (pdev);
+		pci_disable_device (pdev);
+	}
+	pci_set_drvdata (pdev, NULL);
+}
+
+static struct pci_driver rio_driver = {
+	name:		"dl2k",
+	id_table:	rio_pci_tbl,
+	probe:		rio_probe1,
+	remove:		rio_remove1,
+};
+
+static int __init
+rio_init (void)
+{
+#ifdef MODULE
+	printk ("%s", version);
+#endif
+
+	return pci_module_init (&rio_driver);
+}
+
+static void __exit
+rio_exit (void)
+{
+	pci_unregister_driver (&rio_driver);
+}
+
+module_init (rio_init);
+module_exit (rio_exit);
+
+/*
+ 
+Compile command: 
+ 
+gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2x.c
+
+*/
diff -urN linux-2.4.7-pre3/drivers/net/dl2k.h linux/drivers/net/dl2k.h
--- linux-2.4.7-pre3/drivers/net/dl2k.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/dl2k.h	Mon Dec  3 22:54:19 2001
@@ -0,0 +1,729 @@
+/*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
+/*  
+    Copyright (c) 2001 by D-Link Corporation
+    Written by Edward Peng.<edward_peng@dlink.com.tw>
+    Created 03-May-2001, base on Linux' sundance.c.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+*/
+
+#ifndef __DL2K_H__
+#define __DL2K_H__
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <asm/processor.h>	/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#define TX_RING_SIZE	16
+#define TX_QUEUE_LEN	10	/* Limit ring entries actually used.  */
+#define RX_RING_SIZE	16
+
+#define virt_to_le64desc(addr)  cpu_to_le64(virt_to_bus(addr))
+#define le64desc_to_virt(addr)  bus_to_virt(le64_to_cpu(addr))
+/* This driver was written to use PCI memory space, however x86-oriented
+   hardware often uses I/O space accesses. */
+#ifdef USE_IO_OPS
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb inb
+#define readw inw
+#define readl inl
+#define writeb outb
+#define writew outw
+#define writel outl
+#endif
+
+/* Offsets to the device registers.
+   Unlike software-only systems, device drivers interact with complex hardware.
+   It's not useful to define symbolic names for every register bit in the
+   device.  The name can only partially document the semantics and make
+   the driver longer and more difficult to read.
+   In general, only the important configuration values or bits changed
+   multiple times should be defined symbolically.
+*/
+enum dl2x_offsets {
+	/* I/O register offsets */
+	DMACtrl = 0x00,
+	RxDMAStatus = 0x08,
+	TFDListPtr0 = 0x10,
+	TFDListPtr1 = 0x14,
+	TxDMABurstThresh = 0x18,
+	TxDMAUrgentThresh = 0x19,
+	TxDMAPollPeriod = 0x1a,
+	RFDListPtr0 = 0x1c,
+	RFDListPtr1 = 0x20,
+	RxDMABurstThresh = 0x24,
+	RxDMAUrgentThresh = 0x25,
+	RxDMAPollPeriod = 0x26,
+	RxDMAIntCtrl = 0x28,
+	DebugCtrl = 0x2c,
+	ASICCtrl = 0x30,
+	FifoCtrl = 0x38,
+	RxEarlyThresh = 0x3a,
+	FlowOffThresh = 0x3c,
+	FlowOnThresh = 0x3e,
+	TxStartThresh = 0x44,
+	EepromData = 0x48,
+	EepromCtrl = 0x4a,
+	ExpromAddr = 0x4c,
+	Exprodata = 0x50,
+	WakeEvent0x51,
+	CountDown = 0x54,
+	IntStatusAck = 0x5a,
+	IntEnable = 0x5c,
+	IntStatus = 0x5e,
+	TxStatus = 0x60,
+	MACCtrl = 0x6c,
+	VLANTag = 0x70,
+	PhyCtrl = 0x76,
+	StationAddr0 = 0x78,
+	StationAddr1 = 0x7a,
+	StationAddr2 = 0x7c,
+	VLANId = 0x80,
+	MaxFrameSize = 0x86,
+	ReceiveMode = 0x88,
+	HashTable0 = 0x8c,
+	HashTable1 = 0x90,
+	RmonStatMask = 0x98,
+	StatMask = 0x9c,
+	RxJumboFrames = 0xbc,
+	TCPCheckSumErrors = 0xc0,
+	IPCheckSumErrors = 0xc2,
+	UDPCheckSumErrors = 0xc4,
+	TxJumboFrames = 0xf4,
+	/* Ethernet MIB statistic register offsets */
+	OctetRcvOk = 0xa8,
+	McstOctetRcvOk = 0xac,
+	BcstOctetRcvOk = 0xb0,
+	FramesRcvOk = 0xb4,
+	McstFramesRcvOk = 0xb8,
+	BcstFramesRcvOk = 0xbe,
+	MacControlFramesRcvd = 0xc6,
+	FrameTooLongErrors = 0xc8,
+	InRangeLengthErrors = 0xca,
+	FrameCheckSeqError = 0xcc,
+	FrameLostRxError = 0xce,
+	OctetXmtOk = 0xd0,
+	McstOctetXmtOk = 0xd4,
+	BcstOctetXmtOk = 0xd8,
+	FramesXmtOk = 0xdc,
+	McstFramesXmtdOk = 0xe0,
+	FramesWDeferredXmt = 0xe4,
+	LateCollisions = 0xe8,
+	MultiColFrames = 0xec,
+	SingleColFrames = 0xf0,
+	BcstFramesXmtdOk = 0xf6,
+	CarrierSenseErrors = 0xf8,
+	MacControlFramesXmtd = 0xfa,
+	FramesAbortXSColls = 0xfc,
+	FramesWEXDeferal = 0xfe,
+	/* RMON statistic register offsets */
+	EtherStatsCollisions = 0x100,
+	EtherStatsOctetsTransmit = 0x104,
+	EtherStatsPktsTransmit = 0x108,
+	EtherStatsPkts64OctetTransmit = 0x10c,
+	EtherStats65to127OctetsTransmit = 0x110,
+	EtherStatsPkts128to255OctetsTransmit = 0x114,
+	EtherStatsPkts256to511OctetsTransmit = 0x118,
+	EtherStatsPkts512to1023OctetsTransmit = 0x11c,
+	EtherStatsPkts1024to1518OctetsTransmit = 0x120,
+	EtherStatsCRCAlignErrors = 0x124,
+	EtherStatsUndersizePkts = 0x128,
+	EtherStatsFragments = 0x12c,
+	EtherStatsJabbers = 0x130,
+	EtherStatsOctets = 0x134,
+	EtherStatsPkts = 0x138,
+	EtherStats64Octets = 0x13c,
+	EtherStatsPkts65to127Octets = 0x140,
+	EtherStatsPkts128to255Octets = 0x144,
+	EtherStatsPkts256to511Octets = 0x148,
+	EtherStatsPkts512to1023Octets = 0x14c,
+	EtherStatsPkts1024to1518Octets = 0x150,
+};
+
+/* Bits in the interrupt status/mask registers. */
+enum IntStatus_bits {
+	InterruptStatus = 0x0001,
+	HostError = 0x0002,
+	MACCtrlFrame = 0x0008,
+	TxComplete = 0x0004,
+	RxComplete = 0x0010,
+	RxEarly = 0x0020,
+	IntRequested = 0x0040,
+	UpdateStats = 0x0080,
+	LinkEvent = 0x0100,
+	TxDMAComplete = 0x0200,
+	RxDMAComplete = 0x0400,
+	RFDListEnd = 0x0800,
+	RxDMAPriority = 0x1000,
+};
+
+/* Bits in the ReceiveMode register. */
+enum ReceiveMode_bits {
+	ReceiveIPMulticast = 0x0020,
+	ReceiveMulticastHash = 0x0010,
+	ReceiveAllFrames = 0x0008,
+	ReceiveBroadcast = 0x0004,
+	ReceiveMulticast = 0x0002,
+	ReceiveUnicast = 0x0001,
+	ReceiveVLANMatch = 0x0100,
+	ReceiveVLANHash = 0x0200,
+};
+/* Bits in MACCtrl. */
+enum MACCtrl_bits {
+	DuplexSelect = 0x20,
+	RcvFCS = 0x200,
+	AutoVLANtagging = 0x1000,
+	AutoVLANuntagging = 0x2000,
+	StatsEnable = 0x00200000,
+	StatsDisable = 0x00400000,
+	StatsEnabled = 0x00800000,
+	TxEnable = 0x01000000,
+	TxDisable = 0x02000000,
+	TxEnabled = 0x04000000,
+	RxEnable = 0x08000000,
+	RxDisable = 0x10000000,
+	RxEnabled = 0x20000000,
+};
+enum ASICCtrl_HiWord_bits {
+	GlobalReset = 0x0001,
+	RxReset = 0x0002,
+	TxReset = 0x0004,
+	DMAReset = 0x0008,
+	FIFOReset = 0x0010,
+	NetworkReset = 0x0020,
+	HostReset = 0x0040,
+	ResetBusy = 0x0400,
+};
+
+/* Transmit Frame Control bits */
+enum TFC_bits {
+	DwordAlign = 0x00000000,
+	WordAlignDisable = 0x00030000,
+	WordAlign = 0x00020000,
+	TCPChecksumEnable = 0x00040000,
+	UDPChecksumEnable = 0x00080000,
+	IPChecksumEnable = 0x00100000,
+	FCSAppendDisable = 0x00200000,
+	TxIndicate = 0x00400000,
+	TxDMAIndicate = 0x00800000,
+	FragCountShift = 24,
+	VLANTagInsert = 0x0000000010000000,
+	TFDDone = 0x80000000,
+	VIDShift = 32,
+	CFI = 0x0000100000000000,
+	UsePriorityShift = 48,
+};
+
+/* Receive Frames Status bits */
+enum RFS_bits {
+	RxFIFOOverrun = 0x00010000,
+	RxRuntFrame = 0x00020000,
+	RxAlignmentError = 0x00040000,
+	RxFCSError = 0x00080000,
+	RxOverSizedFrame = 0x00100000,
+	RxLengthError = 0x00200000,
+	VLANDetected = 0x00400000,
+	TCPDetected = 0x00800000,
+	TCPError = 0x01000000,
+	UDPDetected = 0x02000000,
+	UDPError = 0x04000000,
+	IPDetected = 0x08000000,
+	IPError = 0x10000000,
+	FrameStart = 0x20000000,
+	FrameEnd = 0x40000000,
+	RFDDone = 0x80000000,
+	TCIShift = 32,
+};
+
+#define MII_RESET_TIME_OUT		10000
+/* MII register */
+enum _mii_reg {
+	MII_BMCR = 0,
+	MII_BMSR = 1,
+	MII_PHY_ID1 = 2,
+	MII_PHY_ID2 = 3,
+	MII_ANAR = 4,
+	MII_ANLPAR = 5,
+	MII_ANER = 6,
+	MII_ANNPT = 7,
+	MII_ANLPRNP = 8,
+	MII_MSCR = 9,
+	MII_MSSR = 10,
+	MII_ESR = 15,
+	MII_PHY_SCR = 16,
+};
+
+/* Basic Mode Control Register */
+typedef union t_MII_BMCR {
+	u16 image;
+	struct {
+		u16 _bit_5_0:6;	// bit 5:0
+		u16 speed1000:1;	// bit 6
+		u16 col_test_enable:1;	// bit 7
+		u16 duplex_mode:1;	// bit 8
+		u16 restart_an:1;	// bit 9
+		u16 isolate:1;	// bit 10
+		u16 power_down:1;	// bit 11
+		u16 an_enable:1;	// bit 12
+		u16 speed100:1;	// bit 13
+		u16 loopback:1;	// bit 14
+		u16 reset:1;	// bit 15
+	} bits;
+} BMCR_t, *PBMCR_t;
+
+enum _mii_bmcr {
+	MII_BMCR_RESET = 0x8000,
+	MII_BMCR_LOOP_BACK = 0x4000,
+	MII_BMCR_SPEED_LSB = 0x2000,
+	MII_BMCR_AN_ENABLE = 0x1000,
+	MII_BMCR_POWER_DOWN = 0x0800,
+	MII_BMCR_ISOLATE = 0x0400,
+	MII_BMCR_RESTART_AN = 0x0200,
+	MII_BMCR_DUPLEX_MODE = 0x0100,
+	MII_BMCR_COL_TEST = 0x0080,
+	MII_BMCR_SPEED_MSB = 0x0040,
+	MII_BMCR_SPEED_RESERVED = 0x003f,
+	MII_BMCR_SPEED_10 = 0,
+	MII_BMCR_SPEED_100 = MII_BMCR_SPEED_LSB,
+	MII_BMCR_SPEED_1000 = MII_BMCR_SPEED_MSB,
+};
+
+/* Basic Mode Status Register */
+typedef union t_MII_BMSR {
+	u16 image;
+	struct {
+		u16 ext_capability:1;	// bit 0
+		u16 japper_detect:1;	// bit 1
+		u16 link_status:1;	// bit 2
+		u16 an_ability:1;	// bit 3
+		u16 remote_fault:1;	// bit 4
+		u16 an_complete:1;	// bit 5
+		u16 preamble_supp:1;	// bit 6
+		u16 _bit_7:1;	// bit 7
+		u16 ext_status:1;	// bit 8
+		u16 media_100BT2_HD:1;	// bit 9
+		u16 media_100BT2_FD:1;	// bit 10
+		u16 media_10BT_HD:1;	// bit 11
+		u16 media_10BT_FD:1;	// bit 12
+		u16 media_100BX_HD:1;	// bit 13
+		u16 media_100BX_FD:1;	// bit 14
+		u16 media_100BT4:1;	// bit 15
+	} bits;
+} BMSR_t, *PBMSR_t;
+
+enum _mii_bmsr {
+	MII_BMSR_100BT4 = 0x8000,
+	MII_BMSR_100BX_FD = 0x4000,
+	MII_BMSR_100BX_HD = 0x2000,
+	MII_BMSR_10BT_FD = 0x1000,
+	MII_BMSR_10BT_HD = 0x0800,
+	MII_BMSR_100BT2_FD = 0x0400,
+	MII_BMSR_100BT2_HD = 0x0200,
+	MII_BMSR_EXT_STATUS = 0x0100,
+	MII_BMSR_PREAMBLE_SUPP = 0x0040,
+	MII_BMSR_AN_COMPLETE = 0x0020,
+	MII_BMSR_REMOTE_FAULT = 0x0010,
+	MII_BMSR_AN_ABILITY = 0x0008,
+	MII_BMSR_LINK_STATUS = 0x0004,
+	MII_BMSR_JABBER_DETECT = 0x0002,
+	MII_BMSR_EXT_CAP = 0x0001,
+};
+
+/* ANAR */
+typedef union t_MII_ANAR {
+	u16 image;
+	struct {
+		u16 selector:5;	// bit 4:0
+		u16 media_10BT_HD:1;	// bit 5
+		u16 media_10BT_FD:1;	// bit 6
+		u16 media_100BX_HD:1;	// bit 7
+		u16 media_100BX_FD:1;	// bit 8
+		u16 media_100BT4:1;	// bit 9
+		u16 pause:1;	// bit 10
+		u16 asymmetric:1;	// bit 11
+		u16 _bit12:1;	// bit 12
+		u16 remote_fault:1;	// bit 13
+		u16 _bit14:1;	// bit 14
+		u16 next_page:1;	// bit 15
+	} bits;
+} ANAR_t, *PANAR_t;
+
+enum _mii_anar {
+	MII_ANAR_NEXT_PAGE = 0x8000,
+	MII_ANAR_REMOTE_FAULT = 0x4000,
+	MII_ANAR_ASYMMETRIC = 0x0800,
+	MII_ANAR_PAUSE = 0x0400,
+	MII_ANAR_100BT4 = 0x0200,
+	MII_ANAR_100BX_FD = 0x0100,
+	MII_ANAR_100BX_HD = 0x0080,
+	MII_ANAR_10BT_FD = 0x0020,
+	MII_ANAR_10BT_HD = 0x0010,
+	MII_ANAR_SELECTOR = 0x001f,
+	MII_IEEE8023_CSMACD = 0x0001,
+};
+
+/* ANLPAR */
+typedef union t_MII_ANLPAR {
+	u16 image;
+	struct {
+		u16 selector:5;	// bit 4:0
+		u16 media_10BT_HD:1;	// bit 5
+		u16 media_10BT_FD:1;	// bit 6
+		u16 media_100BX_HD:1;	// bit 7
+		u16 media_100BX_FD:1;	// bit 8
+		u16 media_100BT4:1;	// bit 9
+		u16 pause:1;	// bit 10
+		u16 asymmetric:1;	// bit 11
+		u16 _bit12:1;	// bit 12
+		u16 remote_fault:1;	// bit 13
+		u16 _bit14:1;	// bit 14
+		u16 next_page:1;	// bit 15
+	} bits;
+} ANLPAR_t, *PANLPAR_t;
+
+enum _mii_anlpar {
+	MII_ANLPAR_NEXT_PAGE = MII_ANAR_NEXT_PAGE,
+	MII_ANLPAR_REMOTE_FAULT = MII_ANAR_REMOTE_FAULT,
+	MII_ANLPAR_ASYMMETRIC = MII_ANAR_ASYMMETRIC,
+	MII_ANLPAR_PAUSE = MII_ANAR_PAUSE,
+	MII_ANLPAR_100BT4 = MII_ANAR_100BT4,
+	MII_ANLPAR_100BX_FD = MII_ANAR_100BX_FD,
+	MII_ANLPAR_100BX_HD = MII_ANAR_100BX_HD,
+	MII_ANLPAR_10BT_FD = MII_ANAR_10BT_FD,
+	MII_ANLPAR_10BT_HD = MII_ANAR_10BT_HD,
+	MII_ANLPAR_SELECTOR = MII_ANAR_SELECTOR,
+};
+
+/* Auto-Negotiation Expansion Register */
+typedef union t_MII_ANER {
+	u16 image;
+	struct {
+		u16 lp_negotiable:1;	// bit 0
+		u16 page_received:1;	// bit 1
+		u16 nextpagable:1;	// bit 2
+		u16 lp_nextpagable:1;	// bit 3
+		u16 pdetect_fault:1;	// bit 4
+		u16 _bit15_5:11;	// bit 15:5
+	} bits;
+} ANER_t, *PANER_t;
+
+enum _mii_aner {
+	MII_ANER_PAR_DETECT_FAULT = 0x0010,
+	MII_ANER_LP_NEXTPAGABLE = 0x0008,
+	MII_ANER_NETXTPAGABLE = 0x0004,
+	MII_ANER_PAGE_RECEIVED = 0x0002,
+	MII_ANER_LP_NEGOTIABLE = 0x0001,
+};
+
+/* MASTER-SLAVE Control Register */
+typedef union t_MII_MSCR {
+	u16 image;
+	struct {
+		u16 _bit_7_0:8;	// bit 7:0
+		u16 media_1000BT_HD:1;	// bit 8
+		u16 media_1000BT_FD:1;	// bit 9
+		u16 port_type:1;	// bit 10
+		u16 cfg_value:1;	// bit 11
+		u16 cfg_enable:1;	// bit 12
+		u16 test_mode:3;	// bit 15:13
+	} bits;
+} MSCR_t, *PMSCR_t;
+
+enum _mii_mscr {
+	MII_MSCR_TEST_MODE = 0xe000,
+	MII_MSCR_CFG_ENABLE = 0x1000,
+	MII_MSCR_CFG_VALUE = 0x0800,
+	MII_MSCR_PORT_VALUE = 0x0400,
+	MII_MSCR_1000BT_FD = 0x0200,
+	MII_MSCR_1000BT_HD = 0X0100,
+};
+
+/* MASTER-SLAVE Status Register */
+typedef union t_MII_MSSR {
+	u16 image;
+	struct {
+		u16 idle_err_count:8;	// bit 7:0
+		u16 _bit_9_8:2;	// bit 9:8
+		u16 lp_1000BT_HD:1;	// bit 10
+		u16 lp_1000BT_FD:1;	// bit 11
+		u16 remote_rcv_status:1;	// bit 12
+		u16 local_rcv_status:1;	// bit 13
+		u16 cfg_resolution:1;	// bit 14
+		u16 cfg_fault:1;	// bit 15
+	} bits;
+} MSSR_t, *PMSSR_t;
+
+enum _mii_mssr {
+	MII_MSSR_CFG_FAULT = 0x8000,
+	MII_MSSR_CFG_RES = 0x4000,
+	MII_MSSR_LOCAL_RCV_STATUS = 0x2000,
+	MII_MSSR_REMOTE_RCVR = 0x1000,
+	MII_MSSR_LP_1000BT_HD = 0x0800,
+	MII_MSSR_LP_1000BT_FD = 0x0400,
+	MII_MSSR_IDLE_ERR_COUNT = 0x00ff,
+};
+
+/* IEEE Extened Status Register */
+typedef union t_MII_ESR {
+	u16 image;
+	struct {
+		u16 _bit_11_0:12;	// bit 11:0
+		u16 media_1000BT_HD:2;	// bit 12
+		u16 media_1000BT_FD:1;	// bit 13
+		u16 media_1000BX_HD:1;	// bit 14
+		u16 media_1000BX_FD:1;	// bit 15
+	} bits;
+} ESR_t, *PESR_t;
+
+enum _mii_esr {
+	MII_ESR_1000BX_FD = 0x8000,
+	MII_ESR_1000BX_HD = 0x4000,
+	MII_ESR_1000BT_FD = 0x2000,
+	MII_ESR_1000BT_HD = 0x1000,
+};
+/* PHY Specific Control Register */
+typedef union t_MII_PHY_SCR {
+	u16 image;
+	struct {
+		u16 disable_jabber:1;	// bit 0
+		u16 polarity_reversal:1;	// bit 1
+		u16 SEQ_test:1;	// bit 2
+		u16 _bit_3:1;	// bit 3
+		u16 disable_CLK125:1;	// bit 4
+		u16 mdi_crossover_mode:2;	// bit 6:5
+		u16 enable_ext_dist:1;	// bit 7
+		u16 _bit_8_9:2;	// bit 9:8
+		u16 force_link:1;	// bit 10
+		u16 assert_CRS:1;	// bit 11
+		u16 rcv_fifo_depth:2;	// bit 13:12
+		u16 xmit_fifo_depth:2;	// bit 15:14
+	} bits;
+} PHY_SCR_t, *PPHY_SCR_t;
+
+typedef enum t_MII_ADMIN_STATUS {
+	adm_reset,
+	adm_operational,
+	adm_loopback,
+	adm_power_down,
+	adm_isolate
+} MII_ADMIN_t, *PMII_ADMIN_t;
+
+typedef struct t_SROM {
+	u16 config_param;	/* 0x00 */
+	u16 asic_ctrl;		/* 0x02 */
+	u16 sub_vendor_id;	/* 0x04 */
+	u16 sub_system_id;	/* 0x06 */
+	u16 reserved1[12];	/* 0x08-0x1f */
+	u8 mac_addr[6];		/* 0x20-0x25 */
+	u8 reserved2[10];	/* 0x26-0x2f */
+	u8 sib[204];		/* 0x30-0xfb */
+	u32 crc;		/* 0xfc-0xff */
+} SROM_t, *PSROM_t;
+
+/* Ioctl custom data */
+struct ioctl_data {
+	char signature[10];
+	int cmd;
+	int len;
+	char *data;
+};
+
+struct mii_data {
+	__u16 reserved;
+	__u16 reg_num;
+	__u16 in_value;
+	__u16 out_value;
+};
+
+/* The Rx and Tx buffer descriptors. */
+struct netdev_desc {
+	u64 next_desc;
+	u64 status;
+	u64 fraginfo;
+};
+
+#define PRIV_ALIGN	15	/* Required alignment mask */
+/* Use  __attribute__((aligned (L1_CACHE_BYTES)))  to maintain alignment
+   within the structure. */
+struct netdev_private {
+	/* Descriptor rings first for alignment. */
+	struct netdev_desc rx_ring[RX_RING_SIZE];
+	struct netdev_desc tx_ring[TX_RING_SIZE];
+	/* The addresses of receive-in-place skbuffs. */
+	struct sk_buff *rx_skbuff[RX_RING_SIZE];
+	/* The saved address of a sent-in-place packet/buffer, for later free(). */
+	struct sk_buff *tx_skbuff[TX_RING_SIZE];
+	struct net_device_stats stats;
+	spinlock_t lock;
+	struct netdev_desc *rx_head_desc;
+	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
+	unsigned int tx_full:1;	/* The Tx queue is full. */
+	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
+	unsigned int speed;	/* Operating speed */
+	unsigned int vlan;	/* VLAN Id */
+	unsigned int an_enable;	/* Auto-Negotiated Enable */
+	unsigned int chip_id;	/* PCI table chip id */
+	unsigned int jumbo;
+	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
+	u64 cur_rx, old_rx;	/* Producer/consumer ring indices */
+	u64 cur_tx, old_tx;
+	int wake_polarity;
+	char name[256];		/* net device description */
+	u8 duplex_polarity;
+	u16 mcast_filter[4];
+	u16 advertising;	/* NWay media advertisement */
+	u16 negotiate;		/* Negotiated media */
+	int phy_addr;		/* PHY addresses. */
+	int tx_debug;
+	int rx_debug;
+};
+
+/* The station address location in the EEPROM. */
+#ifdef USE_IO_OPS
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO  | PCI_ADDR0)
+#else
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
+#endif
+/* The struct pci_device_id consist of:
+        vendor, device          Vendor and device ID to match (or PCI_ANY_ID)
+        subvendor, subdevice    Subsystem vendor and device ID to match (or PCI_ANY_ID)
+        class                   Device class to match. The class_mask tells which bits
+        class_mask              of the class are honored during the comparison.
+        driver_data             Data private to the driver.
+*/
+static struct pci_device_id rio_pci_tbl[] __devinitdata = {
+	{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
+#define TX_TIMEOUT  (4*HZ)
+#define PACKET_SIZE		1536
+#define RIO_IO_SIZE             340
+#ifdef RIO_DEBUG
+#define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
+#define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)
+#define DEBUG_PKT_DUMP(x,len) debug_pkt_dump(x,len)
+#define DEBUG_PRINT printk
+
+static inline void
+debug_tfd_dump (struct netdev_private *np)
+{
+	int i;
+	struct netdev_desc *desc;
+
+	if (np->tx_debug == 6) {
+		printk ("TFDone Dump: ");
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			desc = &np->tx_ring[i];
+			if ((desc->fraginfo & 0xffffffffff) == 0)
+				printk ("X");
+			else
+				printk ("%d", (desc->status & TFDDone) ? 1 : 0);
+		}
+		printk ("\n");
+	}
+	if (np->tx_debug == 5) {
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			desc = &np->tx_ring[i];
+			printk
+			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
+			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
+			     (u32) desc->fraginfo);
+			printk ("\n");
+		}
+		printk ("\n");
+	}
+}
+static inline void
+debug_rfd_dump (struct netdev_private *np, int flag)
+{
+	int i;
+	struct netdev_desc *desc;
+	int entry = np->cur_rx % RX_RING_SIZE;
+
+	if (np->rx_debug == 5) {
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			desc = &np->rx_ring[i];
+			printk
+			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
+			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
+			     (u32) desc->fraginfo);
+			printk ("\n");
+		}
+		printk ("\n");
+	}
+
+	if (np->rx_debug == 6) {
+		if (flag == 1)
+			printk ("RFDone Dump: ");
+		else if (flag == 2)
+			printk ("Re-Filling:  ");
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			desc = &np->rx_ring[i];
+			printk ("%d", (desc->status & RFDDone) ? 1 : 0);
+		}
+		printk ("\n");
+	}
+	if (np->rx_debug == 7) {
+		printk (" In rcv_pkt(), entry %d status %4.4x %4.4x.\n",
+			entry, (u32) (np->rx_ring[entry].status >> 32),
+			(u32) np->rx_ring[entry].status);
+	}
+
+}
+
+static inline void
+debug_pkt_dump (struct netdev_private *np, int pkt_len)
+{
+	int i;
+	struct netdev_desc *desc = np->rx_head_desc;
+	unsigned char *pchar;
+	unsigned char *phead;
+	u64 frame_status = le64_to_cpu (desc->status);
+
+	if (np->rx_debug == 4) {
+		printk ("  rcv_pkt: status was %4.4x %4.4x.\n",
+			(u32) (frame_status >> 32), (u32) frame_status);
+	}
+	if (np->rx_debug == 7) {
+		phead = le64desc_to_virt ((desc->fraginfo & 0xffffffffff));
+		for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) {
+			printk ("%02x ", *pchar);
+			if ((i + 1) % 20 == 0)
+				printk ("\n");
+		}
+	}
+}
+#else
+#define DEBUG_TFD_DUMP(x) {}
+#define DEBUG_RFD_DUMP(x,flag) {}
+#define DEBUG_PKT_DUMP(x,len) {}
+#define DEBUG_PRINT() {}
+#endif
+
+#endif /* __DL2K_H__ */
diff -urN linux-2.4.7-pre3/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.4.7-pre3/drivers/net/epic100.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/epic100.c	Mon Dec  3 22:54:19 2001
@@ -1174,8 +1174,6 @@
 
 			pci_dma_sync_single(ep->pci_dev, ep->rx_ring[entry].bufaddr, 
 					    ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(ep->pci_dev, ep->rx_ring[entry].bufaddr, 
-					 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			if (pkt_len > PKT_BUF_SZ - 4) {
 				printk(KERN_ERR "%s: Oversized Ethernet frame, status %x "
 					   "%d bytes.\n",
@@ -1196,6 +1194,9 @@
 					   pkt_len);
 #endif
 			} else {
+				pci_unmap_single(ep->pci_dev, 
+					ep->rx_ring[entry].bufaddr, 
+					ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
 				ep->rx_skbuff[entry] = NULL;
 			}
diff -urN linux-2.4.7-pre3/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- linux-2.4.7-pre3/drivers/sbus/char/aurora.c	Wed May 16 10:31:27 2001
+++ linux/drivers/sbus/char/aurora.c	Mon Dec  3 22:54:20 2001
@@ -1,4 +1,4 @@
-/*	$Id: aurora.c,v 1.13 2001/05/10 01:45:38 davem Exp $
+/*	$Id: aurora.c,v 1.14 2001/06/29 23:07:37 davem Exp $
  *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -1851,7 +1851,6 @@
 static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd,
 				 unsigned int *value)
 {
-	int error;
 	unsigned int arg;
 	unsigned long flags;
 	struct Aurora_board *bp = port_Board(port);
@@ -1860,9 +1859,8 @@
 #ifdef AURORA_DEBUG
 	printk("aurora_set_modem_info: start\n");
 #endif
-	error = get_user(arg, value);
-	if (error) 
-		return error;
+	if (get_user(arg, value))
+		return -EFAULT;
 	chip = AURORA_CD180(port_No(port));
 	switch (cmd) {
 	 case TIOCMBIS: 
@@ -1940,16 +1938,12 @@
 	struct Aurora_board *bp = port_Board(port);
 	int change_speed;
 	unsigned long flags;
-	int error;
 
 #ifdef AURORA_DEBUG
 	printk("aurora_set_serial_info: start\n");
 #endif
-	error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
-	if (error)
-		return error;
-	copy_from_user(&tmp, newinfo, sizeof(tmp));
-	
+	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+		return -EFAULT;
 #if 0	
 	if ((tmp.irq != bp->irq) ||
 	    (tmp.port != bp->base) ||
@@ -2025,7 +2019,6 @@
 		    
 {
 	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
-	int error;
 	int retval;
 
 #ifdef AURORA_DEBUG
@@ -2051,25 +2044,19 @@
 		aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4);
 		return 0;
 	case TIOCGSOFTCAR:
-		error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
-		if (error)
-			return error;
-		put_user(C_CLOCAL(tty) ? 1 : 0,
-			 (unsigned long *) arg);
-		return 0;
+		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
 	case TIOCSSOFTCAR:
-		retval = get_user(arg,(unsigned long *) arg);
-		if (retval)
-			return retval;
+		if (get_user(arg,(unsigned long *)arg))
+			return -EFAULT;
 		tty->termios->c_cflag =
 			((tty->termios->c_cflag & ~CLOCAL) |
 			 (arg ? CLOCAL : 0));
 		return 0;
 	case TIOCMGET:
-		error = verify_area(VERIFY_WRITE, (void *) arg,
+		retval = verify_area(VERIFY_WRITE, (void *) arg,
 				    sizeof(unsigned int));
-		if (error)
-			return error;
+		if (retval)
+			return retval;
 		return aurora_get_modem_info(port, (unsigned int *) arg);
 	case TIOCMBIS:
 	case TIOCMBIC:
diff -urN linux-2.4.7-pre3/drivers/usb/printer.c linux/drivers/usb/printer.c
--- linux-2.4.7-pre3/drivers/usb/printer.c	Tue Jun 12 15:53:37 2001
+++ linux/drivers/usb/printer.c	Mon Dec  3 22:54:20 2001
@@ -19,6 +19,7 @@
  *	v0.6 - never time out
  *	v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
  *	v0.8 - add devfs support
+ *	v0.9 - fix unplug-while-open paths
  */
 
 /*
@@ -88,6 +89,7 @@
 struct usblp {
 	struct usb_device 	*dev;			/* USB device */
 	devfs_handle_t		devfs;			/* devfs device */
+	struct semaphore	sem;			/* locks this struct, especially "dev" */
 	struct urb		readurb, writeurb;	/* The urbs */
 	wait_queue_head_t	wait;			/* Zzzzz ... */
 	int			readcount;		/* Counter for reads */
@@ -172,9 +174,12 @@
 static int usblp_check_status(struct usblp *usblp, int err)
 {
 	unsigned char status, newerr = 0;
+	int error;
 
-	if (usblp_read_status(usblp, &status)) {
-		err("usblp%d: failed reading printer status", usblp->minor);
+	error = usblp_read_status (usblp, &status);
+	if (error < 0) {
+		err("usblp%d: error %d reading printer status",
+			usblp->minor, error);
 		return 0;
 	}
 
@@ -244,24 +249,30 @@
 	return retval;
 }
 
+static void usblp_cleanup (struct usblp *usblp)
+{
+	devfs_unregister (usblp->devfs);
+	usblp_table [usblp->minor] = NULL;
+	info ("usblp%d: removed", usblp->minor);
+
+	kfree (usblp->writeurb.transfer_buffer);
+	kfree (usblp->device_id_string);
+	kfree (usblp);
+}
+
 static int usblp_release(struct inode *inode, struct file *file)
 {
 	struct usblp *usblp = file->private_data;
 
+	down (&usblp->sem);
 	usblp->used = 0;
-
 	if (usblp->dev) {
 		if (usblp->bidir)
 			usb_unlink_urb(&usblp->readurb);
 		usb_unlink_urb(&usblp->writeurb);
-		return 0;
-	}
-
-	devfs_unregister(usblp->devfs);
-	usblp_table[usblp->minor] = NULL;
-	kfree(usblp->device_id_string);
-	kfree(usblp);
-
+		up(&usblp->sem);
+	} else 		/* finish cleanup from disconnect */
+		usblp_cleanup (usblp);
 	return 0;
 }
 
@@ -279,21 +290,31 @@
 	struct usblp *usblp = file->private_data;
 	int length, err;
 	unsigned char status;
+	int retval = 0;
+
+	down (&usblp->sem);
+	if (!usblp->dev) {
+		retval = -ENODEV;
+		goto done;
+	}
 
 	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */
 	
 		switch (_IOC_NR(cmd)) {
 
 			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
-				if (_IOC_DIR(cmd) != _IOC_READ)
-					return -EINVAL;
+				if (_IOC_DIR(cmd) != _IOC_READ) {
+					retval = -EINVAL;
+					goto done;
+				}
 
 				err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
 				if (err < 0) {
 					dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
 						usblp->minor, err);
 					usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
-					return -EIO;
+					retval = -EIO;
+					goto done;
 				}
 
 				length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
@@ -307,13 +328,16 @@
 
 				if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
 
-				if (copy_to_user((unsigned char *) arg, usblp->device_id_string, (unsigned long) length))
-					return -EFAULT;
+				if (copy_to_user((unsigned char *) arg,
+						usblp->device_id_string, (unsigned long) length)) {
+					retval = -EFAULT;
+					goto done;
+				}
 
 				break;
 
 			default:
-				return -EINVAL;
+				retval = -EINVAL;
 		}
 	else	/* old-style ioctl value */
 		switch (cmd) {
@@ -321,17 +345,20 @@
 			case LPGETSTATUS:
 				if (usblp_read_status(usblp, &status)) {
 					err("usblp%d: failed reading printer status", usblp->minor);
-					return -EIO;
+					retval = -EIO;
+					goto done;
 				}
 				if (copy_to_user ((unsigned char *)arg, &status, 1))
-					return -EFAULT;
+					retval = -EFAULT;
 				break;
 
 			default:
-				return -EINVAL;
+				retval = -EINVAL;
 		}
 
-	return 0;
+done:
+	up (&usblp->sem);
+	return retval;
 }
 
 static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
@@ -341,6 +368,8 @@
 
 	while (writecount < count) {
 
+		// FIXME:  only use urb->status inside completion
+		// callbacks; this way is racey...
 		if (usblp->writeurb.status == -EINPROGRESS) {
 
 			if (file->f_flags & O_NONBLOCK)
@@ -356,28 +385,36 @@
 			}
 		}
 
-		if (!usblp->dev)
+		down (&usblp->sem);
+		if (!usblp->dev) {
+			up (&usblp->sem);
 			return -ENODEV;
+		}
 
-		if (usblp->writeurb.status) {
+		if (usblp->writeurb.status != 0) {
 			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
 				if (usblp->writeurb.status != -EINPROGRESS)
 					err("usblp%d: error %d writing to printer",
 						usblp->minor, usblp->writeurb.status);
 				err = usblp->writeurb.status;
-				continue;
-			}
-			else {
+			} else
 				err = usblp_check_status(usblp, err);
-				continue;
-			}
+			up (&usblp->sem);
+
+			/* if the fault was due to disconnect, let khubd's
+			 * call to usblp_disconnect() grab usblp->sem ...
+			 */
+			schedule ();
+			continue;
 		}
 
 		writecount += usblp->writeurb.transfer_buffer_length;
 		usblp->writeurb.transfer_buffer_length = 0;
 
-		if (writecount == count)
-			continue;
+		if (writecount == count) {
+			up (&usblp->sem);
+			break;
+		}
 
 		usblp->writeurb.transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
 							 (count - writecount) : USBLP_BUF_SIZE;
@@ -387,6 +424,7 @@
 
 		usblp->writeurb.dev = usblp->dev;
 		usb_submit_urb(&usblp->writeurb);
+		up (&usblp->sem);
 	}
 
 	return count;
@@ -399,20 +437,36 @@
 	if (!usblp->bidir)
 		return -EINVAL;
 
+	down (&usblp->sem);
+	if (!usblp->dev) {
+		count = -ENODEV;
+		goto done;
+	}
+
 	if (usblp->readurb.status == -EINPROGRESS) {
 
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
+		if (file->f_flags & O_NONBLOCK) {
+			count = -EAGAIN;
+			goto done;
+		}
 
+		// FIXME:  only use urb->status inside completion
+		// callbacks; this way is racey...
 		while (usblp->readurb.status == -EINPROGRESS) {
-			if (signal_pending(current))
-				return -EINTR;
+			if (signal_pending(current)) {
+				count = -EINTR;
+				goto done;
+			}
+			up (&usblp->sem);
 			interruptible_sleep_on(&usblp->wait);
+			down (&usblp->sem);
 		}
 	}
 
-	if (!usblp->dev)
-		return -ENODEV;
+	if (!usblp->dev) {
+		count = -ENODEV;
+		goto done;
+	}
 
 	if (usblp->readurb.status) {
 		err("usblp%d: error %d reading from printer",
@@ -420,14 +474,17 @@
 		usblp->readurb.dev = usblp->dev;
  		usblp->readcount = 0;
 		usb_submit_urb(&usblp->readurb);
-		return -EIO;
+		count = -EIO;
+		goto done;
 	}
 
 	count = count < usblp->readurb.actual_length - usblp->readcount ?
 		count :	usblp->readurb.actual_length - usblp->readcount;
 
-	if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count))
-		return -EFAULT;
+	if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count)) {
+		count = -EFAULT;
+		goto done;
+	}
 
 	if ((usblp->readcount += count) == usblp->readurb.actual_length) {
 		usblp->readcount = 0;
@@ -435,6 +492,8 @@
 		usb_submit_urb(&usblp->readurb);
 	}
 
+done:
+	up (&usblp->sem);
 	return count;
 }
 
@@ -537,6 +596,7 @@
 		return NULL;
 	}
 	memset(usblp, 0, sizeof(struct usblp));
+	init_MUTEX (&usblp->sem);
 
 	/* lookup quirks for this printer */
 	quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
@@ -599,14 +659,12 @@
 
 	sprintf(name, "lp%d", minor);
 	
-	/* Create with perms=664 */
+	/* if we have devfs, create with perms=660 */
 	usblp->devfs = devfs_register(usb_devfs_handle, name,
 				      DEVFS_FL_DEFAULT, USB_MAJOR,
 				      USBLP_MINOR_BASE + minor,
 				      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
 				      S_IWGRP, &usblp_fops, NULL);
-	if (usblp->devfs == NULL)
-		err("usblp%d: device node registration failed", minor);
 
 	info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
 		minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
@@ -619,25 +677,21 @@
 	struct usblp *usblp = ptr;
 
 	if (!usblp || !usblp->dev) {
-		err("disconnect on nonexisting interface");
-		return;
+		err("bogus disconnect");
+		BUG ();
 	}
 
+	down (&usblp->sem);
 	usblp->dev = NULL;
 
 	usb_unlink_urb(&usblp->writeurb);
 	if (usblp->bidir)
 		usb_unlink_urb(&usblp->readurb);
 
-	kfree(usblp->writeurb.transfer_buffer);
-
-	if (usblp->used) return;
-
-	kfree(usblp->device_id_string);
-
-	devfs_unregister(usblp->devfs);
-	usblp_table[usblp->minor] = NULL;
-	kfree(usblp);
+	if (!usblp->used)
+		usblp_cleanup (usblp);
+	else 	/* cleanup later, on close */
+		up (&usblp->sem);
 }
 
 static struct usb_device_id usblp_ids [] = {
diff -urN linux-2.4.7-pre3/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- linux-2.4.7-pre3/drivers/usb/scanner.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/usb/scanner.c	Mon Dec  3 22:54:20 2001
@@ -909,7 +909,7 @@
 		return result;
 	}
 	default:
-		return -ENOIOCTLCMD;
+		return -ENOTTY;
 	}
 	return 0;
 }
diff -urN linux-2.4.7-pre3/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c
--- linux-2.4.7-pre3/drivers/usb/serial/empeg.c	Wed Jun 20 16:52:30 2001
+++ linux/drivers/usb/serial/empeg.c	Mon Dec  3 22:54:20 2001
@@ -247,7 +247,6 @@
 static void empeg_close (struct usb_serial_port *port, struct file * filp)
 {
 	struct usb_serial *serial;
-	unsigned char *transfer_buffer;
 
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
@@ -263,14 +262,6 @@
 	--port->open_count;
 
 	if (port->open_count <= 0) {
-		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
-
-		if (!transfer_buffer) {
-			err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
-		} else {
-			kfree (transfer_buffer);
-		}
-
 		/* shutdown our bulk read */
 		usb_unlink_urb (port->read_urb);
 		port->active = 0;
diff -urN linux-2.4.7-pre3/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- linux-2.4.7-pre3/drivers/usb/serial/ftdi_sio.c	Wed Jun 20 16:52:30 2001
+++ linux/drivers/usb/serial/ftdi_sio.c	Mon Dec  3 22:54:20 2001
@@ -902,7 +902,8 @@
 
 	case TIOCMSET: /* Turns on and off the lines as specified by the mask */
 		dbg(__FUNCTION__ " TIOCMSET");
-		if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+		if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
 		urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
 		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
 			err("Error from DTR set urb (TIOCMSET)");
@@ -915,7 +916,8 @@
 					
 	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
 		dbg(__FUNCTION__ " TIOCMBIS");
- 	        if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
   	        if (mask & TIOCM_DTR){
 			if ((ret = set_dtr(serial->dev, 
 					   usb_sndctrlpipe(serial->dev, 0),
@@ -936,7 +938,8 @@
 
 	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
 		dbg(__FUNCTION__ " TIOCMBIC");
- 	        if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
   	        if (mask & TIOCM_DTR){
 			if ((ret = set_dtr(serial->dev, 
 					   usb_sndctrlpipe(serial->dev, 0),
diff -urN linux-2.4.7-pre3/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- linux-2.4.7-pre3/drivers/usb/serial/usbserial.c	Wed Jun 20 16:52:30 2001
+++ linux/drivers/usb/serial/usbserial.c	Mon Dec  3 22:54:20 2001
@@ -15,6 +15,13 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (07/03/2001) gkh
+ *	Fixed module paramater size.  Thanks to John Brockmeyer for the pointer.
+ *	Fixed vendor and product getting defined through the MODULE_PARM macro
+ *	if the Generic driver wasn't compiled in.
+ *	Fixed problem with generic_shutdown() not being called for drivers that
+ *	don't have a shutdown() function.
+ *
  * (06/06/2001) gkh
  *	added evil hack that is needed for the prolific pl2303 device due to the
  *	crazy way its endpoints are set up.
@@ -296,7 +303,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.2"
+#define DRIVER_VERSION "v1.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
 #define DRIVER_DESC "USB Serial Driver core"
 
@@ -347,6 +354,7 @@
 static void serial_unthrottle (struct tty_struct * tty);
 static int  serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
 static void serial_set_termios (struct tty_struct *tty, struct termios * old);
+static void serial_shutdown (struct usb_serial *serial);
 
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
 			       const struct usb_device_id *id);
@@ -736,6 +744,16 @@
 }
 
 
+static void serial_shutdown (struct usb_serial *serial)
+{
+	if (serial->type->shutdown) {
+		serial->type->shutdown(serial);
+	} else {
+		generic_shutdown(serial);
+	}
+}
+
+
 
 /*****************************************************************************
  * generic devices specific driver functions
@@ -1311,8 +1329,7 @@
 				serial->port[i].tty->driver_data = NULL;
 		}
 
-		if (serial->type->shutdown)
-			serial->type->shutdown(serial);
+		serial_shutdown (serial);
 
 		for (i = 0; i < serial->num_ports; ++i)
 			serial->port[i].active = 0;
@@ -1426,7 +1443,7 @@
 		return -1;
 	}
 
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 
 	return 0;
 }
@@ -1500,9 +1517,11 @@
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-MODULE_PARM(vendor, "i");
+#ifdef CONFIG_USB_SERIAL_GENERIC
+MODULE_PARM(vendor, "h");
 MODULE_PARM_DESC(vendor, "User specified USB idVendor");
 
-MODULE_PARM(product, "i");
+MODULE_PARM(product, "h");
 MODULE_PARM_DESC(product, "User specified USB idProduct");
+#endif
 
diff -urN linux-2.4.7-pre3/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- linux-2.4.7-pre3/drivers/usb/usb-ohci.c	Wed Jun 27 13:15:17 2001
+++ linux/drivers/usb/usb-ohci.c	Mon Dec  3 22:54:20 2001
@@ -2749,7 +2749,7 @@
 
 		switch (when) {
 		case PBOOK_SLEEP_NOW:
-			ohci_pci_suspend (ohci->ohci_dev);
+			ohci_pci_suspend (ohci->ohci_dev, 3);
 			break;
 		case PBOOK_WAKE:
 			ohci_pci_resume (ohci->ohci_dev);
diff -urN linux-2.4.7-pre3/drivers/video/hgafb.c linux/drivers/video/hgafb.c
--- linux-2.4.7-pre3/drivers/video/hgafb.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/video/hgafb.c	Mon Dec  3 22:54:20 2001
@@ -49,7 +49,7 @@
 
 #ifdef MODULE
 
-#define INCLUDE_LINUX_LOGOBW
+#define INCLUDE_LINUX_LOGO_DATA
 #include <linux/linux_logo.h>
 
 #endif /* MODULE */
diff -urN linux-2.4.7-pre3/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- linux-2.4.7-pre3/drivers/video/imsttfb.c	Mon Dec  3 22:54:11 2001
+++ linux/drivers/video/imsttfb.c	Mon Dec  3 22:54:20 2001
@@ -1278,10 +1278,11 @@
 				break;
 #endif
 #ifdef FBCON_HAS_CFB32
-			case 32:
-				i = (regno << 8) | regno;
+			case 32: {
+				int i = (regno << 8) | regno;
 				p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
 				break;
+			}
 #endif
 		}
 
diff -urN linux-2.4.7-pre3/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.7-pre3/fs/buffer.c	Sat Jun 30 10:44:32 2001
+++ linux/fs/buffer.c	Mon Dec  3 22:54:20 2001
@@ -71,6 +71,9 @@
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_inode_buffers)
 
+#define get_bh(bh)	atomic_inc(&(bh)->b_count)
+#define put_bh(bh)	atomic_dec(&(bh)->b_count)
+
 /*
  * Hash table gook..
  */
@@ -133,6 +136,21 @@
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   1*HZ,   0, 0, 0};
 int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,600*HZ, 6000*HZ, 100, 0, 0};
 
+static inline void __unlock_buffer(struct buffer_head *bh)
+{
+	clear_bit(BH_Lock, &bh->b_state);
+	smp_mb__after_clear_bit();
+	if (waitqueue_active(&bh->b_wait))
+		wake_up(&bh->b_wait);
+}
+
+void unlock_buffer(struct buffer_head *bh)
+{
+	get_bh(bh);
+	__unlock_buffer(bh);
+	put_bh(bh);
+}
+
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
  * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -147,7 +165,7 @@
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
 
-	atomic_inc(&bh->b_count);
+	get_bh(bh);
 	add_wait_queue(&bh->b_wait, &wait);
 	do {
 		run_task_queue(&tq_disk);
@@ -158,14 +176,15 @@
 	} while (buffer_locked(bh));
 	tsk->state = TASK_RUNNING;
 	remove_wait_queue(&bh->b_wait, &wait);
-	atomic_dec(&bh->b_count);
+	put_bh(bh);
 }
 
 /* End-of-write handler.. Just mark it up-to-date and unlock the buffer. */
 static void end_buffer_write(struct buffer_head *bh, int uptodate)
 {
 	mark_buffer_uptodate(bh, uptodate);
-	unlock_buffer(bh);
+	__unlock_buffer(bh);
+	put_bh(bh);
 }
 
 /*
@@ -179,14 +198,14 @@
 static void write_locked_buffers(struct buffer_head **array, unsigned int count)
 {
 	struct buffer_head *wait = *array;
-	atomic_inc(&wait->b_count);
+	get_bh(wait);
 	do {
 		struct buffer_head * bh = *array++;
 		bh->b_end_io = end_buffer_write;
 		submit_bh(WRITE, bh);
 	} while (--count);
 	wait_on_buffer(wait);
-	atomic_dec(&wait->b_count);
+	put_bh(wait);
 }
 
 #define NRSYNC (32)
@@ -210,6 +229,7 @@
 			continue;
 		if (test_and_set_bit(BH_Lock, &bh->b_state))
 			continue;
+		get_bh(bh);
 		if (atomic_set_buffer_clean(bh)) {
 			__refile_buffer(bh);
 			array[count++] = bh;
@@ -220,7 +240,8 @@
 			write_locked_buffers(array, count);
 			goto repeat;
 		}
-		unlock_buffer(bh);
+		__unlock_buffer(bh);
+		put_bh(bh);
 	}
 	spin_unlock(&lru_list_lock);
 
@@ -249,10 +270,10 @@
 		if (dev && bh->b_dev != dev)
 			continue;
 
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 		spin_unlock(&lru_list_lock);
 		wait_on_buffer (bh);
-		atomic_dec(&bh->b_count);
+		put_bh(bh);
 		goto repeat;
 	}
 	spin_unlock(&lru_list_lock);
@@ -552,7 +573,7 @@
 		    bh->b_dev     == dev)
 			break;
 	if (bh)
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 
 	return bh;
 }
@@ -646,12 +667,12 @@
 			if (!bh->b_pprev)
 				continue;
 			if (buffer_locked(bh)) {
-				atomic_inc(&bh->b_count);
+				get_bh(bh);
 				spin_unlock(&lru_list_lock);
 				wait_on_buffer(bh);
 				slept = 1;
 				spin_lock(&lru_list_lock);
-				atomic_dec(&bh->b_count);
+				put_bh(bh);
 			}
 
 			write_lock(&hash_table_lock);
@@ -711,12 +732,12 @@
 			if (!bh->b_pprev)
 				continue;
 			if (buffer_locked(bh)) {
-				atomic_inc(&bh->b_count);
+				get_bh(bh);
 				spin_unlock(&lru_list_lock);
 				wait_on_buffer(bh);
 				slept = 1;
 				spin_lock(&lru_list_lock);
-				atomic_dec(&bh->b_count);
+				put_bh(bh);
 			}
 
 			write_lock(&hash_table_lock);
@@ -802,8 +823,7 @@
 	 * that unlock the page..
 	 */
 	spin_lock_irqsave(&page_uptodate_lock, flags);
-	unlock_buffer(bh);
-	atomic_dec(&bh->b_count);
+	__unlock_buffer(bh);
 	tmp = bh->b_this_page;
 	while (tmp != bh) {
 		if (tmp->b_end_io == end_buffer_io_async && buffer_locked(tmp))
@@ -813,6 +833,7 @@
 
 	/* OK, the async IO on this page is complete. */
 	spin_unlock_irqrestore(&page_uptodate_lock, flags);
+	put_bh(bh);
 
 	/*
 	 * if none of the buffers had errors then we can set the
@@ -832,6 +853,7 @@
 	return;
 
 still_busy:
+	put_bh(bh);
 	spin_unlock_irqrestore(&page_uptodate_lock, flags);
 	return;
 }
@@ -879,7 +901,7 @@
 			bh->b_inode = &tmp;
 			list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
 			if (buffer_dirty(bh)) {
-				atomic_inc(&bh->b_count);
+				get_bh(bh);
 				spin_unlock(&lru_list_lock);
 				ll_rw_block(WRITE, 1, &bh);
 				brelse(bh);
@@ -891,7 +913,7 @@
 	while (!list_empty(&tmp.i_dirty_buffers)) {
 		bh = BH_ENTRY(tmp.i_dirty_buffers.prev);
 		remove_inode_queue(bh);
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 		spin_unlock(&lru_list_lock);
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh))
@@ -935,7 +957,7 @@
 	     bh = BH_ENTRY(list), list != &inode->i_dirty_buffers;
 	     list = bh->b_inode_buffers.prev) {
 		if (buffer_locked(bh)) {
-			atomic_inc(&bh->b_count);
+			get_bh(bh);
 			spin_unlock(&lru_list_lock);
 			wait_on_buffer(bh);
 			if (!buffer_uptodate(bh))
@@ -1130,7 +1152,7 @@
 void __brelse(struct buffer_head * buf)
 {
 	if (atomic_read(&buf->b_count)) {
-		atomic_dec(&buf->b_count);
+		put_bh(buf);
 		return;
 	}
 	printk("VFS: brelse: Trying to free free buffer\n");
@@ -1528,7 +1550,7 @@
 	do {
 		lock_buffer(bh);
 		bh->b_end_io = end_buffer_io_async;
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 		set_bit(BH_Uptodate, &bh->b_state);
 		clear_bit(BH_Dirty, &bh->b_state);
 		bh = bh->b_this_page;
@@ -1536,8 +1558,9 @@
 
 	/* Stage 3: submit the IO */
 	do {
+		struct buffer_head *next = bh->b_this_page;
 		submit_bh(WRITE, bh);
-		bh = bh->b_this_page;		
+		bh = next;
 	} while (bh != head);
 
 	/* Done - end_buffer_io_async will unlock */
@@ -1729,7 +1752,7 @@
 		struct buffer_head * bh = arr[i];
 		lock_buffer(bh);
 		bh->b_end_io = end_buffer_io_async;
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 	}
 
 	/* Stage 3: start the IO */
@@ -1982,7 +2005,8 @@
 	mark_buffer_uptodate(bh, uptodate);
 
 	kiobuf = bh->b_private;
-	unlock_buffer(bh);
+	__unlock_buffer(bh);
+	put_bh(bh);
 	end_kio_request(kiobuf, uptodate);
 }
 
@@ -2107,7 +2131,7 @@
 				offset += size;
 
 				atomic_inc(&iobuf->io_count);
-
+				get_bh(tmp);
 				submit_bh(rw, tmp);
 				/* 
 				 * Wait for IO if we have got too much 
@@ -2175,14 +2199,15 @@
 		bh->b_blocknr = *(b++);
 		set_bit(BH_Mapped, &bh->b_state);
 		bh->b_end_io = end_buffer_io_async;
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 		bh = bh->b_this_page;
 	} while (bh != head);
 
 	/* Stage 2: start the IO */
 	do {
+		struct buffer_head *next = bh->b_this_page;
 		submit_bh(rw, bh);
-		bh = bh->b_this_page;
+		bh = next;
 	} while (bh != head);
 	return 0;
 }
@@ -2554,10 +2579,10 @@
 		}
 
 		/* OK, now we are committed to write it out. */
-		atomic_inc(&bh->b_count);
+		get_bh(bh);
 		spin_unlock(&lru_list_lock);
 		ll_rw_block(WRITE, 1, &bh);
-		atomic_dec(&bh->b_count);
+		put_bh(bh);
 
 		if (current->need_resched)
 			schedule();
diff -urN linux-2.4.7-pre3/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- linux-2.4.7-pre3/fs/proc/proc_misc.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/proc/proc_misc.c	Mon Dec  3 22:54:20 2001
@@ -146,51 +146,53 @@
  */
 #define K(x) ((x) << (PAGE_SHIFT - 10))
 #define B(x) ((x) << PAGE_SHIFT)
-        si_meminfo(&i);
-        si_swapinfo(&i);
-        len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
-                "Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
-                "Swap: %8lu %8lu %8lu\n",
-                B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
-                B(i.sharedram), B(i.bufferram),
-                B(atomic_read(&page_cache_size)), B(i.totalswap),
-                B(i.totalswap-i.freeswap), B(i.freeswap));
-        /*
-         * Tagged format, for easy grepping and expansion.
-         * The above will go away eventually, once the tools
-         * have been updated.
-         */
-        len += sprintf(page+len,
-                "MemTotal:     %8lu kB\n"
-                "MemFree:      %8lu kB\n"
-                "MemShared:    %8lu kB\n"
-                "Buffers:      %8lu kB\n"
-                "Cached:       %8u kB\n"
+	si_meminfo(&i);
+	si_swapinfo(&i);
+	len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
+		"Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
+		"Swap: %8lu %8lu %8lu\n",
+		B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
+		B(i.sharedram), B(i.bufferram),
+		B(atomic_read(&page_cache_size)), B(i.totalswap),
+		B(i.totalswap-i.freeswap), B(i.freeswap));
+	/*
+	 * Tagged format, for easy grepping and expansion.
+	 * The above will go away eventually, once the tools
+	 * have been updated.
+	 */
+	len += sprintf(page+len,
+		"MemTotal:     %8lu kB\n"
+		"MemFree:      %8lu kB\n"
+		"MemShared:    %8lu kB\n"
+		"Buffers:      %8lu kB\n"
+		"Cached:       %8lu kB\n"
+		"SwapCached:   %8lu kB\n"
 		"Active:       %8u kB\n"
 		"Inact_dirty:  %8u kB\n"
 		"Inact_clean:  %8u kB\n"
 		"Inact_target: %8lu kB\n"
-                "HighTotal:    %8lu kB\n"
-                "HighFree:     %8lu kB\n"
-                "LowTotal:     %8lu kB\n"
-                "LowFree:      %8lu kB\n"
-                "SwapTotal:    %8lu kB\n"
-                "SwapFree:     %8lu kB\n",
-                K(i.totalram),
-                K(i.freeram),
-                K(i.sharedram),
-                K(i.bufferram),
-                K(atomic_read(&page_cache_size)),
+		"HighTotal:    %8lu kB\n"
+		"HighFree:     %8lu kB\n"
+		"LowTotal:     %8lu kB\n"
+		"LowFree:      %8lu kB\n"
+		"SwapTotal:    %8lu kB\n"
+		"SwapFree:     %8lu kB\n",
+		K(i.totalram),
+		K(i.freeram),
+		K(i.sharedram),
+		K(i.bufferram),
+		K(atomic_read(&page_cache_size) - swapper_space.nrpages),
+		K(swapper_space.nrpages),
 		K(nr_active_pages),
 		K(nr_inactive_dirty_pages),
 		K(nr_inactive_clean_pages()),
 		K(inactive_target),
-                K(i.totalhigh),
-                K(i.freehigh),
-                K(i.totalram-i.totalhigh),
-                K(i.freeram-i.freehigh),
-                K(i.totalswap),
-                K(i.freeswap));
+		K(i.totalhigh),
+		K(i.freehigh),
+		K(i.totalram-i.totalhigh),
+		K(i.freeram-i.freehigh),
+		K(i.totalswap),
+		K(i.freeswap));
 
 	return proc_calc_metrics(page, start, off, count, eof, len);
 #undef B
@@ -289,11 +291,11 @@
 			kstat.per_cpu_nice[cpu_logical_map(i)],
 			kstat.per_cpu_system[cpu_logical_map(i)],
 			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
-			           + kstat.per_cpu_nice[cpu_logical_map(i)] \
-			           + kstat.per_cpu_system[cpu_logical_map(i)]));
+				   + kstat.per_cpu_nice[cpu_logical_map(i)] \
+				   + kstat.per_cpu_system[cpu_logical_map(i)]));
 	len += sprintf(page + len,
 		"page %u %u\n"
-                "swap %u %u\n"
+		"swap %u %u\n"
 		"intr %u",
 			kstat.pgpgin >> 1,
 			kstat.pgpgout >> 1,
diff -urN linux-2.4.7-pre3/fs/sysv/dir.c linux/fs/sysv/dir.c
--- linux-2.4.7-pre3/fs/sysv/dir.c	Mon Jul  2 14:03:04 2001
+++ linux/fs/sysv/dir.c	Mon Dec  3 22:54:20 2001
@@ -211,7 +211,7 @@
 	if (err)
 		goto out_unlock;
 	memcpy (de->name, name, namelen);
-	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen);
+	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
 	de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino);
 	err = dir_commit_chunk(page, from, to);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
diff -urN linux-2.4.7-pre3/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h
--- linux-2.4.7-pre3/include/asm-sparc/vaddrs.h	Mon Jul  2 13:56:40 2001
+++ linux/include/asm-sparc/vaddrs.h	Mon Dec  3 22:54:20 2001
@@ -1,4 +1,4 @@
-/* $Id: vaddrs.h,v 1.26 2000/08/01 04:53:58 anton Exp $ */
+/* $Id: vaddrs.h,v 1.27 2001/07/04 00:18:18 davem Exp $ */
 #ifndef _SPARC_VADDRS_H
 #define _SPARC_VADDRS_H
 
diff -urN linux-2.4.7-pre3/include/asm-sparc64/starfire.h linux/include/asm-sparc64/starfire.h
--- linux-2.4.7-pre3/include/asm-sparc64/starfire.h	Mon Jul  2 13:56:40 2001
+++ linux/include/asm-sparc64/starfire.h	Mon Dec  3 22:54:20 2001
@@ -1,4 +1,4 @@
-/* $Id: starfire.h,v 1.1 2000/09/21 06:18:53 anton Exp $
+/* $Id: starfire.h,v 1.2 2001/07/04 00:18:18 davem Exp $
  * starfire.h: Group all starfire specific code together.
  *
  * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
diff -urN linux-2.4.7-pre3/include/linux/if_arp.h linux/include/linux/if_arp.h
--- linux-2.4.7-pre3/include/linux/if_arp.h	Tue Jul  3 15:43:04 2001
+++ linux/include/linux/if_arp.h	Mon Dec  3 22:54:20 2001
@@ -35,6 +35,7 @@
 #define	ARPHRD_IEEE802	6		/* IEEE 802.2 Ethernet/TR/TB	*/
 #define	ARPHRD_ARCNET	7		/* ARCnet			*/
 #define	ARPHRD_APPLETLK	8		/* APPLEtalk			*/
+#define	ARPHRD_IEEE1394	9		/* IEEE 1394 IPv4 - RFC 2734	*/
 #define ARPHRD_DLCI	15		/* Frame Relay DLCI		*/
 #define ARPHRD_ATM	19		/* ATM 				*/
 #define ARPHRD_METRICOM	23		/* Metricom STRIP (new IANA id)	*/
diff -urN linux-2.4.7-pre3/include/linux/isdnif.h linux/include/linux/isdnif.h
--- linux-2.4.7-pre3/include/linux/isdnif.h	Mon Jul  2 14:07:55 2001
+++ linux/include/linux/isdnif.h	Mon Dec  3 22:54:20 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.37.6.4 2001/06/09 15:14:19 kai Exp $
+/* $Id: isdnif.h,v 1.37.6.5 2001/06/11 22:08:38 kai Exp $
 
  * Linux ISDN subsystem
  *
diff -urN linux-2.4.7-pre3/include/linux/locks.h linux/include/linux/locks.h
--- linux-2.4.7-pre3/include/linux/locks.h	Tue Jul  3 15:43:04 2001
+++ linux/include/linux/locks.h	Mon Dec  3 22:54:20 2001
@@ -26,13 +26,7 @@
 		__wait_on_buffer(bh);
 }
 
-extern inline void unlock_buffer(struct buffer_head *bh)
-{
-	clear_bit(BH_Lock, &bh->b_state);
-	smp_mb__after_clear_bit();
-	if (waitqueue_active(&bh->b_wait))
-		wake_up(&bh->b_wait);
-}
+extern void unlock_buffer(struct buffer_head *bh);
 
 /*
  * super-block locking. Again, interrupts may only unlock
diff -urN linux-2.4.7-pre3/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.7-pre3/kernel/ksyms.c	Mon Jun 11 19:15:27 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 22:54:20 2001
@@ -194,6 +194,7 @@
 EXPORT_SYMBOL(__bforget);
 EXPORT_SYMBOL(ll_rw_block);
 EXPORT_SYMBOL(submit_bh);
+EXPORT_SYMBOL(unlock_buffer);
 EXPORT_SYMBOL(__wait_on_buffer);
 EXPORT_SYMBOL(___wait_on_page);
 EXPORT_SYMBOL(block_write_full_page);
diff -urN linux-2.4.7-pre3/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.7-pre3/mm/filemap.c	Tue Jun 12 11:16:41 2001
+++ linux/mm/filemap.c	Mon Dec  3 22:54:20 2001
@@ -1649,10 +1649,13 @@
 {
 	pte_t pte = *ptep;
 
-	if (pte_present(pte) && ptep_test_and_clear_dirty(ptep)) {
+	if (pte_present(pte)) {
 		struct page *page = pte_page(pte);
-		flush_tlb_page(vma, address);
-		set_page_dirty(page);
+		if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
+			flush_tlb_page(vma, address);
+			if (page->mapping)
+				set_page_dirty(page);
+		}
 	}
 	return 0;
 }
diff -urN linux-2.4.7-pre3/mm/memory.c linux/mm/memory.c
--- linux-2.4.7-pre3/mm/memory.c	Mon Jun 11 19:15:27 2001
+++ linux/mm/memory.c	Mon Dec  3 22:54:20 2001
@@ -1108,9 +1108,6 @@
 			spin_lock(&mm->page_table_lock);
 			return -1;
 		}
-		wait_on_page(page);
-		flush_page_to_ram(page);
-		flush_icache_page(vma, page);
 	}
 
 	/*
@@ -1140,6 +1137,8 @@
 		pte = pte_mkwrite(pte_mkdirty(pte));
 	UnlockPage(page);
 
+	flush_page_to_ram(page);
+	flush_icache_page(vma, page);
 	set_pte(page_table, pte);
 
 	/* No need to invalidate - it was non-present before */
diff -urN linux-2.4.7-pre3/mm/oom_kill.c linux/mm/oom_kill.c
--- linux-2.4.7-pre3/mm/oom_kill.c	Tue May 15 00:25:41 2001
+++ linux/mm/oom_kill.c	Mon Dec  3 22:54:20 2001
@@ -191,11 +191,28 @@
  */
 int out_of_memory(void)
 {
+	long cache_mem, limit;
+
 	/* Enough free memory?  Not OOM. */
 	if (nr_free_pages() > freepages.min)
 		return 0;
 
 	if (nr_free_pages() + nr_inactive_clean_pages() > freepages.low)
+		return 0;
+
+	/*
+	 * If the buffer and page cache (excluding swap cache) are over
+	 * their (/proc tunable) minimum, we're still not OOM.  We test
+	 * this to make sure we don't return OOM when the system simply
+	 * has a hard time with the cache.
+	 */
+	cache_mem = atomic_read(&page_cache_size);
+	cache_mem += atomic_read(&buffermem_pages);
+	cache_mem -= swapper_space.nrpages;
+	limit = (page_cache.min_percent + buffer_mem.min_percent);
+	limit *= num_physpages / 100;
+
+	if (cache_mem > limit)
 		return 0;
 
 	/* Enough swap space left?  Not OOM. */
diff -urN linux-2.4.7-pre3/mm/shmem.c linux/mm/shmem.c
--- linux-2.4.7-pre3/mm/shmem.c	Tue May 22 09:31:25 2001
+++ linux/mm/shmem.c	Mon Dec  3 22:54:20 2001
@@ -223,7 +223,7 @@
  */
 static int shmem_writepage(struct page * page)
 {
-	int error = 0;
+	int error;
 	struct shmem_inode_info *info;
 	swp_entry_t *entry, swap;
 	struct inode *inode;
@@ -231,17 +231,14 @@
 	if (!PageLocked(page))
 		BUG();
 	
-	/* Only move to the swap cache if there are no other users of
-	 * the page. */
-	if (atomic_read(&page->count) > 2)
-		goto out;
-	
 	inode = page->mapping->host;
 	info = &inode->u.shmem_i;
 	swap = __get_swap_page(2);
 	error = -ENOMEM;
-	if (!swap.val)
+	if (!swap.val) {
+		activate_page(page);
 		goto out;
+	}
 
 	spin_lock(&info->lock);
 	entry = shmem_swp_entry(info, page->index);
diff -urN linux-2.4.7-pre3/mm/swap_state.c linux/mm/swap_state.c
--- linux-2.4.7-pre3/mm/swap_state.c	Mon Jun 11 19:15:27 2001
+++ linux/mm/swap_state.c	Mon Dec  3 22:54:20 2001
@@ -81,6 +81,7 @@
 		BUG();
 	flags = page->flags & ~((1 << PG_error) | (1 << PG_arch_1));
 	page->flags = flags | (1 << PG_uptodate);
+	page->age = PAGE_AGE_START;
 	add_to_page_cache_locked(page, &swapper_space, entry.val);
 }
 
diff -urN linux-2.4.7-pre3/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- linux-2.4.7-pre3/net/decnet/dn_dev.c	Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/dn_dev.c	Mon Dec  3 22:54:20 2001
@@ -68,106 +68,77 @@
 
 static struct dn_dev_parms dn_dev_list[] =  {
 {
-	ARPHRD_ETHER, /* Ethernet */
-	DN_DEV_BCAST,
-	DN_DEV_S_RU,
-	0,
-	1498,
-	1,
-	10,
-	0,
-	"ethernet",
-	NET_DECNET_CONF_ETHER,
-	dn_eth_up,
-	NULL,
-	dn_send_brd_hello,
-	NULL
+	type:		ARPHRD_ETHER, /* Ethernet */
+	mode:		DN_DEV_BCAST,
+	state:		DN_DEV_S_RU,
+	blksize:	1498,
+	t2:		1,
+	t3:		10,
+	name:		"ethernet",
+	ctl_name:	NET_DECNET_CONF_ETHER,
+	up:		dn_eth_up,
+	timer3:		dn_send_brd_hello,
 },
 {
-	ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
-	DN_DEV_BCAST,
-	DN_DEV_S_RU,
-	0,
-	1400,
-	1,
-	10,
-	0,
-	"ipgre",
-	NET_DECNET_CONF_GRE,
-	NULL,
-	NULL,
-	dn_send_brd_hello,
-	NULL
+	type:		ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
+	mode:		DN_DEV_BCAST,
+	state:		DN_DEV_S_RU,
+	blksize:	1400,
+	t2:		1,
+	t3:		10,
+	name:		"ipgre",
+	ctl_name:	NET_DECNET_CONF_GRE,
+	timer3:		dn_send_brd_hello,
 },
 #if 0
 {
-	ARPHRD_X25, /* Bog standard X.25 */
-	DN_DEV_UCAST,
-	DN_DEV_S_DS,
-	0,
-	230,
-	1,
-	120,
-	0,
-	"x25",
-	NET_DECNET_CONF_X25,
-	NULL,
-	NULL,
-	dn_send_ptp_hello,
-	NULL
+	type:		ARPHRD_X25, /* Bog standard X.25 */
+	mode:		DN_DEV_UCAST,
+	state:		DN_DEV_S_DS,
+	blksize:	230,
+	t2:		1,
+	t3:		120,
+	name:		"x25",
+	ctl_name:	NET_DECNET_CONF_X25,
+	timer3:		dn_send_ptp_hello,
 },
 #endif
 #if 0
 {
-	ARPHRD_PPP, /* DECnet over PPP */
-	DN_DEV_BCAST,
-	DN_DEV_S_RU,
-	0,
-	230,
-	1,
-	10,
-	0,
-	"ppp",
-	NET_DECNET_CONF_PPP,
-	NULL,
-	NULL,
-	dn_send_brd_hello,
-	NULL
+	type:		ARPHRD_PPP, /* DECnet over PPP */
+	mode:		DN_DEV_BCAST,
+	state:		DN_DEV_S_RU,
+	blksize:	230,
+	t2:		1,
+	t3:		10,
+	name:		"ppp",
+	ctl_name:	NET_DECNET_CONF_PPP,
+	timer3:		dn_send_brd_hello,
 },
 #endif
 #if 0
 {
-	ARPHRD_DDCMP, /* DECnet over DDCMP */
-	DN_DEV_UCAST,
-	DN_DEV_S_DS,
-	0,
-	230,
-	1,
-	120,
-	0,
-	"ddcmp",
-	NET_DECNET_CONF_DDCMP,
-	NULL,
-	NULL,
-	dn_send_ptp_hello,
-	NULL
+	type:		ARPHRD_DDCMP, /* DECnet over DDCMP */
+	mode:		DN_DEV_UCAST,
+	state:		DN_DEV_S_DS,
+	blksize:	230,
+	t2:		1,
+	t3:		120,
+	name:		"ddcmp",
+	ctl_name:	NET_DECNET_CONF_DDCMP,
+	timer3:		dn_send_ptp_hello,
 },
 #endif
 {
-	ARPHRD_LOOPBACK, /* Loopback interface - always last */
-	DN_DEV_BCAST,
-	DN_DEV_S_RU,
-	0,
-	1498,
-	1,
-	10,
-	0,
-	"loopback",
-	NET_DECNET_CONF_LOOPBACK,
-	NULL,
-	NULL,
-	dn_send_brd_hello,
-	NULL
+	type:		ARPHRD_LOOPBACK, /* Loopback interface - always last */
+	mode:		DN_DEV_BCAST,
+	state:		DN_DEV_S_RU,
+	blksize:	1498,
+	t2:		1,
+	t3:		10,
+	name:		"loopback",
+	ctl_name:	NET_DECNET_CONF_LOOPBACK,
+	timer3:		dn_send_brd_hello,
 }
 };
 
@@ -182,7 +153,7 @@
 static int min_t3[] = { 1 };
 static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MULT or T3MULT */
 
-static int min_priority[] = { 0 };
+static int min_priority[1];
 static int max_priority[] = { 127 }; /* From DECnet spec */
 
 static int dn_forwarding_proc(ctl_table *, int, struct file *,
@@ -344,7 +315,8 @@
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		get_user(value, (int *)newval);
+		if (get_user(value, (int *)newval))
+			return -EFAULT;
 		if (value < 0)
 			return -EINVAL;
 		if (value > 2)
diff -urN linux-2.4.7-pre3/net/ipv4/netfilter/ip_queue.c linux/net/ipv4/netfilter/ip_queue.c
--- linux-2.4.7-pre3/net/ipv4/netfilter/ip_queue.c	Mon Dec 11 12:37:04 2000
+++ linux/net/ipv4/netfilter/ip_queue.c	Mon Dec  3 22:54:20 2001
@@ -24,19 +24,28 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 #include <net/sock.h>
+#include <net/route.h>
 
 #include <linux/netfilter_ipv4/ip_queue.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
 
 #define IPQ_QMAX_DEFAULT 1024
 #define IPQ_PROC_FS_NAME "ip_queue"
 #define NET_IPQ_QMAX 2088
 #define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
 
+typedef struct ipq_rt_info {
+	__u8 tos;
+	__u32 daddr;
+	__u32 saddr;
+} ipq_rt_info_t;
+
 typedef struct ipq_queue_element {
 	struct list_head list;		/* Links element into queue */
 	int verdict;			/* Current verdict */
 	struct nf_info *info;		/* Extra info from netfilter */
 	struct sk_buff *skb;		/* Packet inside */
+	ipq_rt_info_t rt_info;		/* May need post-mangle routing */
 } ipq_queue_element_t;
 
 typedef int (*ipq_send_cb_t)(ipq_queue_element_t *e);
@@ -64,7 +73,6 @@
  * Packet queue
  *
  ****************************************************************************/
-
 /* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */
 static ipq_queue_element_t *
 ipq_dequeue(ipq_queue_t *q,
@@ -150,9 +158,19 @@
 		printk(KERN_ERR "ip_queue: OOM in enqueue\n");
 		return -ENOMEM;
 	}
+
 	e->verdict = NF_DROP;
 	e->info = info;
 	e->skb = skb;
+
+	if (e->info->hook == NF_IP_LOCAL_OUT) {
+		struct iphdr *iph = skb->nh.iph;
+
+		e->rt_info.tos = iph->tos;
+		e->rt_info.daddr = iph->daddr;
+		e->rt_info.saddr = iph->saddr;
+	}
+
 	spin_lock_bh(&q->lock);
 	if (q->len >= *q->maxlen) {
 		spin_unlock_bh(&q->lock);
@@ -198,6 +216,32 @@
 	kfree(q);
 }
 
+/* With a chainsaw... */
+static int route_me_harder(struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct rtable *rt;
+
+	struct rt_key key = {
+				dst:iph->daddr, src:iph->saddr,
+				oif:skb->sk ? skb->sk->bound_dev_if : 0,
+				tos:RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+				fwmark:skb->nfmark
+#endif
+			};
+
+	if (ip_route_output_key(&rt, &key) != 0) {
+		printk("route_me_harder: No more route.\n");
+		return -EINVAL;
+	}
+
+	/* Drop old route. */
+	dst_release(skb->dst);
+	skb->dst = &rt->u.dst;
+	return 0;
+}
+
 static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
 {
 	int diff;
@@ -223,6 +267,8 @@
 				      "in mangle, dropping packet\n");
 				return -ENOMEM;
 			}
+			if (e->skb->sk)
+				skb_set_owner_w(newskb, e->skb->sk);
 			kfree_skb(e->skb);
 			e->skb = newskb;
 		}
@@ -230,6 +276,19 @@
 	}
 	memcpy(e->skb->data, v->payload, v->data_len);
 	e->skb->nfcache |= NFC_ALTERED;
+
+	/*
+	 * Extra routing may needed on local out, as the QUEUE target never
+	 * returns control to the table.
+	 */
+	if (e->info->hook == NF_IP_LOCAL_OUT) {
+		struct iphdr *iph = e->skb->nh.iph;
+
+		if (!(iph->tos == e->rt_info.tos
+		      && iph->daddr == e->rt_info.daddr
+		      && iph->saddr == e->rt_info.saddr))
+			return route_me_harder(e->skb);
+	}
 	return 0;
 }
 
@@ -400,6 +459,13 @@
 	if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
 	else pm->outdev_name[0] = '\0';
 	pm->hw_protocol = e->skb->protocol;
+	if (e->info->indev && e->skb->dev) {
+		pm->hw_type = e->skb->dev->type;
+		if (e->skb->dev->hard_header_parse)
+			pm->hw_addrlen =
+				e->skb->dev->hard_header_parse(e->skb,
+				                               pm->hw_addr);
+	}
 	if (data_len)
 		memcpy(pm->payload, e->skb->data, data_len);
 	nlh->nlmsg_len = skb->tail - old_tail;
@@ -431,10 +497,15 @@
 	int status, type;
 	struct nlmsghdr *nlh;
 
+	if (skb->len < sizeof(struct nlmsghdr))
+		return;
+
 	nlh = (struct nlmsghdr *)skb->data;
-	if (nlh->nlmsg_len < sizeof(*nlh)
-	    || skb->len < nlh->nlmsg_len
-	    || nlh->nlmsg_pid <= 0
+	if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
+	    || skb->len < nlh->nlmsg_len)
+	    	return;
+
+	if(nlh->nlmsg_pid <= 0
 	    || !(nlh->nlmsg_flags & NLM_F_REQUEST)
 	    || nlh->nlmsg_flags & NLM_F_MULTI)
 		RCV_SKB_FAIL(-EINVAL);
diff -urN linux-2.4.7-pre3/net/ipv4/netfilter/ipt_unclean.c linux/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.7-pre3/net/ipv4/netfilter/ipt_unclean.c	Wed Jun 20 16:05:21 2001
+++ linux/net/ipv4/netfilter/ipt_unclean.c	Mon Dec  3 22:54:20 2001
@@ -268,6 +268,7 @@
 	  int embedded)
 {
 	u_int8_t *opt = (u_int8_t *)tcph;
+	u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
 	u_int8_t tcpflags;
 	int end_of_options = 0;
 	size_t i;
@@ -373,7 +374,7 @@
 				return 0;
 			}
 			/* CHECK: oversize options. */
-			else if (opt[i+1] + i >= tcph->doff * 4) {
+			else if (&opt[i] + opt[i+1] > endhdr) {
 				limpk("TCP option %u at %Zu too long\n",
 				      (unsigned int) opt[i], i);
 				return 0;
@@ -392,6 +393,7 @@
 check_ip(struct iphdr *iph, size_t length, int embedded)
 {
 	u_int8_t *opt = (u_int8_t *)iph;
+	u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
 	int end_of_options = 0;
 	void *protoh;
 	size_t datalen;
@@ -444,7 +446,7 @@
 				return 0;
 			}
 			/* CHECK: oversize options. */
-			else if (opt[i+1] + i > iph->ihl * 4) {
+			else if (&opt[i] + opt[i+1] > endhdr) {
 				limpk("IP option %u at %u too long\n",
 				      opt[i], i);
 				return 0;
diff -urN linux-2.4.7-pre3/net/ipv4/netfilter/iptable_mangle.c linux/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.4.7-pre3/net/ipv4/netfilter/iptable_mangle.c	Mon Jan 29 08:07:30 2001
+++ linux/net/ipv4/netfilter/iptable_mangle.c	Mon Dec  3 22:54:20 2001
@@ -148,7 +148,7 @@
 
 	ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
 	/* Reroute for ANY change. */
-	if (ret != NF_DROP && ret != NF_STOLEN
+	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
 	    && ((*pskb)->nh.iph->saddr != saddr
 		|| (*pskb)->nh.iph->daddr != daddr
 		|| (*pskb)->nfmark != nfmark
