[SCSI] Merge up to linux-2.6 head

Conflicts:

	drivers/scsi/jazz_esp.c

Same changes made by both SCSI and SPARC trees: problem with UTF-8
conversion in the copyright.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt
new file mode 100644
index 0000000..d403e46
--- /dev/null
+++ b/Documentation/scsi/scsi_fc_transport.txt
@@ -0,0 +1,450 @@
+                             SCSI FC Tansport
+                 =============================================
+
+Date:  4/12/2007
+Kernel Revisions for features:
+  rports : <<TBS>>
+  vports : 2.6.22 (? TBD)
+
+
+Introduction
+============
+This file documents the features and components of the SCSI FC Transport.
+It also provides documents the API between the transport and FC LLDDs.
+The FC transport can be found at:
+  drivers/scsi/scsi_transport_fc.c
+  include/scsi/scsi_transport_fc.h
+  include/scsi/scsi_netlink_fc.h
+
+This file is found at Documentation/scsi/scsi_fc_transport.txt
+
+
+FC Remote Ports (rports)
+========================================================================
+<< To Be Supplied >>
+
+
+FC Virtual Ports (vports)
+========================================================================
+
+Overview:
+-------------------------------
+
+  New FC standards have defined mechanisms which allows for a single physical
+  port to appear on as multiple communication ports. Using the N_Port Id
+  Virtualization (NPIV) mechanism, a point-to-point connection to a Fabric
+  can be assigned more than 1 N_Port_ID.  Each N_Port_ID appears as a
+  separate port to other endpoints on the fabric, even though it shares one
+  physical link to the switch for communication. Each N_Port_ID can have a
+  unique view of the fabric based on fabric zoning and array lun-masking
+  (just like a normal non-NPIV adapter).  Using the Virtual Fabric (VF)
+  mechanism, adding a fabric header to each frame allows the port to
+  interact with the Fabric Port to join multiple fabrics. The port will
+  obtain an N_Port_ID on each fabric it joins. Each fabric will have its
+  own unique view of endpoints and configuration parameters.  NPIV may be
+  used together with VF so that the port can obtain multiple N_Port_IDs
+  on each virtual fabric.
+
+  The FC transport is now recognizing a new object - a vport.  A vport is
+  an entity that has a world-wide unique World Wide Port Name (wwpn) and
+  World Wide Node Name (wwnn). The transport also allows for the FC4's to
+  be specified for the vport, with FCP_Initiator being the primary role
+  expected. Once instantiated by one of the above methods, it will have a
+  distinct N_Port_ID and view of fabric endpoints and storage entities.
+  The fc_host associated with the physical adapter will export the ability
+  to create vports. The transport will create the vport object within the
+  Linux device tree, and instruct the fc_host's driver to instantiate the
+  virtual port. Typically, the driver will create a new scsi_host instance
+  on the vport, resulting in a unique <H,C,T,L> namespace for the vport.
+  Thus, whether a FC port is based on a physical port or on a virtual port,
+  each will appear as a unique scsi_host with its own target and lun space.
+
+  Note: At this time, the transport is written to create only NPIV-based
+    vports. However, consideration was given to VF-based vports and it
+    should be a minor change to add support if needed.  The remaining
+    discussion will concentrate on NPIV.
+
+  Note: World Wide Name assignment (and uniqueness guarantees) are left
+    up to an administrative entity controling the vport. For example,
+    if vports are to be associated with virtual machines, a XEN mgmt
+    utility would be responsible for creating wwpn/wwnn's for the vport,
+    using it's own naming authority and OUI. (Note: it already does this
+    for virtual MAC addresses).
+
+
+Device Trees and Vport Objects:
+-------------------------------
+
+  Today, the device tree typically contains the scsi_host object,
+  with rports and scsi target objects underneath it. Currently the FC
+  transport creates the vport object and places it under the scsi_host
+  object corresponding to the physical adapter.  The LLDD will allocate
+  a new scsi_host for the vport and link it's object under the vport.
+  The remainder of the tree under the vports scsi_host is the same
+  as the non-NPIV case. The transport is written currently to easily
+  allow the parent of the vport to be something other than the scsi_host.
+  This could be used in the future to link the object onto a vm-specific
+  device tree. If the vport's parent is not the physical port's scsi_host,
+  a symbolic link to the vport object will be placed in the physical
+  port's scsi_host.
+
+  Here's what to expect in the device tree :
+   The typical Physical Port's Scsi_Host:
+     /sys/devices/.../host17/
+   and it has the typical decendent tree:
+     /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:
+   and then the vport is created on the Physical Port:
+     /sys/devices/.../host17/vport-17:0-0
+   and the vport's Scsi_Host is then created:
+     /sys/devices/.../host17/vport-17:0-0/host18
+   and then the rest of the tree progresses, such as:
+     /sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0:
+
+  Here's what to expect in the sysfs tree :
+   scsi_hosts:
+     /sys/class/scsi_host/host17                physical port's scsi_host
+     /sys/class/scsi_host/host18                vport's scsi_host
+   fc_hosts:
+     /sys/class/fc_host/host17                  physical port's fc_host
+     /sys/class/fc_host/host18                  vport's fc_host
+   fc_vports:
+     /sys/class/fc_vports/vport-17:0-0          the vport's fc_vport
+   fc_rports:
+     /sys/class/fc_remote_ports/rport-17:0-0    rport on the physical port
+     /sys/class/fc_remote_ports/rport-18:0-0    rport on the vport
+
+
+Vport Attributes:
+-------------------------------
+
+  The new fc_vport class object has the following attributes
+
+     node_name:                                                 Read_Only
+       The WWNN of the vport
+
+     port_name:                                                 Read_Only
+       The WWPN of the vport
+
+     roles:                                                     Read_Only
+       Indicates the FC4 roles enabled on the vport.
+
+     symbolic_name:                                             Read_Write
+       A string, appended to the driver's symbolic port name string, which
+       is registered with the switch to identify the vport. For example,
+       a hypervisor could set this string to "Xen Domain 2 VM 5 Vport 2",
+       and this set of identifiers can be seen on switch management screens
+       to identify the port.
+
+     vport_delete:                                              Write_Only
+       When written with a "1", will tear down the vport.
+
+     vport_disable:                                             Write_Only
+       When written with a "1", will transition the vport to a disabled.
+       state.  The vport will still be instantiated with the Linux kernel,
+       but it will not be active on the FC link.
+       When written with a "0", will enable the vport.
+
+     vport_last_state:                                          Read_Only
+       Indicates the previous state of the vport.  See the section below on
+       "Vport States".
+
+     vport_state:                                               Read_Only
+       Indicates the state of the vport.  See the section below on
+       "Vport States".
+
+     vport_type:                                                Read_Only
+       Reflects the FC mechanism used to create the virtual port.
+       Only NPIV is supported currently.
+
+
+  For the fc_host class object, the following attributes are added for vports:
+
+     max_npiv_vports:                                           Read_Only
+       Indicates the maximum number of NPIV-based vports that the
+       driver/adapter can support on the fc_host.
+
+     npiv_vports_inuse:                                         Read_Only
+       Indicates how many NPIV-based vports have been instantiated on the
+       fc_host.
+
+     vport_create:                                              Write_Only
+       A "simple" create interface to instantiate a vport on an fc_host.
+       A "<WWPN>:<WWNN>" string is written to the attribute. The transport
+       then instantiates the vport object and calls the LLDD to create the
+       vport with the role of FCP_Initiator.  Each WWN is specified as 16
+       hex characters and may *not* contain any prefixes (e.g. 0x, x, etc).
+
+     vport_delete:                                              Write_Only
+        A "simple" delete interface to teardown a vport. A "<WWPN>:<WWNN>"
+        string is written to the attribute. The transport will locate the
+        vport on the fc_host with the same WWNs and tear it down.  Each WWN
+        is specified as 16 hex characters and may *not* contain any prefixes
+        (e.g. 0x, x, etc).
+
+
+Vport States:
+-------------------------------
+
+  Vport instantiation consists of two parts:
+    - Creation with the kernel and LLDD. This means all transport and
+      driver data structures are built up, and device objects created.
+      This is equivalent to a driver "attach" on an adapter, which is
+      independent of the adapter's link state.
+    - Instantiation of the vport on the FC link via ELS traffic, etc.
+      This is equivalent to a "link up" and successfull link initialization.
+  Futher information can be found in the interfaces section below for
+  Vport Creation.
+
+  Once a vport has been instantiated with the kernel/LLDD, a vport state
+  can be reported via the sysfs attribute. The following states exist:
+
+    FC_VPORT_UNKNOWN            - Unknown
+      An temporary state, typically set only while the vport is being
+      instantiated with the kernel and LLDD.
+
+    FC_VPORT_ACTIVE             - Active
+      The vport has been successfully been created on the FC link.
+      It is fully functional.
+
+    FC_VPORT_DISABLED           - Disabled
+      The vport instantiated, but "disabled". The vport is not instantiated
+      on the FC link. This is equivalent to a physical port with the
+      link "down".
+
+    FC_VPORT_LINKDOWN           - Linkdown
+      The vport is not operational as the physical link is not operational.
+
+    FC_VPORT_INITIALIZING       - Initializing
+      The vport is in the process of instantiating on the FC link.
+      The LLDD will set this state just prior to starting the ELS traffic
+      to create the vport. This state will persist until the vport is
+      successfully created (state becomes FC_VPORT_ACTIVE) or it fails
+      (state is one of the values below).  As this state is transitory,
+      it will not be preserved in the "vport_last_state".
+
+    FC_VPORT_NO_FABRIC_SUPP     - No Fabric Support
+      The vport is not operational. One of the following conditions were
+      encountered:
+       - The FC topology is not Point-to-Point
+       - The FC port is not connected to an F_Port
+       - The F_Port has indicated that NPIV is not supported.
+
+    FC_VPORT_NO_FABRIC_RSCS     - No Fabric Resources
+      The vport is not operational. The Fabric failed FDISC with a status
+      indicating that it does not have sufficient resources to complete
+      the operation.
+
+    FC_VPORT_FABRIC_LOGOUT      - Fabric Logout
+      The vport is not operational. The Fabric has LOGO'd the N_Port_ID
+      associated with the vport.
+
+    FC_VPORT_FABRIC_REJ_WWN     - Fabric Rejected WWN
+      The vport is not operational. The Fabric failed FDISC with a status
+      indicating that the WWN's are not valid.
+
+    FC_VPORT_FAILED             - VPort Failed
+      The vport is not operational. This is a catchall for all other
+      error conditions.
+
+
+  The following state table indicates the different state transitions:
+
+    State              Event                            New State
+    --------------------------------------------------------------------
+     n/a                Initialization                  Unknown
+    Unknown:            Link Down                       Linkdown
+                        Link Up & Loop                  No Fabric Support
+                        Link Up & no Fabric             No Fabric Support
+                        Link Up & FLOGI response        No Fabric Support
+                          indicates no NPIV support
+                        Link Up & FDISC being sent      Initializing
+                        Disable request                 Disable
+    Linkdown:           Link Up                         Unknown
+    Initializing:       FDISC ACC                       Active
+                        FDISC LS_RJT w/ no resources    No Fabric Resources
+                        FDISC LS_RJT w/ invalid         Fabric Rejected WWN
+                          pname or invalid nport_id
+                        FDISC LS_RJT failed for         Vport Failed
+                          other reasons
+                        Link Down                       Linkdown
+                        Disable request                 Disable
+    Disable:            Enable request                  Unknown
+    Active:             LOGO received from fabric       Fabric Logout
+                        Link Down                       Linkdown
+                        Disable request                 Disable
+    Fabric Logout:      Link still up                   Unknown
+
+         The following 4 error states all have the same transitions:
+    No Fabric Support:
+    No Fabric Resources:
+    Fabric Rejected WWN:
+    Vport Failed:
+                        Disable request                 Disable
+                        Link goes down                  Linkdown
+
+
+Transport <-> LLDD Interfaces :
+-------------------------------
+
+Vport support by LLDD:
+
+  The LLDD indicates support for vports by supplying a vport_create()
+  function in the transport template.  The presense of this function will
+  cause the creation of the new attributes on the fc_host.  As part of
+  the physical port completing its initialization relative to the
+  transport, it should set the max_npiv_vports attribute to indicate the
+  maximum number of vports the driver and/or adapter supports.
+
+
+Vport Creation:
+
+  The LLDD vport_create() syntax is:
+
+      int vport_create(struct fc_vport *vport, bool disable)
+
+    where:
+      vport:    Is the newly allocated vport object
+      disable:  If "true", the vport is to be created in a disabled stated.
+                If "false", the vport is to be enabled upon creation.
+
+  When a request is made to create a new vport (via sgio/netlink, or the
+  vport_create fc_host attribute), the transport will validate that the LLDD
+  can support another vport (e.g. max_npiv_vports > npiv_vports_inuse).
+  If not, the create request will be failed.  If space remains, the transport
+  will increment the vport count, create the vport object, and then call the
+  LLDD's vport_create() function with the newly allocated vport object.
+
+  As mentioned above, vport creation is divided into two parts:
+    - Creation with the kernel and LLDD. This means all transport and
+      driver data structures are built up, and device objects created.
+      This is equivalent to a driver "attach" on an adapter, which is
+      independent of the adapter's link state.
+    - Instantiation of the vport on the FC link via ELS traffic, etc.
+      This is equivalent to a "link up" and successfull link initialization.
+
+  The LLDD's vport_create() function will not synchronously wait for both
+  parts to be fully completed before returning. It must validate that the
+  infrastructure exists to support NPIV, and complete the first part of
+  vport creation (data structure build up) before returning.  We do not
+  hinge vport_create() on the link-side operation mainly because:
+    - The link may be down. It is not a failure if it is. It simply
+      means the vport is in an inoperable state until the link comes up.
+      This is consistent with the link bouncing post vport creation.
+    - The vport may be created in a disabled state.
+    - This is consistent with a model where:  the vport equates to a
+      FC adapter. The vport_create is synonymous with driver attachment
+      to the adapter, which is independent of link state.
+
+    Note: special error codes have been defined to delineate infrastructure
+      failure cases for quicker resolution.
+
+  The expected behavior for the LLDD's vport_create() function is:
+    - Validate Infrastructure:
+        - If the driver or adapter cannot support another vport, whether
+            due to improper firmware, (a lie about) max_npiv, or a lack of
+            some other resource - return VPCERR_UNSUPPORTED.
+        - If the driver validates the WWN's against those already active on
+            the adapter and detects an overlap - return VPCERR_BAD_WWN.
+        - If the driver detects the topology is loop, non-fabric, or the
+            FLOGI did not support NPIV - return VPCERR_NO_FABRIC_SUPP.
+    - Allocate data structures. If errors are encountered, such as out
+        of memory conditions, return the respective negative Exxx error code.
+    - If the role is FCP Initiator, the LLDD is to :
+        - Call scsi_host_alloc() to allocate a scsi_host for the vport.
+        - Call scsi_add_host(new_shost, &vport->dev) to start the scsi_host
+          and bind it as a child of the vport device.
+        - Initializes the fc_host attribute values.
+    - Kick of further vport state transitions based on the disable flag and
+        link state - and return success (zero).
+
+  LLDD Implementers Notes:
+  - It is suggested that there be a different fc_function_templates for
+    the physical port and the virtual port.  The physical port's template
+    would have the vport_create, vport_delete, and vport_disable functions,
+    while the vports would not.
+  - It is suggested that there be different scsi_host_templates
+    for the physical port and virtual port. Likely, there are driver
+    attributes, embedded into the scsi_host_template, that are applicable
+    for the physical port only (link speed, topology setting, etc). This
+    ensures that the attributes are applicable to the respective scsi_host.
+
+
+Vport Disable/Enable:
+
+  The LLDD vport_disable() syntax is:
+
+      int vport_disable(struct fc_vport *vport, bool disable)
+
+    where:
+      vport:    Is vport to to be enabled or disabled
+      disable:  If "true", the vport is to be disabled.
+                If "false", the vport is to be enabled.
+
+  When a request is made to change the disabled state on a vport, the
+  transport will validate the request against the existing vport state.
+  If the request is to disable and the vport is already disabled, the
+  request will fail. Similarly, if the request is to enable, and the
+  vport is not in a disabled state, the request will fail.  If the request
+  is valid for the vport state, the transport will call the LLDD to
+  change the vport's state.
+
+  Within the LLDD, if a vport is disabled, it remains instantiated with
+  the kernel and LLDD, but it is not active or visible on the FC link in
+  any way. (see Vport Creation and the 2 part instantiation discussion).
+  The vport will remain in this state until it is deleted or re-enabled.
+  When enabling a vport, the LLDD reinstantiates the vport on the FC
+  link - essentially restarting the LLDD statemachine (see Vport States
+  above).
+
+
+Vport Deletion:
+
+  The LLDD vport_delete() syntax is:
+
+      int vport_delete(struct fc_vport *vport)
+
+    where:
+      vport:    Is vport to delete
+
+  When a request is made to delete a vport (via sgio/netlink, or via the
+  fc_host or fc_vport vport_delete attributes), the transport will call
+  the LLDD to terminate the vport on the FC link, and teardown all other
+  datastructures and references.  If the LLDD completes successfully,
+  the transport will teardown the vport objects and complete the vport
+  removal.  If the LLDD delete request fails, the vport object will remain,
+  but will be in an indeterminate state.
+
+  Within the LLDD, the normal code paths for a scsi_host teardown should
+  be followed. E.g. If the vport has a FCP Initiator role, the LLDD
+  will call fc_remove_host() for the vports scsi_host, followed by
+  scsi_remove_host() and scsi_host_put() for the vports scsi_host.
+
+
+Other:
+  fc_host port_type attribute:
+    There is a new fc_host port_type value - FC_PORTTYPE_NPIV. This value
+    must be set on all vport-based fc_hosts.  Normally, on a physical port,
+    the port_type attribute would be set to NPORT, NLPORT, etc based on the
+    topology type and existence of the fabric. As this is not applicable to
+    a vport, it makes more sense to report the FC mechanism used to create
+    the vport.
+
+  Driver unload:
+    FC drivers are required to call fc_remove_host() prior to calling
+    scsi_remove_host().  This allows the fc_host to tear down all remote
+    ports prior the scsi_host being torn down.  The fc_remove_host() call
+    was updated to remove all vports for the fc_host as well.
+
+
+Credits
+=======
+The following people have contributed to this document:
+
+
+
+
+
+
+James Smart
+james.smart@emulex.com
+
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 90961a8..4aca7dd 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -555,7 +555,6 @@
 {
 	struct scsi_cmnd *cmd;
 	ctlr_info_t *ctlr;
-	u64bit addr64;
 	ErrorInfo_struct *ei;
 
 	ei = cp->err_info;
@@ -569,20 +568,7 @@
 	cmd = (struct scsi_cmnd *) cp->scsi_cmd;	
 	ctlr = hba[cp->ctlr];
 
-	/* undo the DMA mappings */
-
-	if (cmd->use_sg) {
-		pci_unmap_sg(ctlr->pdev,
-			cmd->request_buffer, cmd->use_sg,
-				cmd->sc_data_direction); 
-	}
-	else if (cmd->request_bufflen) {
-		addr64.val32.lower = cp->SG[0].Addr.lower;
-                addr64.val32.upper = cp->SG[0].Addr.upper;
-                pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val,
-                	cmd->request_bufflen, 
-				cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(cmd);
 
 	cmd->result = (DID_OK << 16); 		/* host byte */
 	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
@@ -597,7 +583,7 @@
 		ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
 			SCSI_SENSE_BUFFERSIZE : 
 			ei->SenseLen);
-	cmd->resid = ei->ResidualCnt;
+	scsi_set_resid(cmd, ei->ResidualCnt);
 
 	if(ei->CommandStatus != 0) 
 	{ /* an error has occurred */ 
@@ -1204,46 +1190,29 @@
 		CommandList_struct *cp,	
 		struct scsi_cmnd *cmd)
 {
-	unsigned int use_sg, nsegs=0, len;
-	struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer;
+	unsigned int len;
+	struct scatterlist *sg;
 	__u64 addr64;
+	int use_sg, i;
 
-	/* is it just one virtual address? */	
-	if (!cmd->use_sg) {
-		if (cmd->request_bufflen) {	/* anything to xfer? */
+	BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
 
-			addr64 = (__u64) pci_map_single(pdev, 
-				cmd->request_buffer, 
-				cmd->request_bufflen, 
-				cmd->sc_data_direction); 
-	
-			cp->SG[0].Addr.lower = 
-			  (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[0].Addr.upper =
-			  (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[0].Len = cmd->request_bufflen;
-			nsegs=1;
+	use_sg = scsi_dma_map(cmd);
+	if (use_sg) {	/* not too many addrs? */
+		scsi_for_each_sg(cmd, sg, use_sg, i) {
+			addr64 = (__u64) sg_dma_address(sg);
+			len  = sg_dma_len(sg);
+			cp->SG[i].Addr.lower =
+				(__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+			cp->SG[i].Addr.upper =
+				(__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+			cp->SG[i].Len = len;
+			cp->SG[i].Ext = 0;  // we are not chaining
 		}
-	} /* else, must be a list of virtual addresses.... */
-	else if (cmd->use_sg <= MAXSGENTRIES) {	/* not too many addrs? */
+	}
 
-		use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg,
-			cmd->sc_data_direction);
-
-		for (nsegs=0; nsegs < use_sg; nsegs++) {
-			addr64 = (__u64) sg_dma_address(&scatter[nsegs]);
-			len  = sg_dma_len(&scatter[nsegs]);
-			cp->SG[nsegs].Addr.lower =
-			  (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[nsegs].Addr.upper =
-			  (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
-			cp->SG[nsegs].Len = len;
-			cp->SG[nsegs].Ext = 0;  // we are not chaining
-		}
-	} else BUG();
-
-	cp->Header.SGList = (__u8) nsegs;   /* no. SGs contig in this cmd */
-	cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */
+	cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
+	cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
 	return;
 }
 
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 875eadd..ce86ff2 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -1489,69 +1489,6 @@
 	}
 }
 
-static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
-					struct sbp2_fwhost_info *hi,
-					struct sbp2_command_info *cmd,
-					struct scatterlist *sgpnt,
-					u32 orb_direction,
-					unsigned int scsi_request_bufflen,
-					void *scsi_request_buffer,
-					enum dma_data_direction dma_dir)
-{
-	cmd->dma_dir = dma_dir;
-	cmd->dma_size = scsi_request_bufflen;
-	cmd->dma_type = CMD_DMA_SINGLE;
-	cmd->cmd_dma = dma_map_single(hi->host->device.parent,
-				      scsi_request_buffer,
-				      cmd->dma_size, cmd->dma_dir);
-	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-	orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-	/* handle case where we get a command w/o s/g enabled
-	 * (but check for transfers larger than 64K) */
-	if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-		orb->data_descriptor_lo = cmd->cmd_dma;
-		orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-
-	} else {
-		/* The buffer is too large. Turn this into page tables. */
-
-		struct sbp2_unrestricted_page_table *sg_element =
-						&cmd->scatter_gather_element[0];
-		u32 sg_count, sg_len;
-		dma_addr_t sg_addr;
-
-		orb->data_descriptor_lo = cmd->sge_dma;
-		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-
-		/* fill out our SBP-2 page tables; split up the large buffer */
-		sg_count = 0;
-		sg_len = scsi_request_bufflen;
-		sg_addr = cmd->cmd_dma;
-		while (sg_len) {
-			sg_element[sg_count].segment_base_lo = sg_addr;
-			if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-				sg_element[sg_count].length_segment_base_hi =
-					PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-				sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-				sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-			} else {
-				sg_element[sg_count].length_segment_base_hi =
-					PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-				sg_len = 0;
-			}
-			sg_count++;
-		}
-
-		orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-		sbp2util_cpu_to_be32_buffer(sg_element,
-				(sizeof(struct sbp2_unrestricted_page_table)) *
-				sg_count);
-	}
-}
-
 static void sbp2_create_command_orb(struct sbp2_lu *lu,
 				    struct sbp2_command_info *cmd,
 				    unchar *scsi_cmd,
@@ -1595,13 +1532,9 @@
 		orb->data_descriptor_hi = 0x0;
 		orb->data_descriptor_lo = 0x0;
 		orb->misc |= ORB_SET_DIRECTION(1);
-	} else if (scsi_use_sg)
+	} else
 		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
 					 orb_direction, dma_dir);
-	else
-		sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
-					    scsi_request_bufflen,
-					    scsi_request_buffer, dma_dir);
 
 	sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
@@ -1690,15 +1623,15 @@
 			     void (*done)(struct scsi_cmnd *))
 {
 	unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
-	unsigned int request_bufflen = SCpnt->request_bufflen;
+	unsigned int request_bufflen = scsi_bufflen(SCpnt);
 	struct sbp2_command_info *cmd;
 
 	cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
 	if (!cmd)
 		return -EIO;
 
-	sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
-				request_bufflen, SCpnt->request_buffer,
+	sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+				request_bufflen, scsi_sglist(SCpnt),
 				SCpnt->sc_data_direction);
 	sbp2_link_orb_command(lu, cmd);
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3bd94f1..bc740a6 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -260,30 +260,13 @@
 	/* Map the data portion, if any.
 	 * sges_left  = 0 if no data transfer.
 	 */
-	if ( (sges_left = SCpnt->use_sg) ) {
-		sges_left = pci_map_sg(ioc->pcidev,
-			       (struct scatterlist *) SCpnt->request_buffer,
- 			       SCpnt->use_sg,
-			       SCpnt->sc_data_direction);
-		if (sges_left == 0)
-			return FAILED;
-	} else if (SCpnt->request_bufflen) {
-		SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
-				      SCpnt->request_buffer,
-				      SCpnt->request_bufflen,
-				      SCpnt->sc_data_direction);
-		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
-				ioc->name, SCpnt, SCpnt->request_bufflen));
-		mptscsih_add_sge((char *) &pReq->SGL,
-			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
-			SCpnt->SCp.dma_handle);
-
-		return SUCCESS;
-	}
+	sges_left = scsi_dma_map(SCpnt);
+	if (sges_left < 0)
+		return FAILED;
 
 	/* Handle the SG case.
 	 */
-	sg = (struct scatterlist *) SCpnt->request_buffer;
+	sg = scsi_sglist(SCpnt);
 	sg_done  = 0;
 	sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
 	chainSge = NULL;
@@ -662,7 +645,7 @@
 		scsi_state = pScsiReply->SCSIState;
 		scsi_status = pScsiReply->SCSIStatus;
 		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
-		sc->resid = sc->request_bufflen - xfer_cnt;
+		scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
 		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
 
 		/*
@@ -767,7 +750,7 @@
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
-			sc->resid = sc->request_bufflen - xfer_cnt;
+			scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
 			if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
 				sc->result=DID_SOFT_ERROR << 16;
 			else /* Sufficient data transfer occurred */
@@ -816,7 +799,7 @@
 			break;
 
 		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
-			sc->resid=0;
+			scsi_set_resid(sc, 0);
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
 			sc->result = (DID_OK << 16) | scsi_status;
@@ -899,23 +882,18 @@
 			    scsi_state, scsi_status, log_info));
 
 			dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
-			    "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
-			    sc->device->host->host_no, sc->device->channel, sc->device->id,
-			    sc->device->lun, sc->resid, sc->request_bufflen,
-			    xfer_cnt));
+				      "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+				      sc->device->host->host_no,
+				      sc->device->channel, sc->device->id,
+				      sc->device->lun, scsi_get_resid(sc),
+				      scsi_bufflen(sc), xfer_cnt));
 		}
 #endif
 
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
-	if (sc->use_sg) {
-		pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
-			    sc->use_sg, sc->sc_data_direction);
-	} else if (sc->request_bufflen) {
-		pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
-				sc->request_bufflen, sc->sc_data_direction);
-	}
+	scsi_dma_unmap(sc);
 
 	sc->scsi_done(sc);		/* Issue the command callback */
 
@@ -970,17 +948,8 @@
 			/* Set status, free OS resources (SG DMA buffers)
 			 * Do OS callback
 			 */
-			if (SCpnt->use_sg) {
-				pci_unmap_sg(ioc->pcidev,
-					(struct scatterlist *) SCpnt->request_buffer,
-					SCpnt->use_sg,
-					SCpnt->sc_data_direction);
-			} else if (SCpnt->request_bufflen) {
-				pci_unmap_single(ioc->pcidev,
-					SCpnt->SCp.dma_handle,
-					SCpnt->request_bufflen,
-					SCpnt->sc_data_direction);
-			}
+			scsi_dma_unmap(SCpnt);
+
 			SCpnt->result = DID_RESET << 16;
 			SCpnt->host_scribble = NULL;
 
@@ -1039,17 +1008,8 @@
 			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
 			if ((unsigned char *)mf != sc->host_scribble)
 				continue;
-			if (sc->use_sg) {
-				pci_unmap_sg(hd->ioc->pcidev,
-				(struct scatterlist *) sc->request_buffer,
-					sc->use_sg,
-					sc->sc_data_direction);
-			} else if (sc->request_bufflen) {
-				pci_unmap_single(hd->ioc->pcidev,
-					sc->SCp.dma_handle,
-					sc->request_bufflen,
-					sc->sc_data_direction);
-			}
+			scsi_dma_unmap(sc);
+
 			sc->host_scribble = NULL;
 			sc->result = DID_NO_CONNECT << 16;
 			sc->scsi_done(sc);
@@ -1380,10 +1340,10 @@
 	 *    will be no data transfer!  GRRRRR...
 	 */
 	if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
-		datalen = SCpnt->request_bufflen;
+		datalen = scsi_bufflen(SCpnt);
 		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */
 	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
-		datalen = SCpnt->request_bufflen;
+		datalen = scsi_bufflen(SCpnt);
 		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */
 	} else {
 		datalen = 0;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index eb766c3..113aaed 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1306,22 +1306,26 @@
 					wake_up(&tw_dev->ioctl_wqueue);
 				}
 			} else {
+				struct scsi_cmnd *cmd;
+
+				cmd = tw_dev->srb[request_id];
+
 				twa_scsiop_execute_scsi_complete(tw_dev, request_id);
 				/* If no error command was a success */
 				if (error == 0) {
-					tw_dev->srb[request_id]->result = (DID_OK << 16);
+					cmd->result = (DID_OK << 16);
 				}
 
 				/* If error, command failed */
 				if (error == 1) {
 					/* Ask for a host reset */
-					tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+					cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
 				}
 
 				/* Report residual bytes for single sgl */
-				if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
-					if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
-						tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
+				if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+					if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
+						scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
 				}
 
 				/* Now complete the io */
@@ -1384,53 +1388,21 @@
 {
 	int use_sg;
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
-	int retval = 0;
 
-	if (cmd->use_sg == 0)
-		goto out;
-
-	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-
-	if (use_sg == 0) {
+	use_sg = scsi_dma_map(cmd);
+	if (!use_sg)
+		return 0;
+	else if (use_sg < 0) {
 		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-		goto out;
+		return 0;
 	}
 
 	cmd->SCp.phase = TW_PHASE_SGLIST;
 	cmd->SCp.have_data_in = use_sg;
-	retval = use_sg;
-out:
-	return retval;
+
+	return use_sg;
 } /* End twa_map_scsi_sg_data() */
 
-/* This function will perform a pci-dma map for a single buffer */
-static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id)
-{
-	dma_addr_t mapping;
-	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
-	dma_addr_t retval = 0;
-
-	if (cmd->request_bufflen == 0) {
-		retval = 0;
-		goto out;
-	}
-
-	mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-
-	if (mapping == 0) {
-		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page");
-		goto out;
-	}
-
-	cmd->SCp.phase = TW_PHASE_SINGLE;
-	cmd->SCp.have_data_in = mapping;
-	retval = mapping;
-out:
-	return retval;
-} /* End twa_map_scsi_single_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1815,15 +1787,13 @@
 	u32 num_sectors = 0x0;
 	int i, sg_count;
 	struct scsi_cmnd *srb = NULL;
-	struct scatterlist *sglist = NULL;
-	dma_addr_t buffaddr = 0x0;
+	struct scatterlist *sglist = NULL, *sg;
 	int retval = 1;
 
 	if (tw_dev->srb[request_id]) {
-		if (tw_dev->srb[request_id]->request_buffer) {
-			sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-		}
 		srb = tw_dev->srb[request_id];
+		if (scsi_sglist(srb))
+			sglist = scsi_sglist(srb);
 	}
 
 	/* Initialize command packet */
@@ -1856,32 +1826,12 @@
 
 	if (!sglistarg) {
 		/* Map sglist from scsi layer to cmd packet */
-		if (tw_dev->srb[request_id]->use_sg == 0) {
-			if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
-				command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
-				command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
-				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
-					memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
-			} else {
-				buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
-				if (buffaddr == 0)
-					goto out;
 
-				command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
-				command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
-			}
-			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
-
-			if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
-				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
-				goto out;
-			}
-		}
-
-		if (tw_dev->srb[request_id]->use_sg > 0) {
-			if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
-				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
-					struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+		if (scsi_sg_count(srb)) {
+			if ((scsi_sg_count(srb) == 1) &&
+			    (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+				if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+					struct scatterlist *sg = scsi_sglist(srb);
 					char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 					memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
 					kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -1893,16 +1843,16 @@
 				if (sg_count == 0)
 					goto out;
 
-				for (i = 0; i < sg_count; i++) {
-					command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
-					command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
+				scsi_for_each_sg(srb, sg, sg_count, i) {
+					command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
+					command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
 					if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
 						TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
 						goto out;
 					}
 				}
 			}
-			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
+			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
 		}
 	} else {
 		/* Internal cdb post */
@@ -1932,7 +1882,7 @@
 
 	/* Update SG statistics */
 	if (srb) {
-		tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+		tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
 		if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
 			tw_dev->max_sgl_entries = tw_dev->sgl_entries;
 	}
@@ -1951,16 +1901,19 @@
 /* This function completes an execute scsi operation */
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
 {
-	if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
-	    (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
-	     tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
-		if (tw_dev->srb[request_id]->use_sg == 0) {
-			memcpy(tw_dev->srb[request_id]->request_buffer,
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+	int use_sg = scsi_sg_count(cmd);
+
+	if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+	    (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+	     cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
+		if (!use_sg)
+			memcpy(scsi_sglist(cmd),
 			       tw_dev->generic_buffer_virt[request_id],
-			       tw_dev->srb[request_id]->request_bufflen);
-		}
-		if (tw_dev->srb[request_id]->use_sg == 1) {
-			struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+			       scsi_bufflen(cmd));
+
+		if (use_sg == 1) {
+			struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
 			char *buf;
 			unsigned long flags = 0;
 			local_irq_save(flags);
@@ -2017,16 +1970,8 @@
 static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
 {
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-	struct pci_dev *pdev = tw_dev->tw_pci_dev;
 
-	switch(cmd->SCp.phase) {
-	case TW_PHASE_SINGLE:
-		pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-		break;
-	case TW_PHASE_SGLIST:
-		pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-		break;
-	}
+	scsi_dma_unmap(cmd);
 } /* End twa_unmap_scsi_data() */
 
 /* scsi_host_template initializer */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 656bdb1..c7995fc 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1273,57 +1273,24 @@
 	int use_sg;
 
 	dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-	
-	if (cmd->use_sg == 0)
-		return 0;
 
-	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-	
-	if (use_sg == 0) {
+	use_sg = scsi_dma_map(cmd);
+	if (use_sg < 0) {
 		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
 		return 0;
 	}
 
 	cmd->SCp.phase = TW_PHASE_SGLIST;
 	cmd->SCp.have_data_in = use_sg;
-	
+
 	return use_sg;
 } /* End tw_map_scsi_sg_data() */
 
-static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	dma_addr_t mapping;
-
-	dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
-
-	if (cmd->request_bufflen == 0)
-		return 0;
-
-	mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
-
-	if (mapping == 0) {
-		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
-		return 0;
-	}
-
-	cmd->SCp.phase = TW_PHASE_SINGLE;
-	cmd->SCp.have_data_in = mapping;
-
-	return mapping;
-} /* End tw_map_scsi_single_data() */
-
 static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
 {
 	dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
 
-	switch(cmd->SCp.phase) {
-		case TW_PHASE_SINGLE:
-			pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
-			break;
-		case TW_PHASE_SGLIST:
-			pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
-			break;
-	}
+	scsi_dma_unmap(cmd);
 } /* End tw_unmap_scsi_data() */
 
 /* This function will reset a device extension */
@@ -1499,27 +1466,16 @@
 	void *buf;
 	unsigned int transfer_len;
 	unsigned long flags = 0;
+	struct scatterlist *sg = scsi_sglist(cmd);
 
-	if (cmd->use_sg) {
-		struct scatterlist *sg =
-			(struct scatterlist *)cmd->request_buffer;
-		local_irq_save(flags);
-		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		transfer_len = min(sg->length, len);
-	} else {
-		buf = cmd->request_buffer;
-		transfer_len = min(cmd->request_bufflen, len);
-	}
+	local_irq_save(flags);
+	buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+	transfer_len = min(sg->length, len);
 
 	memcpy(buf, data, transfer_len);
-	
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
 
-		sg = (struct scatterlist *)cmd->request_buffer;
-		kunmap_atomic(buf - sg->offset, KM_IRQ0);
-		local_irq_restore(flags);
-	}
+	kunmap_atomic(buf - sg->offset, KM_IRQ0);
+	local_irq_restore(flags);
 }
 
 /* This function is called by the isr to complete an inquiry command */
@@ -1764,19 +1720,20 @@
 {
 	TW_Command *command_packet;
 	unsigned long command_que_value;
-	u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
+	u32 lba = 0x0, num_sectors = 0x0;
 	int i, use_sg;
 	struct scsi_cmnd *srb;
-	struct scatterlist *sglist;
+	struct scatterlist *sglist, *sg;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
 
-	if (tw_dev->srb[request_id]->request_buffer == NULL) {
+	srb = tw_dev->srb[request_id];
+
+	sglist = scsi_sglist(srb);
+	if (!sglist) {
 		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
 		return 1;
 	}
-	sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-	srb = tw_dev->srb[request_id];
 
 	/* Initialize command packet */
 	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
@@ -1819,33 +1776,18 @@
 	command_packet->byte8.io.lba = lba;
 	command_packet->byte6.block_count = num_sectors;
 
-	/* Do this if there are no sg list entries */
-	if (tw_dev->srb[request_id]->use_sg == 0) {    
-		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
-		buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-		if (buffaddr == 0)
-			return 1;
+	use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
+	if (!use_sg)
+		return 1;
 
-		command_packet->byte8.io.sgl[0].address = buffaddr;
-		command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+	scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
+		command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
+		command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
 		command_packet->size+=2;
 	}
 
-	/* Do this if we have multiple sg list entries */
-	if (tw_dev->srb[request_id]->use_sg > 0) {
-		use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-		if (use_sg == 0)
-			return 1;
-
-		for (i=0;i<use_sg; i++) {
-			command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
-			command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
-			command_packet->size+=2;
-		}
-	}
-
 	/* Update SG statistics */
-	tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+	tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
 	if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
 		tw_dev->max_sgl_entries = tw_dev->sgl_entries;
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index cb02656..405d9d6 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -585,16 +585,8 @@
 	      struct NCR_700_command_slot *slot)
 {
 	if(SCp->sc_data_direction != DMA_NONE &&
-	   SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
-		if(SCp->use_sg) {
-			dma_unmap_sg(hostdata->dev, SCp->request_buffer,
-				     SCp->use_sg, SCp->sc_data_direction);
-		} else {
-			dma_unmap_single(hostdata->dev, slot->dma_handle,
-					 SCp->request_bufflen,
-					 SCp->sc_data_direction);
-		}
-	}
+	   SCp->sc_data_direction != DMA_BIDIRECTIONAL)
+		scsi_dma_unmap(SCp);
 }
 
 STATIC inline void
@@ -1263,14 +1255,13 @@
 		       host->host_no, pun, lun, NCR_700_condition[i],
 		       NCR_700_phase[j], dsp - hostdata->pScript);
 		if(SCp != NULL) {
-			scsi_print_command(SCp);
+			struct scatterlist *sg;
 
-			if(SCp->use_sg) {
-				for(i = 0; i < SCp->use_sg + 1; i++) {
-					printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
-				}
+			scsi_print_command(SCp);
+			scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) {
+				printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
 			}
-		}	       
+		}
 		NCR_700_internal_bus_reset(host);
 	} else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) {
 		printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %08x[%04x], continuing\n",
@@ -1844,8 +1835,8 @@
 	}
 	/* sanity check: some of the commands generated by the mid-layer
 	 * have an eccentric idea of their sc_data_direction */
-	if(!SCp->use_sg && !SCp->request_bufflen 
-	   && SCp->sc_data_direction != DMA_NONE) {
+	if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) &&
+	   SCp->sc_data_direction != DMA_NONE) {
 #ifdef NCR_700_DEBUG
 		printk("53c700: Command");
 		scsi_print_command(SCp);
@@ -1887,31 +1878,15 @@
 		int i;
 		int sg_count;
 		dma_addr_t vPtr = 0;
+		struct scatterlist *sg;
 		__u32 count = 0;
 
-		if(SCp->use_sg) {
-			sg_count = dma_map_sg(hostdata->dev,
-					      SCp->request_buffer, SCp->use_sg,
-					      direction);
-		} else {
-			vPtr = dma_map_single(hostdata->dev,
-					      SCp->request_buffer, 
-					      SCp->request_bufflen,
-					      direction);
-			count = SCp->request_bufflen;
-			slot->dma_handle = vPtr;
-			sg_count = 1;
-		}
-			
+		sg_count = scsi_dma_map(SCp);
+		BUG_ON(sg_count < 0);
 
-		for(i = 0; i < sg_count; i++) {
-
-			if(SCp->use_sg) {
-				struct scatterlist *sg = SCp->request_buffer;
-
-				vPtr = sg_dma_address(&sg[i]);
-				count = sg_dma_len(&sg[i]);
-			}
+		scsi_for_each_sg(SCp, sg, sg_count, i) {
+			vPtr = sg_dma_address(sg);
+			count = sg_dma_len(sg);
 
 			slot->SG[i].ins = bS_to_host(move_ins | count);
 			DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n",
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
deleted file mode 100644
index 93b41f4..0000000
--- a/drivers/scsi/53c7xx.c
+++ /dev/null
@@ -1,6102 +0,0 @@
-/*
- * 53c710 driver.  Modified from Drew Eckhardts driver
- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
- * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the
- * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]).
- * There are also currently some defines at the top of 53c7xx.scr.
- * The chip type is #defined in script_asm.pl, as well as the Makefile.
- * Host scsi ID expected to be 7 - see NCR53c7x0_init().
- *
- * I have removed the PCI code and some of the 53c8xx specific code - 
- * simply to make this file smaller and easier to manage.
- *
- * MVME16x issues:
- *   Problems trying to read any chip registers in NCR53c7x0_init(), as they
- *   may never have been set by 16xBug (eg. If kernel has come in over tftp).
- */
-
-/*
- * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and
- * WarpEngine SCSI controllers.
- * By Alan Hourihane <alanh@fairlite.demon.co.uk>
- * Thanks to Richard Hirst for making it possible with the MVME additions
- */
-
-/*
- * 53c710 rev 0 doesn't support add with carry.  Rev 1 and 2 does.  To
- * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures
- * that the DSA address is always xxxxxx00.  If disconnection is not allowed,
- * then the script only ever tries to add small (< 256) positive offsets to
- * DSA, so lack of carry isn't a problem.  FORCE_DSA_ALIGNMENT can, of course,
- * be defined for all chip revisions at a small cost in memory usage.
- */
-
-#define FORCE_DSA_ALIGNMENT
-
-/*
- * Selection timer does not always work on the 53c710, depending on the
- * timing at the last disconnect, if this is a problem for you, try
- * using validids as detailed below.
- *
- * Options for the NCR7xx driver
- *
- * noasync:0		-	disables sync and asynchronous negotiation
- * nosync:0		-	disables synchronous negotiation (does async)
- * nodisconnect:0	-	disables disconnection
- * validids:0x??	-	Bitmask field that disallows certain ID's.
- *			-	e.g.	0x03	allows ID 0,1
- *			-		0x1F	allows ID 0,1,2,3,4
- * opthi:n		-	replace top word of options with 'n'
- * optlo:n		-	replace bottom word of options with 'n'
- *			-	ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<<
- */
-
-/*
- * PERM_OPTIONS are driver options which will be enabled for all NCR boards
- * in the system at driver initialization time.
- *
- * Don't THINK about touching these in PERM_OPTIONS : 
- *   OPTION_MEMORY_MAPPED 
- * 	680x0 doesn't have an IO map!
- *
- *   OPTION_DEBUG_TEST1
- *	Test 1 does bus mastering and interrupt tests, which will help weed 
- *	out brain damaged main boards.
- *
- * Other PERM_OPTIONS settings are listed below.  Note the actual options
- * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc):
- *
- *   OPTION_NO_ASYNC
- *	Don't negotiate for asynchronous transfers on the first command 
- *	when OPTION_ALWAYS_SYNCHRONOUS is set.  Useful for dain bramaged
- *	devices which do something bad rather than sending a MESSAGE 
- *	REJECT back to us like they should if they can't cope.
- *
- *   OPTION_SYNCHRONOUS
- *	Enable support for synchronous transfers.  Target negotiated 
- *	synchronous transfers will be responded to.  To initiate 
- *	a synchronous transfer request,  call 
- *
- *	    request_synchronous (hostno, target) 
- *
- *	from within KGDB.
- *
- *   OPTION_ALWAYS_SYNCHRONOUS
- *	Negotiate for synchronous transfers with every target after
- *	driver initialization or a SCSI bus reset.  This is a bit dangerous, 
- *	since there are some dain bramaged SCSI devices which will accept
- *	SDTR messages but keep talking asynchronously.
- *
- *   OPTION_DISCONNECT
- *	Enable support for disconnect/reconnect.  To change the 
- *	default setting on a given host adapter, call
- *
- *	    request_disconnect (hostno, allow)
- *
- *	where allow is non-zero to allow, 0 to disallow.
- * 
- *  If you really want to run 10MHz FAST SCSI-II transfers, you should 
- *  know that the NCR driver currently ignores parity information.  Most
- *  systems do 5MHz SCSI fine.  I've seen a lot that have problems faster
- *  than 8MHz.  To play it safe, we only request 5MHz transfers.
- *
- *  If you'd rather get 10MHz transfers, edit sdtr_message and change 
- *  the fourth byte from 50 to 25.
- */
-
-/*
- * Sponsored by 
- *	iX Multiuser Multitasking Magazine
- *	Hannover, Germany
- *	hm@ix.de
- *
- * Copyright 1993, 1994, 1995 Drew Eckhardt
- *      Visionary Computing 
- *      (Unix and Linux consulting and custom programming)
- *      drew@PoohSticks.ORG
- *	+1 (303) 786-7975
- *
- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
- * 
- * For more information, please consult 
- *
- * NCR53C810 
- * SCSI I/O Processor
- * Programmer's Guide
- *
- * NCR 53C810
- * PCI-SCSI I/O Processor
- * Data Manual
- *
- * NCR 53C810/53C820
- * PCI-SCSI I/O Processor Design In Guide
- *
- * For literature on Symbios Logic Inc. formerly NCR, SCSI, 
- * and Communication products please call (800) 334-5454 or
- * (719) 536-3300. 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000 
- * +1 (800) 433-5177
- */
-
-/*
- * Design issues : 
- * The cumulative latency needed to propagate a read/write request 
- * through the file system, buffer cache, driver stacks, SCSI host, and 
- * SCSI device is ultimately the limiting factor in throughput once we 
- * have a sufficiently fast host adapter.
- *  
- * So, to maximize performance we want to keep the ratio of latency to data 
- * transfer time to a minimum by
- * 1.  Minimizing the total number of commands sent (typical command latency
- *	including drive and bus mastering host overhead is as high as 4.5ms)
- *	to transfer a given amount of data.  
- *
- *      This is accomplished by placing no arbitrary limit on the number
- *	of scatter/gather buffers supported, since we can transfer 1K
- *	per scatter/gather buffer without Eric's cluster patches, 
- *	4K with.  
- *
- * 2.  Minimizing the number of fatal interrupts serviced, since
- * 	fatal interrupts halt the SCSI I/O processor.  Basically,
- *	this means offloading the practical maximum amount of processing 
- *	to the SCSI chip.
- * 
- *	On the NCR53c810/820/720,  this is accomplished by using 
- *		interrupt-on-the-fly signals when commands complete, 
- *		and only handling fatal errors and SDTR / WDTR 	messages 
- *		in the host code.
- *
- *	On the NCR53c710, interrupts are generated as on the NCR53c8x0,
- *		only the lack of a interrupt-on-the-fly facility complicates
- *		things.   Also, SCSI ID registers and commands are 
- *		bit fielded rather than binary encoded.
- *		
- * 	On the NCR53c700 and NCR53c700-66, operations that are done via 
- *		indirect, table mode on the more advanced chips must be
- *	        replaced by calls through a jump table which 
- *		acts as a surrogate for the DSA.  Unfortunately, this 
- * 		will mean that we must service an interrupt for each 
- *		disconnect/reconnect.
- * 
- * 3.  Eliminating latency by pipelining operations at the different levels.
- * 	
- *	This driver allows a configurable number of commands to be enqueued
- *	for each target/lun combination (experimentally, I have discovered
- *	that two seems to work best) and will ultimately allow for 
- *	SCSI-II tagged queuing.
- * 	
- *
- * Architecture : 
- * This driver is built around a Linux queue of commands waiting to 
- * be executed, and a shared Linux/NCR array of commands to start.  Commands
- * are transferred to the array  by the run_process_issue_queue() function 
- * which is called whenever a command completes.
- *
- * As commands are completed, the interrupt routine is triggered,
- * looks for commands in the linked list of completed commands with
- * valid status, removes these commands from a list of running commands, 
- * calls the done routine, and flags their target/luns as not busy.
- *
- * Due to limitations in the intelligence of the NCR chips, certain
- * concessions are made.  In many cases, it is easier to dynamically 
- * generate/fix-up code rather than calculate on the NCR at run time.  
- * So, code is generated or fixed up for
- *
- * - Handling data transfers, using a variable number of MOVE instructions
- *	interspersed with CALL MSG_IN, WHEN MSGIN instructions.
- *
- * 	The DATAIN and DATAOUT routines	are separate, so that an incorrect
- *	direction can be trapped, and space isn't wasted. 
- *
- *	It may turn out that we're better off using some sort 
- *	of table indirect instruction in a loop with a variable
- *	sized table on the NCR53c710 and newer chips.
- *
- * - Checking for reselection (NCR53c710 and better)
- *
- * - Handling the details of SCSI context switches (NCR53c710 and better),
- *	such as reprogramming appropriate synchronous parameters, 
- *	removing the dsa structure from the NCR's queue of outstanding
- *	commands, etc.
- *
- */
-
-#include <linux/module.h>
-
-
-#include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/time.h>
-#include <linux/blkdev.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/irq.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#endif
-
-#ifdef CONFIG_MVME16x
-#include <asm/mvme16xhw.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#define VALID_IDS
-#endif
-
-#ifdef CONFIG_BVME6000
-#include <asm/bvme6000hw.h>
-
-#define BIG_ENDIAN
-#define NO_IO_SPACE
-#define VALID_IDS
-#endif
-
-#include "scsi.h"
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport_spi.h>
-#include "53c7xx.h"
-#include <linux/stat.h>
-#include <linux/stddef.h>
-
-#ifdef NO_IO_SPACE
-/*
- * The following make the definitions in 53c7xx.h (write8, etc) smaller,
- * we don't have separate i/o space anyway.
- */
-#undef inb
-#undef outb
-#undef inw
-#undef outw
-#undef inl
-#undef outl
-#define inb(x)          1
-#define inw(x)          1
-#define inl(x)          1
-#define outb(x,y)       1
-#define outw(x,y)       1
-#define outl(x,y)       1
-#endif
-
-static int check_address (unsigned long addr, int size);
-static void dump_events (struct Scsi_Host *host, int count);
-static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
-    int free, int issue);
-static void hard_reset (struct Scsi_Host *host);
-static void ncr_scsi_reset (struct Scsi_Host *host);
-static void print_lots (struct Scsi_Host *host);
-static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, 
-    int scntl3, int now_connected);
-static int datapath_residual (struct Scsi_Host *host);
-static const char * sbcl_to_phase (int sbcl);
-static void print_progress (Scsi_Cmnd *cmd);
-static void print_queues (struct Scsi_Host *host);
-static void process_issue_queue (unsigned long flags);
-static int shutdown (struct Scsi_Host *host);
-static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
-static int disable (struct Scsi_Host *host);
-static int NCR53c7xx_run_tests (struct Scsi_Host *host);
-static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id);
-static void NCR53c7x0_intfly (struct Scsi_Host *host);
-static int ncr_halt (struct Scsi_Host *host);
-static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
-    *cmd);
-static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
-static void print_dsa (struct Scsi_Host *host, u32 *dsa,
-    const char *prefix);
-static int print_insn (struct Scsi_Host *host, const u32 *insn,
-    const char *prefix, int kernel);
-
-static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);
-static void NCR53c7x0_init_fixup (struct Scsi_Host *host);
-static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd);
-static void NCR53c7x0_soft_reset (struct Scsi_Host *host);
-
-/* Size of event list (per host adapter) */
-static int track_events = 0;
-static struct Scsi_Host *first_host = NULL;	/* Head of list of NCR boards */
-static struct scsi_host_template *the_template = NULL;
-
-/* NCR53c710 script handling code */
-
-#include "53c7xx_d.h"
-#ifdef A_int_debug_sync
-#define DEBUG_SYNC_INTR A_int_debug_sync
-#endif
-int NCR53c7xx_script_len = sizeof (SCRIPT);
-int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template;
-#ifdef FORCE_DSA_ALIGNMENT
-int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;
-#endif
-
-static char *setup_strings[] =
-	{"","","","","","","",""};
-
-#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings)
-#define SETUP_BUFFER_SIZE 200
-static char setup_buffer[SETUP_BUFFER_SIZE];
-static char setup_used[MAX_SETUP_STRINGS];
-
-void ncr53c7xx_setup (char *str, int *ints)
-{
-   int i;
-   char *p1, *p2;
-
-   p1 = setup_buffer;
-   *p1 = '\0';
-   if (str)
-      strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
-   setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
-   p1 = setup_buffer;
-   i = 0;
-   while (*p1 && (i < MAX_SETUP_STRINGS)) {
-      p2 = strchr(p1, ',');
-      if (p2) {
-         *p2 = '\0';
-         if (p1 != p2)
-            setup_strings[i] = p1;
-         p1 = p2 + 1;
-         i++;
-         }
-      else {
-         setup_strings[i] = p1;
-         break;
-         }
-      }
-   for (i=0; i<MAX_SETUP_STRINGS; i++)
-      setup_used[i] = 0;
-}
-
-
-/* check_setup_strings() returns index if key found, 0 if not
- */
-
-static int check_setup_strings(char *key, int *flags, int *val, char *buf)
-{
-int x;
-char *cp;
-
-   for  (x=0; x<MAX_SETUP_STRINGS; x++) {
-      if (setup_used[x])
-         continue;
-      if (!strncmp(setup_strings[x], key, strlen(key)))
-         break;
-      if (!strncmp(setup_strings[x], "next", strlen("next")))
-         return 0;
-      }
-   if (x == MAX_SETUP_STRINGS)
-      return 0;
-   setup_used[x] = 1;
-   cp = setup_strings[x] + strlen(key);
-   *val = -1;
-   if (*cp != ':')
-      return ++x;
-   cp++;
-   if ((*cp >= '0') && (*cp <= '9')) {
-      *val = simple_strtoul(cp,NULL,0);
-      }
-   return ++x;
-}
-
-
-
-/*
- * KNOWN BUGS :
- * - There is some sort of conflict when the PPP driver is compiled with 
- * 	support for 16 channels?
- * 
- * - On systems which predate the 1.3.x initialization order change,
- *      the NCR driver will cause Cannot get free page messages to appear.  
- *      These are harmless, but I don't know of an easy way to avoid them.
- *
- * - With OPTION_DISCONNECT, on two systems under unknown circumstances,
- *	we get a PHASE MISMATCH with DSA set to zero (suggests that we 
- *	are occurring somewhere in the reselection code) where 
- *	DSP=some value DCMD|DBC=same value.  
- * 	
- *	Closer inspection suggests that we may be trying to execute
- *	some portion of the DSA?
- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
- * scsi0 : no current command : unexpected phase MSGIN.
- *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0
- *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80
- * scsi0 : DSP->
- * 001c46cc : 0x001c46cc 0x00000000
- * 001c46d4 : 0x001c5ea0 0x000011f8
- *
- *	Changed the print code in the phase_mismatch handler so
- *	that we call print_lots to try to diagnose this.
- *
- */
-
-/* 
- * Possible future direction of architecture for max performance :
- *
- * We're using a single start array for the NCR chip.  This is 
- * sub-optimal, because we cannot add a command which would conflict with 
- * an executing command to this start queue, and therefore must insert the 
- * next command for a given I/T/L combination after the first has completed;
- * incurring our interrupt latency between SCSI commands.
- *
- * To allow further pipelining of the NCR and host CPU operation, we want 
- * to set things up so that immediately on termination of a command destined 
- * for a given LUN, we get that LUN busy again.  
- * 
- * To do this, we need to add a 32 bit pointer to which is jumped to 
- * on completion of a command.  If no new command is available, this 
- * would point to the usual DSA issue queue select routine.
- *
- * If one were, it would point to a per-NCR53c7x0_cmd select routine 
- * which starts execution immediately, inserting the command at the head 
- * of the start queue if the NCR chip is selected or reselected.
- *
- * We would change so that we keep a list of outstanding commands 
- * for each unit, rather than a single running_list.  We'd insert 
- * a new command into the right running list; if the NCR didn't 
- * have something running for that yet, we'd put it in the 
- * start queue as well.  Some magic needs to happen to handle the 
- * race condition between the first command terminating before the 
- * new one is written.
- *
- * Potential for profiling : 
- * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution.
- */
-
-
-/*
- * TODO : 
- * 1.  To support WIDE transfers, not much needs to happen.  We
- *	should do CHMOVE instructions instead of MOVEs when
- *	we have scatter/gather segments of uneven length.  When
- * 	we do this, we need to handle the case where we disconnect
- *	between segments.
- * 
- * 2.  Currently, when Icky things happen we do a FATAL().  Instead,
- *     we want to do an integrity check on the parts of the NCR hostdata
- *     structure which were initialized at boot time; FATAL() if that 
- *     fails, and otherwise try to recover.  Keep track of how many
- *     times this has happened within a single SCSI command; if it 
- *     gets excessive, then FATAL().
- *
- * 3.  Parity checking is currently disabled, and a few things should 
- *     happen here now that we support synchronous SCSI transfers :
- *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking)
- *	   and AAP (Assert SATN/ on parity error) bits in SCNTL0.
- *	
- *     2.  We should enable the parity interrupt in the SIEN0 register.
- * 
- *     3.  intr_phase_mismatch() needs to believe that message out is 
- *	   always an "acceptable" phase to have a mismatch in.  If 
- *	   the old phase was MSG_IN, we should send a MESSAGE PARITY 
- *	   error.  If the old phase was something else, we should send
- *	   a INITIATOR_DETECTED_ERROR message.  Note that this could
- *	   cause a RESTORE POINTERS message; so we should handle that 
- *	   correctly first.  Instead, we should probably do an 
- *	   initiator_abort.
- *
- * 4.  MPEE bit of CTEST4 should be set so we get interrupted if 
- *     we detect an error.
- *
- *  
- * 5.  The initial code has been tested on the NCR53c810.  I don't 
- *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710
- *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to 
- *     finish development on those platforms.
- *
- *     NCR53c820/825/720 - need to add wide transfer support, including WDTR 
- *     		negotiation, programming of wide transfer capabilities
- *		on reselection and table indirect selection.
- *
- *     NCR53c710 - need to add fatal interrupt or GEN code for 
- *		command completion signaling.   Need to modify all 
- *		SDID, SCID, etc. registers, and table indirect select code 
- *		since these use bit fielded (ie 1<<target) instead of 
- *		binary encoded target ids.  Need to accommodate
- *		different register mappings, probably scan through
- *		the SCRIPT code and change the non SFBR register operand
- *		of all MOVE instructions.
- *
- *		It is rather worse than this actually, the 710 corrupts
- *		both TEMP and DSA when you do a MOVE MEMORY.  This
- *		screws you up all over the place.  MOVE MEMORY 4 with a
- *		destination of DSA seems to work OK, which helps some.
- *		Richard Hirst  richard@sleepie.demon.co.uk
- * 
- *     NCR53c700/700-66 - need to add code to refix addresses on 
- *		every nexus change, eliminate all table indirect code,
- *		very messy.
- *
- * 6.  The NCR53c7x0 series is very popular on other platforms that 
- *     could be running Linux - ie, some high performance AMIGA SCSI 
- *     boards use it.  
- *	
- *     So, I should include #ifdef'd code so that it is 
- *     compatible with these systems.
- *	
- *     Specifically, the little Endian assumptions I made in my 
- *     bit fields need to change, and if the NCR doesn't see memory
- *     the right way, we need to provide options to reverse words
- *     when the scripts are relocated.
- *
- * 7.  Use vremap() to access memory mapped boards.  
- */
-
-/* 
- * Allow for simultaneous existence of multiple SCSI scripts so we 
- * can have a single driver binary for all of the family.
- *
- * - one for NCR53c700 and NCR53c700-66 chips	(not yet supported)
- * - one for rest (only the NCR53c810, 815, 820, and 825 are currently 
- *	supported)
- * 
- * So that we only need two SCSI scripts, we need to modify things so
- * that we fixup register accesses in READ/WRITE instructions, and 
- * we'll also have to accommodate the bit vs. binary encoding of IDs
- * with the 7xx chips.
- */
-
-#define ROUNDUP(adr,type)	\
-  ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1)))
-
-
-/*
- * Function: issue_to_cmd
- *
- * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd
- *	structure pointer.  
- *
- * Inputs; issue - pointer to start of NOP or JUMP instruction
- *	in issue array.
- *
- * Returns: pointer to command on success; 0 if opcode is NOP.
- */
-
-static inline struct NCR53c7x0_cmd *
-issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
-    u32 *issue)
-{
-    return (issue[0] != hostdata->NOP_insn) ? 
-    /* 
-     * If the IF TRUE bit is set, it's a JUMP instruction.  The
-     * operand is a bus pointer to the dsa_begin routine for this DSA.  The
-     * dsa field of the NCR53c7x0_cmd structure starts with the 
-     * DSA code template.  By converting to a virtual address,
-     * subtracting the code template size, and offset of the 
-     * dsa field, we end up with a pointer to the start of the 
-     * structure (alternatively, we could use the 
-     * dsa_cmnd field, an anachronism from when we weren't
-     * sure what the relationship between the NCR structures
-     * and host structures were going to be.
-     */
-	(struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - 
-	    (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) -
-	    offsetof(struct NCR53c7x0_cmd, dsa)) 
-    /* If the IF TRUE bit is not set, it's a NOP */
-	: NULL;
-}
-
-
-/* 
- * FIXME: we should junk these, in favor of synchronous_want and 
- * wide_want in the NCR53c7x0_hostdata structure.
- */
-
-/* Template for "preferred" synchronous transfer parameters. */
-
-static const unsigned char sdtr_message[] = {
-#ifdef CONFIG_SCSI_NCR53C7xx_FAST
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */
-#else
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ 
-#endif
-};
-
-/* Template to request asynchronous transfers */
-
-static const unsigned char async_message[] = {
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */
-};
-
-/* Template for "preferred" WIDE transfer parameters */
-
-static const unsigned char wdtr_message[] = {
-    EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */
-};
-
-#if 0
-/*
- * Function : struct Scsi_Host *find_host (int host)
- * 
- * Purpose : KGDB support function which translates a host number 
- * 	to a host structure. 
- *
- * Inputs : host - number of SCSI host
- *
- * Returns : NULL on failure, pointer to host structure on success.
- */
-
-static struct Scsi_Host *
-find_host (int host) {
-    struct Scsi_Host *h;
-    for (h = first_host; h && h->host_no != host; h = h->next);
-    if (!h) {
-	printk (KERN_ALERT "scsi%d not found\n", host);
-	return NULL;
-    } else if (h->hostt != the_template) {
-	printk (KERN_ALERT "scsi%d is not a NCR board\n", host);
-	return NULL;
-    }
-    return h;
-}
-
-#if 0
-/*
- * Function : request_synchronous (int host, int target)
- * 
- * Purpose : KGDB interface which will allow us to negotiate for 
- * 	synchronous transfers.  This ill be replaced with a more 
- * 	integrated function; perhaps a new entry in the scsi_host 
- *	structure, accessible via an ioctl() or perhaps /proc/scsi.
- *
- * Inputs : host - number of SCSI host; target - number of target.
- *
- * Returns : 0 when negotiation has been setup for next SCSI command,
- *	-1 on failure.
- */
-
-static int
-request_synchronous (int host, int target) {
-    struct Scsi_Host *h;
-    struct NCR53c7x0_hostdata *hostdata;
-    unsigned long flags;
-    if (target < 0) {
-	printk (KERN_ALERT "target %d is bogus\n", target);
-	return -1;
-    }
-    if (!(h = find_host (host)))
-	return -1;
-    else if (h->this_id == target) {
-	printk (KERN_ALERT "target %d is host ID\n", target);
-	return -1;
-    } 
-    else if (target >= h->max_id) {
-	printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,
-	    h->max_id);
-	return -1;
-    }
-    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
-
-    local_irq_save(flags);
-    if (hostdata->initiate_sdtr & (1 << target)) {
-	local_irq_restore(flags);
-	printk (KERN_ALERT "target %d already doing SDTR\n", target);
-	return -1;
-    } 
-    hostdata->initiate_sdtr |= (1 << target);
-    local_irq_restore(flags);
-    return 0;
-}
-#endif
-
-/*
- * Function : request_disconnect (int host, int on_or_off)
- * 
- * Purpose : KGDB support function, tells us to allow or disallow 
- *	disconnections.
- *
- * Inputs : host - number of SCSI host; on_or_off - non-zero to allow,
- *	zero to disallow.
- *
- * Returns : 0 on success, *	-1 on failure.
- */
-
-static int 
-request_disconnect (int host, int on_or_off) {
-    struct Scsi_Host *h;
-    struct NCR53c7x0_hostdata *hostdata;
-    if (!(h = find_host (host)))
-	return -1;
-    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];
-    if (on_or_off) 
-	hostdata->options |= OPTION_DISCONNECT;
-    else
-	hostdata->options &= ~OPTION_DISCONNECT;
-    return 0;
-}
-#endif
-
-/*
- * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host)
- *
- * Purpose : Initialize internal structures, as required on startup, or 
- *	after a SCSI bus reset.
- * 
- * Inputs : host - pointer to this host adapter's structure
- */
-
-static void 
-NCR53c7x0_driver_init (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int i, j;
-    u32 *ncrcurrent;
-
-    for (i = 0; i < 16; ++i) {
-	hostdata->request_sense[i] = 0;
-    	for (j = 0; j < 8; ++j) 
-	    hostdata->busy[i][j] = 0;
-	set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0);
-    }
-    hostdata->issue_queue = NULL;
-    hostdata->running_list = hostdata->finished_queue = 
-	hostdata->ncrcurrent = NULL;
-    for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
-	i < host->can_queue; ++i, ncrcurrent += 2) {
-	ncrcurrent[0] = hostdata->NOP_insn;
-	ncrcurrent[1] = 0xdeadbeef;
-    }
-    ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE;
-    ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) +
-	hostdata->E_wait_reselect;
-    hostdata->reconnect_dsa_head = 0;
-    hostdata->addr_reconnect_dsa_head = (u32) 
-	virt_to_bus((void *) &(hostdata->reconnect_dsa_head));
-    hostdata->expecting_iid = 0;
-    hostdata->expecting_sto = 0;
-    if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) 
-	hostdata->initiate_sdtr = 0xffff; 
-    else
-    	hostdata->initiate_sdtr = 0;
-    hostdata->talked_to = 0;
-    hostdata->idle = 1;
-}
-
-/* 
- * Function : static int clock_to_ccf_710 (int clock)
- *
- * Purpose :  Return the clock conversion factor for a given SCSI clock.
- *
- * Inputs : clock - SCSI clock expressed in Hz.
- *
- * Returns : ccf on success, -1 on failure.
- */
-
-static int 
-clock_to_ccf_710 (int clock) {
-    if (clock <= 16666666)
-	return -1;
-    if (clock <= 25000000)
-	return 2; 	/* Divide by 1.0 */
-    else if (clock <= 37500000)
-	return 1; 	/* Divide by 1.5 */
-    else if (clock <= 50000000)
-	return 0;	/* Divide by 2.0 */
-    else if (clock <= 66000000)
-	return 3;	/* Divide by 3.0 */
-    else 
-	return -1;
-}
-    
-/* 
- * Function : static int NCR53c7x0_init (struct Scsi_Host *host)
- *
- * Purpose :  initialize the internal structures for a given SCSI host
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- * Preconditions : when this function is called, the chip_type 
- * 	field of the hostdata structure MUST have been set.
- *
- * Returns : 0 on success, -1 on failure.
- */
-
-int 
-NCR53c7x0_init (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    int i, ccf;
-    unsigned char revision;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    /* 
-     * There are some things which we need to know about in order to provide
-     * a semblance of support.  Print 'em if they aren't what we expect, 
-     * otherwise don't add to the noise.
-     * 
-     * -1 means we don't know what to expect.
-     */
-    int val, flags;
-    char buf[32];
-    int expected_id = -1;
-    int expected_clock = -1;
-    int uninitialized = 0;
-#ifdef NO_IO_SPACE
-    int expected_mapping = OPTION_MEMORY_MAPPED;
-#else
-    int expected_mapping = OPTION_IO_MAPPED;
-#endif
-    for (i=0;i<7;i++)
-	hostdata->valid_ids[i] = 1;	/* Default all ID's to scan */
-
-    /* Parse commandline flags */
-    if (check_setup_strings("noasync",&flags,&val,buf))
-    {
-	hostdata->options |= OPTION_NO_ASYNC;
-	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    if (check_setup_strings("nosync",&flags,&val,buf))
-    {
-	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    if (check_setup_strings("nodisconnect",&flags,&val,buf))
-	hostdata->options &= ~OPTION_DISCONNECT;
-
-    if (check_setup_strings("validids",&flags,&val,buf))
-    {
-	for (i=0;i<7;i++) 
-		hostdata->valid_ids[i] = val & (1<<i);
-    }
- 
-    if  ((i = check_setup_strings("next",&flags,&val,buf)))
-    {
-	while (i)
-		setup_used[--i] = 1;
-    }
-
-    if (check_setup_strings("opthi",&flags,&val,buf))
-	hostdata->options = (long long)val << 32;
-    if (check_setup_strings("optlo",&flags,&val,buf))
-	hostdata->options |= val;
-
-    NCR53c7x0_local_setup(host);
-    switch (hostdata->chip) {
-    case 710:
-    case 770:
-    	hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;
-    	hostdata->init_save_regs = NULL;
-    	hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;
-    	hostdata->init_fixup = NCR53c7x0_init_fixup;
-    	hostdata->soft_reset = NCR53c7x0_soft_reset;
-	hostdata->run_tests = NCR53c7xx_run_tests;
-	expected_clock = hostdata->scsi_clock;
-	expected_id = 7;
-    	break;
-    default:
-	printk ("scsi%d : chip type of %d is not supported yet, detaching.\n",
-	    host->host_no, hostdata->chip);
-	scsi_unregister (host);
-	return -1;
-    }
-
-    /* Assign constants accessed by NCR */
-    hostdata->NCR53c7xx_zero = 0;			
-    hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT;
-    hostdata->NCR53c7xx_msg_abort = ABORT;
-    hostdata->NCR53c7xx_msg_nop = NOP;
-    hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;
-    if (expected_mapping == -1 || 
-	(hostdata->options & (OPTION_MEMORY_MAPPED)) != 
-	(expected_mapping & OPTION_MEMORY_MAPPED))
-	printk ("scsi%d : using %s mapped access\n", host->host_no, 
-	    (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : 
-	    "io");
-
-    hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? 
-	DMODE_REG_00 : DMODE_REG_10;
-    hostdata->istat = ((hostdata->chip / 100) == 8) ? 
-    	ISTAT_REG_800 : ISTAT_REG_700;
-
-/* We have to assume that this may be the first access to the chip, so
- * we must set EA in DCNTL. */
-
-    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);
-
-
-/* Only the ISTAT register is readable when the NCR is running, so make 
-   sure it's halted. */
-    ncr_halt(host);
-
-/* 
- * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc,
- *	as does the 710 with one bit per SCSI ID.  Conversely, the NCR
- * 	uses a normal, 3 bit binary representation of these values.
- *
- * Get the rest of the NCR documentation, and FIND OUT where the change
- * was.
- */
-
-#if 0
-	/* May not be able to do this - chip my not have been set up yet */
-	tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG);
-	for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);
-#else
-	host->this_id = 7;
-#endif
-
-/*
- * Note : we should never encounter a board setup for ID0.  So,
- * 	if we see ID0, assume that it was uninitialized and set it
- * 	to the industry standard 7.
- */
-    if (!host->this_id) {
-	printk("scsi%d : initiator ID was %d, changing to 7\n",
-	    host->host_no, host->this_id);
-	host->this_id = 7;
-	hostdata->this_id_mask = 1 << 7;
-	uninitialized = 1;
-    };
-
-    if (expected_id == -1 || host->this_id != expected_id)
-    	printk("scsi%d : using initiator ID %d\n", host->host_no,
-    	    host->this_id);
-
-    /*
-     * Save important registers to allow a soft reset.
-     */
-
-    /*
-     * CTEST7 controls cache snooping, burst mode, and support for 
-     * external differential drivers.  This isn't currently used - the
-     * default value may not be optimal anyway.
-     * Even worse, it may never have been set up since reset.
-     */
-    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
-    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
-    switch (revision) {
-	case 1: revision = 0;    break;
-	case 2: revision = 1;    break;
-	case 4: revision = 2;    break;
-	case 8: revision = 3;    break;
-	default: revision = 255; break;
-    }
-    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
-
-    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))
-    {
-	printk ("scsi%d: Disabling sync working and disconnect/reselect\n",
-							host->host_no);
-	hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);
-    }
-
-    /*
-     * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,
-     * on 800 series chips, it allows for a totem-pole IRQ driver.
-     * NOTE saved_dcntl currently overwritten in init function.
-     * The value read here may be garbage anyway, MVME16x board at least
-     * does not initialise chip if kernel arrived via tftp.
-     */
-
-    hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG);
-
-    /*
-     * DMODE controls DMA burst length, and on 700 series chips,
-     * 286 mode and bus width  
-     * NOTE:  On MVME16x, chip may have been reset, so this could be a
-     * power-on/reset default value.
-     */
-    hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);
-
-    /* 
-     * Now that burst length and enabled/disabled status is known, 
-     * clue the user in on it.  
-     */
-   
-    ccf = clock_to_ccf_710 (expected_clock);
-
-    for (i = 0; i < 16; ++i) 
-	hostdata->cmd_allocated[i] = 0;
-
-    if (hostdata->init_save_regs)
-    	hostdata->init_save_regs (host);
-    if (hostdata->init_fixup)
-    	hostdata->init_fixup (host);
-
-    if (!the_template) {
-	the_template = host->hostt;
-	first_host = host;
-    }
-
-    /* 
-     * Linux SCSI drivers have always been plagued with initialization 
-     * problems - some didn't work with the BIOS disabled since they expected
-     * initialization from it, some didn't work when the networking code
-     * was enabled and registers got scrambled, etc.
-     *
-     * To avoid problems like this, in the future, we will do a soft 
-     * reset on the SCSI chip, taking it back to a sane state.
-     */
-
-    hostdata->soft_reset (host);
-
-#if 1
-    hostdata->debug_count_limit = -1;
-#else
-    hostdata->debug_count_limit = 1;
-#endif
-    hostdata->intrs = -1;
-    hostdata->resets = -1;
-    memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, 
-	sizeof (hostdata->synchronous_want));
-
-    NCR53c7x0_driver_init (host);
-
-    if (request_irq(host->irq, NCR53c7x0_intr, IRQF_SHARED, "53c7xx", host))
-    {
-	printk("scsi%d : IRQ%d not free, detaching\n",
-		host->host_no, host->irq);
-	goto err_unregister;
-    } 
-
-    if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
-        (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
-    	/* XXX Should disable interrupts, etc. here */
-	goto err_free_irq;
-    } else {
-	if (host->io_port)  {
-	    host->n_io_port = 128;
-	    if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
-		goto err_free_irq;
-	}
-    }
-    
-    if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) {
-	printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no);
-	hard_reset (host);
-    }
-    return 0;
-
- err_free_irq:
-    free_irq(host->irq,  NCR53c7x0_intr);
- err_unregister:
-    scsi_unregister(host);
-    return -1;
-}
-
-/* 
- * Function : int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
- *	unsigned long base, int io_port, int irq, int dma, long long options,
- *	int clock);
- *
- * Purpose : initializes a NCR53c7,8x0 based on base addresses,
- *	IRQ, and DMA channel.	
- *	
- * Inputs : tpnt - Template for this SCSI adapter, board - board level
- *	product, chip - 710
- * 
- * Returns : 0 on success, -1 on failure.
- *
- */
-
-int 
-ncr53c7xx_init (struct scsi_host_template *tpnt, int board, int chip,
-    unsigned long base, int io_port, int irq, int dma, 
-    long long options, int clock)
-{
-    struct Scsi_Host *instance;
-    struct NCR53c7x0_hostdata *hostdata;
-    char chip_str[80];
-    int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0,
-	schedule_size = 0, ok = 0;
-    void *tmp;
-    unsigned long page;
-
-    switch (chip) {
-    case 710:
-    case 770:
-	schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */;
-	script_len = NCR53c7xx_script_len;
-    	dsa_len = NCR53c7xx_dsa_len;
-    	options |= OPTION_INTFLY;
-    	sprintf (chip_str, "NCR53c%d", chip);
-    	break;
-    default:
-    	printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip);
-    	return -1;
-    }
-
-    printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d",
-    	chip_str, base, io_port, irq);
-    if (dma == DMA_NONE)
-    	printk("\n");
-    else 
-    	printk(", dma %d\n", dma);
-
-    if (options & OPTION_DEBUG_PROBE_ONLY) {
-    	printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n");
-    	return -1;
-    }
-
-    max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len +
-    	/* Size of dynamic part of command structure : */
-	2 * /* Worst case : we don't know if we need DATA IN or DATA out */
-		( 2 * /* Current instructions per scatter/gather segment */ 
-        	  tpnt->sg_tablesize + 
-                  3 /* Current startup / termination required per phase */
-		) *
-	8 /* Each instruction is eight bytes */;
-
-    /* Allocate fixed part of hostdata, dynamic part to hold appropriate
-       SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure.
-
-       We need a NCR53c7x0_cmd structure for scan_scsis() when we are 
-       not loaded as a module, and when we're loaded as a module, we 
-       can't use a non-dynamically allocated structure because modules
-       are vmalloc()'d, which can allow structures to cross page 
-       boundaries and breaks our physical/virtual address assumptions
-       for DMA.
-
-       So, we stick it past the end of our hostdata structure.
-
-       ASSUMPTION : 
-       	 Regardless of how many simultaneous SCSI commands we allow,
-	 the probe code only executes a _single_ instruction at a time,
-	 so we only need one here, and don't need to allocate NCR53c7x0_cmd
-	 structures for each target until we are no longer in scan_scsis
-	 and kmalloc() has become functional (memory_init() happens 
-	 after all device driver initialization).
-    */
-
-    size = sizeof(struct NCR53c7x0_hostdata) + script_len + 
-    /* Note that alignment will be guaranteed, since we put the command
-       allocated at probe time after the fixed-up SCSI script, which 
-       consists of 32 bit words, aligned on a 32 bit boundary.  But
-       on a 64bit machine we need 8 byte alignment for hostdata->free, so
-       we add in another 4 bytes to take care of potential misalignment
-       */
-	(sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size;
-
-    page = __get_free_pages(GFP_ATOMIC,1);
-    if(page==0)
-    {
-    	printk(KERN_ERR "53c7xx: out of memory.\n");
-    	return -ENOMEM;
-    }
-#ifdef FORCE_DSA_ALIGNMENT
-    /*
-     * 53c710 rev.0 doesn't have an add-with-carry instruction.
-     * Ensure we allocate enough memory to force DSA alignment.
-    */
-    size += 256;
-#endif
-    /* Size should be < 8K, so we can fit it in two pages. */
-    if (size > 8192) {
-      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
-      return -1;
-    }
-
-    instance = scsi_register (tpnt, 4);
-    if (!instance)
-    {
-        free_page(page);
-	return -1;
-    }
-    instance->hostdata[0] = page;
-    memset((void *)instance->hostdata[0], 0, 8192);
-    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);
-    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);
-    kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);
-
-    /* FIXME : if we ever support an ISA NCR53c7xx based board, we
-       need to check if the chip is running in a 16 bit mode, and if so 
-       unregister it if it is past the 16M (0x1000000) mark */
-
-    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];
-    hostdata->size = size;
-    hostdata->script_count = script_len / sizeof(u32);
-    hostdata->board = board;
-    hostdata->chip = chip;
-
-    /*
-     * Being memory mapped is more desirable, since 
-     *
-     * - Memory accesses may be faster.
-     *
-     * - The destination and source address spaces are the same for 
-     *	 all instructions, meaning we don't have to twiddle dmode or 
-     *	 any other registers.
-     *
-     * So, we try for memory mapped, and if we don't get it,
-     * we go for port mapped, and that failing we tell the user
-     * it can't work.
-     */
-
-    if (base) {
-	instance->base = base;
-	/* Check for forced I/O mapping */
-    	if (!(options & OPTION_IO_MAPPED)) {
-	    options |= OPTION_MEMORY_MAPPED;
-	    ok = 1;
-	}
-    } else {
-	options &= ~OPTION_MEMORY_MAPPED;
-    }
-
-    if (io_port) {
-	instance->io_port = io_port;
-	options |= OPTION_IO_MAPPED;
-	ok = 1;
-    } else {
-	options &= ~OPTION_IO_MAPPED;
-    }
-
-    if (!ok) {
-	printk ("scsi%d : not initializing, no I/O or memory mapping known \n",
-	    instance->host_no);
-	scsi_unregister (instance);
-	return -1;
-    }
-    instance->irq = irq;
-    instance->dma_channel = dma;
-
-    hostdata->options = options;
-    hostdata->dsa_len = dsa_len;
-    hostdata->max_cmd_size = max_cmd_size;
-    hostdata->num_cmds = 1;
-    hostdata->scsi_clock = clock;
-    /* Initialize single command */
-    tmp = (hostdata->script + hostdata->script_count);
-#ifdef FORCE_DSA_ALIGNMENT
-    {
-	void *t = ROUNDUP(tmp, void *);
-	if (((u32)t & 0xff) > CmdPageStart)
-	    t = (void *)((u32)t + 255);
-	t = (void *)(((u32)t & ~0xff) + CmdPageStart);
-        hostdata->free = t;
-#if 0
-	printk ("scsi: Registered size increased by 256 to %d\n", size);
-	printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);
-	printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",
-			(u32)tmp, (u32)t);
-#endif
-    }
-#else
-    hostdata->free = ROUNDUP(tmp, void *);
-#endif
-    hostdata->free->real = tmp;
-    hostdata->free->size = max_cmd_size;
-    hostdata->free->free = NULL;
-    hostdata->free->next = NULL;
-    hostdata->extra_allocate = 0;
-
-    /* Allocate command start code space */
-    hostdata->schedule = (chip == 700 || chip == 70066) ?
-	NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);
-
-/* 
- * For diagnostic purposes, we don't really care how fast things blaze.
- * For profiling, we want to access the 800ns resolution system clock,
- * using a 'C' call on the host processor.
- *
- * Therefore, there's no need for the NCR chip to directly manipulate
- * this data, and we should put it wherever is most convenient for 
- * Linux.
- */
-    if (track_events) 
-	hostdata->events = (struct NCR53c7x0_event *) (track_events ? 
-	    vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL);
-    else
-	hostdata->events = NULL;
-
-    if (hostdata->events) {
-	memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) *
-	    track_events);	
-	hostdata->event_size = track_events;
-	hostdata->event_index = 0;
-    } else 
-	hostdata->event_size = 0;
-
-    return NCR53c7x0_init(instance);
-}
-
-
-/* 
- * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host)
- *
- * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device.
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- */
-
-static void 
-NCR53c7x0_init_fixup (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned char tmp;
-    int i, ncr_to_memory, memory_to_ncr;
-    u32 base;
-    NCR53c7x0_local_setup(host);
-
-
-    /* XXX - NOTE : this code MUST be made endian aware */
-    /*  Copy code into buffer that was allocated at detection time.  */
-    memcpy ((void *) hostdata->script, (void *) SCRIPT, 
-	sizeof(SCRIPT));
-    /* Fixup labels */
-    for (i = 0; i < PATCHES; ++i) 
-	hostdata->script[LABELPATCHES[i]] += 
-    	    virt_to_bus(hostdata->script);
-    /* Fixup addresses of constants that used to be EXTERNAL */
-
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_msg_abort)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_msg_reject)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_zero)));
-    patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, 
-    	virt_to_bus(&(hostdata->NCR53c7xx_sink)));
-    patch_abs_32 (hostdata->script, 0, NOP_insn,
-	virt_to_bus(&(hostdata->NOP_insn)));
-    patch_abs_32 (hostdata->script, 0, schedule,
-	virt_to_bus((void *) hostdata->schedule));
-
-    /* Fixup references to external variables: */
-    for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i)
-       hostdata->script[EXTERNAL_PATCHES[i].offset] +=
-         virt_to_bus(EXTERNAL_PATCHES[i].address);
-
-    /* 
-     * Fixup absolutes set at boot-time.
-     * 
-     * All non-code absolute variables suffixed with "dsa_" and "int_"
-     * are constants, and need no fixup provided the assembler has done 
-     * it for us (I don't know what the "real" NCR assembler does in 
-     * this case, my assembler does the right magic).
-     */
-
-    patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, 
-    	Ent_dsa_code_save_data_pointer - Ent_dsa_zero);
-    patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers,
-    	Ent_dsa_code_restore_pointers - Ent_dsa_zero);
-    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,
-    	Ent_dsa_code_check_reselect - Ent_dsa_zero);
-
-    /*
-     * Just for the hell of it, preserve the settings of 
-     * Burst Length and Enable Read Line bits from the DMODE 
-     * register.  Make sure SCRIPTS start automagically.
-     */
-
-#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
-    /* We know better what we want than 16xBug does! */
-    tmp = DMODE_10_BL_8 | DMODE_10_FC2;
-#else
-    tmp = NCR53c7x0_read8(DMODE_REG_10);
-    tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD |
-								DMODE_710_UO);
-#endif
-
-    if (!(hostdata->options & OPTION_MEMORY_MAPPED)) {
-    	base = (u32) host->io_port;
-    	memory_to_ncr = tmp|DMODE_800_DIOM;
-    	ncr_to_memory = tmp|DMODE_800_SIOM;
-    } else {
-    	base = virt_to_bus((void *)host->base);
-	memory_to_ncr = ncr_to_memory = tmp;
-    }
-
-    /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */
-    patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800);
-    patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG);
-    patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG);
-
-    /*
-     * I needed some variables in the script to be accessible to 
-     * both the NCR chip and the host processor. For these variables,
-     * I made the arbitrary decision to store them directly in the 
-     * hostdata structure rather than in the RELATIVE area of the 
-     * SCRIPTS.
-     */
-    
-
-    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);
-    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);
-    patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory);
-
-    patch_abs_32 (hostdata->script, 0, msg_buf, 
-	virt_to_bus((void *)&(hostdata->msg_buf)));
-    patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, 
-    	virt_to_bus((void *)&(hostdata->reconnect_dsa_head)));
-    patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, 
-	virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head)));
-    patch_abs_32 (hostdata->script, 0, reselected_identify, 
-    	virt_to_bus((void *)&(hostdata->reselected_identify)));
-/* reselected_tag is currently unused */
-#if 0
-    patch_abs_32 (hostdata->script, 0, reselected_tag, 
-    	virt_to_bus((void *)&(hostdata->reselected_tag)));
-#endif
-
-    patch_abs_32 (hostdata->script, 0, test_dest, 
-	virt_to_bus((void*)&hostdata->test_dest));
-    patch_abs_32 (hostdata->script, 0, test_src, 
-	virt_to_bus(&hostdata->test_source));
-    patch_abs_32 (hostdata->script, 0, saved_dsa,
-	virt_to_bus((void *)&hostdata->saved2_dsa));
-    patch_abs_32 (hostdata->script, 0, emulfly,
-	virt_to_bus((void *)&hostdata->emulated_intfly));
-
-    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, 
-	(unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero));
-
-/* These are for event logging; the ncr_event enum contains the 
-   actual interrupt numbers. */
-#ifdef A_int_EVENT_SELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT);
-#endif
-#ifdef A_int_EVENT_DISCONNECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT);
-#endif
-#ifdef A_int_EVENT_RESELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT);
-#endif
-#ifdef A_int_EVENT_COMPLETE
-   patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE);
-#endif
-#ifdef A_int_EVENT_IDLE
-   patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE);
-#endif
-#ifdef A_int_EVENT_SELECT_FAILED
-   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, 
-	(u32) EVENT_SELECT_FAILED);
-#endif
-#ifdef A_int_EVENT_BEFORE_SELECT
-   patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT,
-	(u32) EVENT_BEFORE_SELECT);
-#endif
-#ifdef A_int_EVENT_RESELECT_FAILED
-   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, 
-	(u32) EVENT_RESELECT_FAILED);
-#endif
-
-    /*
-     * Make sure the NCR and Linux code agree on the location of 
-     * certain fields.
-     */
-
-    hostdata->E_accept_message = Ent_accept_message;
-    hostdata->E_command_complete = Ent_command_complete;		
-    hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout;
-    hostdata->E_data_transfer = Ent_data_transfer;
-    hostdata->E_debug_break = Ent_debug_break;	
-    hostdata->E_dsa_code_template = Ent_dsa_code_template;
-    hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end;
-    hostdata->E_end_data_transfer = Ent_end_data_transfer;
-    hostdata->E_initiator_abort = Ent_initiator_abort;
-    hostdata->E_msg_in = Ent_msg_in;
-    hostdata->E_other_transfer = Ent_other_transfer;
-    hostdata->E_other_in = Ent_other_in;
-    hostdata->E_other_out = Ent_other_out;
-    hostdata->E_reject_message = Ent_reject_message;
-    hostdata->E_respond_message = Ent_respond_message;
-    hostdata->E_select = Ent_select;
-    hostdata->E_select_msgout = Ent_select_msgout;
-    hostdata->E_target_abort = Ent_target_abort;
-#ifdef Ent_test_0
-    hostdata->E_test_0 = Ent_test_0;
-#endif
-    hostdata->E_test_1 = Ent_test_1;
-    hostdata->E_test_2 = Ent_test_2;
-#ifdef Ent_test_3
-    hostdata->E_test_3 = Ent_test_3;
-#endif
-    hostdata->E_wait_reselect = Ent_wait_reselect;
-    hostdata->E_dsa_code_begin = Ent_dsa_code_begin;
-
-    hostdata->dsa_cmdout = A_dsa_cmdout;
-    hostdata->dsa_cmnd = A_dsa_cmnd;
-    hostdata->dsa_datain = A_dsa_datain;
-    hostdata->dsa_dataout = A_dsa_dataout;
-    hostdata->dsa_end = A_dsa_end;			
-    hostdata->dsa_msgin = A_dsa_msgin;
-    hostdata->dsa_msgout = A_dsa_msgout;
-    hostdata->dsa_msgout_other = A_dsa_msgout_other;
-    hostdata->dsa_next = A_dsa_next;
-    hostdata->dsa_select = A_dsa_select;
-    hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero;
-    hostdata->dsa_status = A_dsa_status;
-    hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + 
-	8 /* destination operand */;
-
-    /* sanity check */
-    if (A_dsa_fields_start != Ent_dsa_code_template_end - 
-    	Ent_dsa_zero) 
-    	printk("scsi%d : NCR dsa_fields start is %d not %d\n",
-    	    host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - 
-    	    Ent_dsa_zero);
-
-    printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,
-	virt_to_bus(hostdata->script), hostdata->script);
-}
-
-/*
- * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host)
- *
- * Purpose : run various verification tests on the NCR chip, 
- *	including interrupt generation, and proper bus mastering
- * 	operation.
- * 
- * Inputs : host - a properly initialized Scsi_Host structure
- *
- * Preconditions : the NCR chip must be in a halted state.
- *
- * Returns : 0 if all tests were successful, -1 on error.
- * 
- */
-
-static int 
-NCR53c7xx_run_tests (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long timeout;
-    u32 start;
-    int failed, i;
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    /* The NCR chip _must_ be idle to run the test scripts */
-
-    local_irq_save(flags);
-    if (!hostdata->idle) {
-	printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
-	local_irq_restore(flags);
-	return -1;
-    }
-
-    /* 
-     * Check for functional interrupts, this could work as an
-     * autoprobe routine.
-     */
-
-    if ((hostdata->options & OPTION_DEBUG_TEST1) && 
-	    hostdata->state != STATE_DISABLED) {
-	hostdata->idle = 0;
-	hostdata->test_running = 1;
-	hostdata->test_completed = -1;
-	hostdata->test_dest = 0;
-	hostdata->test_source = 0xdeadbeef;
-	start = virt_to_bus (hostdata->script) + hostdata->E_test_1;
-    	hostdata->state = STATE_RUNNING;
-	printk ("scsi%d : test 1", host->host_no);
-	NCR53c7x0_write32 (DSP_REG, start);
-	if (hostdata->options & OPTION_DEBUG_TRACE)
-	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
-						DCNTL_STD);
-	printk (" started\n");
-	local_irq_restore(flags);
-
-	/* 
-	 * This is currently a .5 second timeout, since (in theory) no slow 
-	 * board will take that long.  In practice, we've seen one 
-	 * pentium which occassionally fails with this, but works with 
-	 * 10 times as much?
-	 */
-
-	timeout = jiffies + 5 * HZ / 10;
-	while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
-		barrier();
-
-	failed = 1;
-	if (hostdata->test_completed == -1)
-	    printk ("scsi%d : driver test 1 timed out%s\n",host->host_no ,
-		(hostdata->test_dest == 0xdeadbeef) ? 
-		    " due to lost interrupt.\n"
-		    "         Please verify that the correct IRQ is being used for your board,\n"
-		    : "");
-	else if (hostdata->test_completed != 1) 
-	    printk ("scsi%d : test 1 bad interrupt value (%d)\n", 
-		host->host_no, hostdata->test_completed);
-	else 
-	    failed = (hostdata->test_dest != 0xdeadbeef);
-
-	if (hostdata->test_dest != 0xdeadbeef) {
-	    printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n"
-                    "         probable cache invalidation problem.  Please configure caching\n"
-		    "         as write-through or disabled\n",
-		host->host_no, hostdata->test_dest);
-	}
-
-	if (failed) {
-	    printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n",
-		host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)),
-		hostdata->script, start);
-	    printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
-		NCR53c7x0_read32(DSPS_REG));
-	    local_irq_restore(flags);
-	    return -1;
-	}
-    	hostdata->test_running = 0;
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_TEST2) && 
-	hostdata->state != STATE_DISABLED) {
-	u32 dsa[48];
-    	unsigned char identify = IDENTIFY(0, 0);
-	unsigned char cmd[6];
-	unsigned char data[36];
-    	unsigned char status = 0xff;
-    	unsigned char msg = 0xff;
-
-    	cmd[0] = INQUIRY;
-    	cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0;
-    	cmd[4] = sizeof(data); 
-
-    	dsa[2] = 1;
-    	dsa[3] = virt_to_bus(&identify);
-    	dsa[4] = 6;
-    	dsa[5] = virt_to_bus(&cmd);
-    	dsa[6] = sizeof(data);
-    	dsa[7] = virt_to_bus(&data);
-    	dsa[8] = 1;
-    	dsa[9] = virt_to_bus(&status);
-    	dsa[10] = 1;
-    	dsa[11] = virt_to_bus(&msg);
-
-	for (i = 0; i < 6; ++i) {
-#ifdef VALID_IDS
-	    if (!hostdata->valid_ids[i])
-		continue;
-#endif
-	    local_irq_disable();
-	    if (!hostdata->idle) {
-		printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
-		local_irq_restore(flags);
-		return -1;
-	    }
-
-	    /* 710: bit mapped scsi ID, async   */
-            dsa[0] = (1 << i) << 16;
-	    hostdata->idle = 0;
-	    hostdata->test_running = 2;
-	    hostdata->test_completed = -1;
-	    start = virt_to_bus(hostdata->script) + hostdata->E_test_2;
-	    hostdata->state = STATE_RUNNING;
-	    NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));
-	    NCR53c7x0_write32 (DSP_REG, start);
-	    if (hostdata->options & OPTION_DEBUG_TRACE)
-	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-	    local_irq_restore(flags);
-
-	    timeout = jiffies + 5 * HZ;	/* arbitrary */
-	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
-	    	barrier();
-
-	    NCR53c7x0_write32 (DSA_REG, 0);
-
-	    if (hostdata->test_completed == 2) {
-		data[35] = 0;
-		printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n",
-		    host->host_no, i, data + 8);
-		printk ("scsi%d : status ", host->host_no);
-		scsi_print_status (status);
-		printk ("\nscsi%d : message ", host->host_no);
-		spi_print_msg(&msg);
-		printk ("\n");
-	    } else if (hostdata->test_completed == 3) {
-		printk("scsi%d : test 2 no connection with target %d\n",
-		    host->host_no, i);
-		if (!hostdata->idle) {
-		    printk("scsi%d : not idle\n", host->host_no);
-		    local_irq_restore(flags);
-		    return -1;
-		}
-	    } else if (hostdata->test_completed == -1) {
-		printk ("scsi%d : test 2 timed out\n", host->host_no);
-		local_irq_restore(flags);
-		return -1;
-	    } 
-	    hostdata->test_running = 0;
-	}
-    }
-
-    local_irq_restore(flags);
-    return 0;
-}
-
-/*
- * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer,
- * 	performing all necessary relocation.
- *
- * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large
- *	enough to hold the NCR53c8xx dsa.
- */
-
-static void 
-NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {
-    Scsi_Cmnd *c = cmd->cmd;
-    struct Scsi_Host *host = c->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    int i;
-
-    memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),
-    	hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template);
-
-    /* 
-     * Note : within the NCR 'C' code, dsa points to the _start_
-     * of the DSA structure, and _not_ the offset of dsa_zero within
-     * that structure used to facilitate shorter signed offsets
-     * for the 8 bit ALU.
-     * 
-     * The implications of this are that 
-     * 
-     * - 32 bit A_dsa_* absolute values require an additional 
-     * 	 dsa_zero added to their value to be correct, since they are 
-     *   relative to dsa_zero which is in essentially a separate
-     *   space from the code symbols.
-     *
-     * - All other symbols require no special treatment.
-     */
-
-    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_lun, c->device->lun);
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-	dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero -
-	Ent_dsa_code_template + A_dsa_next);
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
-    	dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
-    	dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710));
-    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	    dsa_temp_target, 1 << c->device->id);
-    /* XXX - new pointer stuff */
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual));
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-    	dsa_temp_addr_residual, virt_to_bus(&cmd->residual));
-
-    /*  XXX - new start stuff */
-
-    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
-	dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));
-}
-
-/* 
- * Function : run_process_issue_queue (void)
- * 
- * Purpose : insure that the coroutine is running and will process our 
- * 	request.  process_issue_queue_running is checked/set here (in an 
- *	inline function) rather than in process_issue_queue itself to reduce 
- * 	the chances of stack overflow.
- *
- */
-
-static volatile int process_issue_queue_running = 0;
-
-static __inline__ void 
-run_process_issue_queue(void) {
-    unsigned long flags;
-    local_irq_save(flags);
-    if (!process_issue_queue_running) {
-	process_issue_queue_running = 1;
-        process_issue_queue(flags);
-	/* 
-         * process_issue_queue_running is cleared in process_issue_queue 
-	 * once it can't do more work, and process_issue_queue exits with 
-	 * interrupts disabled.
-	 */
-    }
-    local_irq_restore(flags);
-}
-
-/*
- * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int
- *	result)
- *
- * Purpose : mark SCSI command as finished, OR'ing the host portion 
- *	of the result word into the result field of the corresponding
- *	Scsi_Cmnd structure, and removing it from the internal queues.
- *
- * Inputs : cmd - command, result - entire result field
- *
- * Preconditions : the 	NCR chip should be in a halted state when 
- *	abnormal_finished is run, since it modifies structures which
- *	the NCR expects to have exclusive access to.
- */
-
-static void 
-abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
-    Scsi_Cmnd *c = cmd->cmd;
-    struct Scsi_Host *host = c->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    unsigned long flags;
-    int left, found;
-    volatile struct NCR53c7x0_cmd * linux_search;
-    volatile struct NCR53c7x0_cmd * volatile *linux_prev;
-    volatile u32 *ncr_prev, *ncrcurrent, ncr_search;
-
-#if 0
-    printk ("scsi%d: abnormal finished\n", host->host_no);
-#endif
-
-    local_irq_save(flags);
-    found = 0;
-    /* 
-     * Traverse the NCR issue array until we find a match or run out 
-     * of instructions.  Instructions in the NCR issue array are 
-     * either JUMP or NOP instructions, which are 2 words in length.
-     */
-
-
-    for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; 
-	left > 0; --left, ncrcurrent += 2)
-    {
-	if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) 
-	{
-	    ncrcurrent[0] = hostdata->NOP_insn;
-	    ncrcurrent[1] = 0xdeadbeef;
-	    ++found;
-	    break;
-	}
-    }
-	
-    /* 
-     * Traverse the NCR reconnect list of DSA structures until we find 
-     * a pointer to this dsa or have found too many command structures.  
-     * We let prev point at the next field of the previous element or 
-     * head of the list, so we don't do anything different for removing 
-     * the head element.  
-     */
-
-    for (left = host->can_queue,
-	    ncr_search = hostdata->reconnect_dsa_head, 
-	    ncr_prev = &hostdata->reconnect_dsa_head;
-	left >= 0 && ncr_search && 
-	    ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) 
-		!= (char *) cmd->dsa;
-	ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + 
-	    hostdata->dsa_next), ncr_search = *ncr_prev, --left);
-
-    if (left < 0) 
-	printk("scsi%d: loop detected in ncr reconncect list\n",
-	    host->host_no);
-    else if (ncr_search) {
-	if (found)
-	    printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
-		host->host_no, c->pid);
-	else {
-	    volatile u32 * next = (u32 *) 
-	    	((char *)bus_to_virt(ncr_search) + hostdata->dsa_next);
-	    *ncr_prev = *next;
-/* If we're at the tail end of the issue queue, update that pointer too. */
-	    found = 1;
-	}
-    }
-
-    /*
-     * Traverse the host running list until we find this command or discover
-     * we have too many elements, pointing linux_prev at the next field of the 
-     * linux_previous element or head of the list, search at this element.
-     */
-
-    for (left = host->can_queue, linux_search = hostdata->running_list, 
-	    linux_prev = &hostdata->running_list;
-	left >= 0 && linux_search && linux_search != cmd;
-	linux_prev = &(linux_search->next), 
-	    linux_search = linux_search->next, --left);
-    
-    if (left < 0) 
-	printk ("scsi%d: loop detected in host running list for scsi pid %ld\n",
-	    host->host_no, c->pid);
-    else if (linux_search) {
-	*linux_prev = linux_search->next;
-	--hostdata->busy[c->device->id][c->device->lun];
-    }
-
-    /* Return the NCR command structure to the free list */
-    cmd->next = hostdata->free;
-    hostdata->free = cmd;
-    c->host_scribble = NULL;
-
-    /* And return */
-    c->result = result;
-    c->scsi_done(c);
-
-    local_irq_restore(flags);
-    run_process_issue_queue();
-}
-
-/* 
- * Function : static void intr_break (struct Scsi_Host *host,
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose :  Handler for breakpoint interrupts from a SCSI script
- *
- * Inputs : host - pointer to this host adapter's structure,
- * 	cmd - pointer to the command (if any) dsa was pointing 
- * 	to.
- *
- */
-
-static void 
-intr_break (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_break *bp;
-#if 0
-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
-#endif
-    u32 *dsp;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];		
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Find the break point corresponding to this address, and 
-     * dump the appropriate debugging information to standard 
-     * output.  
-     */
-    local_irq_save(flags);
-    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
-    for (bp = hostdata->breakpoints; bp && bp->address != dsp; 
-    	bp = bp->next);
-    if (!bp) 
-    	panic("scsi%d : break point interrupt from %p with no breakpoint!",
-    	    host->host_no, dsp);
-
-    /*
-     * Configure the NCR chip for manual start mode, so that we can 
-     * point the DSP register at the instruction that follows the 
-     * INT int_debug_break instruction.
-     */
-
-    NCR53c7x0_write8 (hostdata->dmode, 
-	NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN);
-
-    /*
-     * And update the DSP register, using the size of the old 
-     * instruction in bytes.
-     */
-
-    local_irq_restore(flags);
-}
-/*
- * Function : static void print_synchronous (const char *prefix, 
- *	const unsigned char *msg)
- * 
- * Purpose : print a pretty, user and machine parsable representation
- *	of a SDTR message, including the "real" parameters, data
- *	clock so we can tell transfer rate at a glance.
- *
- * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes)
- */
-
-static void
-print_synchronous (const char *prefix, const unsigned char *msg) {
-    if (msg[4]) {
-	int Hz = 1000000000 / (msg[3] * 4);
-	int integer = Hz / 1000000;
-	int fraction = (Hz - (integer * 1000000)) / 10000;
-	printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n",
-	    prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction,
-	    (((msg[3] * 4) < 200) ? "FAST" : "synchronous"),
-	    (((msg[3] * 4) < 200) ? "-II" : ""));
-    } else 
-	printk ("%sasynchronous SCSI\n", prefix);
-}
-
-/*
- * Function : static void set_synchronous (struct Scsi_Host *host, 
- *	 	int target, int sxfer, int scntl3, int now_connected)
- *
- * Purpose : reprogram transfers between the selected SCSI initiator and 
- *	target with the given register values; in the indirect
- *	select operand, reselection script, and chip registers.
- *
- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
- *	sxfer and scntl3 - NCR registers. now_connected - if non-zero, 
- *	we should reprogram the registers now too.
- *
- *      NOTE:  For 53c710, scntl3 is actually used for SCF bits from
- *	SBCL, as we don't have a SCNTL3.
- */
-
-static void
-set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3,
-    int now_connected) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) 
-	host->hostdata[0];
-    u32 *script;
-    NCR53c7x0_local_setup(host);
-
-    /* These are eight bit registers */
-    sxfer &= 0xff;
-    scntl3 &= 0xff;
-
-    hostdata->sync[target].sxfer_sanity = sxfer;
-    hostdata->sync[target].scntl3_sanity = scntl3;
-
-/* 
- * HARD CODED : synchronous script is EIGHT words long.  This 
- * must agree with 53c7.8xx.h
- */
-
-    if ((hostdata->chip != 700) && (hostdata->chip != 70066)) {
-	hostdata->sync[target].select_indirect = (1 << target) << 16 |
-		(sxfer << 8);
-	hostdata->sync[target].sscf_710 = scntl3;
-
-	script = (u32 *) hostdata->sync[target].script;
-
-	/* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */
-	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
-		DCMD_RWRI_OP_MOVE) << 24) |
-		(SBCL_REG << 16) | (scntl3 << 8);
-	script[1] = 0;
-	script += 2;
-
-	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
-	    DCMD_RWRI_OP_MOVE) << 24) |
-		(SXFER_REG << 16) | (sxfer << 8);
-	script[1] = 0;
-	script += 2;
-
-#ifdef DEBUG_SYNC_INTR
-	if (hostdata->options & OPTION_DEBUG_DISCONNECT) {
-	    script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE;
-	    script[1] = DEBUG_SYNC_INTR;
-	    script += 2;
-	}
-#endif
-
-	script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE;
-	script[1] = 0;
-	script += 2;
-    }
-
-    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) 
-	printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n",
-	host->host_no, target, sxfer, scntl3);
-
-    if (now_connected) {
-	NCR53c7x0_write8(SBCL_REG, scntl3);
-	NCR53c7x0_write8(SXFER_REG, sxfer);
-    }
-}
-
-
-/*
- * Function : static int asynchronous (struct Scsi_Host *host, int target)
- *
- * Purpose : reprogram between the selected SCSI Host adapter and target 
- *      (assumed to be currently connected) for asynchronous transfers.
- *
- * Inputs : host - SCSI host structure, target - numeric target ID.
- *
- * Preconditions : the NCR chip should be in one of the halted states
- */
-    
-static void
-asynchronous (struct Scsi_Host *host, int target) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-    set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3,
-	1);
-    printk ("scsi%d : setting target %d to asynchronous SCSI\n",
-	host->host_no, target);
-}
-
-/* 
- * XXX - do we want to go out of our way (ie, add extra code to selection
- * 	in the NCR53c710/NCR53c720 script) to reprogram the synchronous
- * 	conversion bits, or can we be content in just setting the 
- * 	sxfer bits?  I chose to do so [richard@sleepie.demon.co.uk]
- */
-
-/* Table for NCR53c8xx synchronous values */
-
-/* This table is also correct for 710, allowing that scf=4 is equivalent
- * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock.
- * For any other clock values, we cannot use entries with SCF values of
- * 4.  I guess that for a 66MHz clock, the slowest it will set is 2MHz,
- * and for a 50MHz clock, the slowest will be 2.27Mhz.  Should check
- * that a device doesn't try and negotiate sync below these limits!
- */
- 
-static const struct {
-    int div;		/* Total clock divisor * 10 */
-    unsigned char scf;	/* */
-    unsigned char tp;	/* 4 + tp = xferp divisor */
-} syncs[] = {
-/*	div	scf	tp	div	scf	tp	div	scf	tp */
-    {	40,	1,	0}, {	50,	1,	1}, {	60,	1,	2}, 
-    {	70,	1,	3}, {	75,	2,	1}, {	80,	1,	4},
-    {	90,	1,	5}, {	100,	1,	6}, {	105,	2,	3},
-    {	110,	1,	7}, {	120,	2,	4}, {	135,	2,	5},
-    {	140,	3,	3}, {	150,	2,	6}, {	160,	3,	4},
-    {	165,	2,	7}, {	180,	3,	5}, {	200,	3,	6},
-    {	210,	4,	3}, {	220,	3,	7}, {	240,	4,	4},
-    {	270,	4,	5}, {	300,	4,	6}, {	330,	4,	7}
-};
-
-/*
- * Function : static void synchronous (struct Scsi_Host *host, int target, 
- *	char *msg)
- *
- * Purpose : reprogram transfers between the selected SCSI initiator and 
- *	target for synchronous SCSI transfers such that the synchronous 
- *	offset is less than that requested and period at least as long 
- *	as that requested.  Also modify *msg such that it contains 
- *	an appropriate response. 
- *
- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
- *	msg - synchronous transfer request.
- */
-
-
-static void
-synchronous (struct Scsi_Host *host, int target, char *msg) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int desire, divisor, i, limit;
-    unsigned char scntl3, sxfer;
-/* The diagnostic message fits on one line, even with max. width integers */
-    char buf[80];
-
-/* Desired transfer clock in Hz */
-    desire = 1000000000L / (msg[3] * 4);
-/* Scale the available SCSI clock by 10 so we get tenths */
-    divisor = (hostdata->scsi_clock * 10) / desire;
-
-/* NCR chips can handle at most an offset of 8 */
-    if (msg[4] > 8)
-	msg[4] = 8;
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : optimal synchronous divisor of %d.%01d\n",
-	    host->host_no, divisor / 10, divisor % 10);
-
-    limit = ARRAY_SIZE(syncs) - 1;
-    for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i);
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : selected synchronous divisor of %d.%01d\n",
-	    host->host_no, syncs[i].div / 10, syncs[i].div % 10);
-
-    msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4);
-
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : selected synchronous period of %dns\n", host->host_no,
-	    msg[3] * 4);
-
-    scntl3 = syncs[i].scf;
-    sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4);
-    if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", 
-	    host->host_no, (int) sxfer, (int) scntl3);
-    set_synchronous (host, target, sxfer, scntl3, 1);
-    sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target);
-    print_synchronous (buf, msg);
-}
-
-/* 
- * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host,
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose :  Handler for INT generated instructions for the 
- * 	NCR53c810/820 SCSI SCRIPT
- *
- * Inputs : host - pointer to this host adapter's structure,
- * 	cmd - pointer to the command (if any) dsa was pointing 
- * 	to.
- *
- */
-
-static int 
-NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
-    NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    int print;
-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];		
-    u32 dsps,*dsp;	/* Argument of the INT instruction */
-
-    NCR53c7x0_local_setup(host);
-    dsps = NCR53c7x0_read32(DSPS_REG);
-    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
-
-    /* RGH 150597:  Frig.  Commands which fail with Check Condition are
-     * Flagged as successful - hack dsps to indicate check condition */
-#if 0
-    /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions
-     * and then dies.  Seems to handle Check Condition at startup, but
-     * not mid kernel build. */
-    if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2)
-        dsps = A_int_err_check_condition;
-#endif
-
-    if (hostdata->options & OPTION_DEBUG_INTR) 
-	printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps);
-
-    switch (dsps) {
-    case A_int_msg_1:
-	print = 1;
-	switch (hostdata->msg_buf[0]) {
-	/* 
-	 * Unless we've initiated synchronous negotiation, I don't
-	 * think that this should happen.
-	 */
-	case MESSAGE_REJECT:
-	    hostdata->dsp = hostdata->script + hostdata->E_accept_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    if (cmd && (cmd->flags & CMD_FLAG_SDTR)) {
-		printk ("scsi%d : target %d rejected SDTR\n", host->host_no, 
-		    c->device->id);
-		cmd->flags &= ~CMD_FLAG_SDTR;
-		asynchronous (host, c->device->id);
-		print = 0;
-	    } 
-	    break;
-	case INITIATE_RECOVERY:
-	    printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n",
-		host->host_no);
-	    /* Fall through to default */
-	    hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    break;
-	default:
-	    printk ("scsi%d : unsupported message, rejecting\n",
-		host->host_no);
-	    hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	}
-	if (print) {
-	    printk ("scsi%d : received message", host->host_no);
-	    if (c) 
-	    	printk (" from target %d lun %d ", c->device->id, c->device->lun);
-	    spi_print_msg((unsigned char *) hostdata->msg_buf);
-	    printk("\n");
-	}
-	
-	return SPECIFIC_INT_NOTHING;
-
-
-    case A_int_msg_sdtr:
-/*
- * At this point, hostdata->msg_buf contains
- * 0 EXTENDED MESSAGE
- * 1 length 
- * 2 SDTR
- * 3 period * 4ns
- * 4 offset
- */
-
-	if (cmd) {
-	    char buf[80];
-	    sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id,
-		(cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting");
-	    print_synchronous (buf, (unsigned char *) hostdata->msg_buf);
-
-	/* 
-	 * Initiator initiated, won't happen unless synchronous 
-	 * 	transfers are enabled.  If we get a SDTR message in
-	 * 	response to our SDTR, we should program our parameters
-	 * 	such that 
-	 *		offset <= requested offset
-	 *		period >= requested period		 	
-   	 */
-	    if (cmd->flags & CMD_FLAG_SDTR) {
-		cmd->flags &= ~CMD_FLAG_SDTR; 
-		if (hostdata->msg_buf[4]) 
-		    synchronous (host, c->device->id, (unsigned char *) 
-		    	hostdata->msg_buf);
-		else 
-		    asynchronous (host, c->device->id);
-		hostdata->dsp = hostdata->script + hostdata->E_accept_message /
-		    sizeof(u32);
-		hostdata->dsp_changed = 1;
-		return SPECIFIC_INT_NOTHING;
-	    } else {
-		if (hostdata->options & OPTION_SYNCHRONOUS)  {
-		    cmd->flags |= CMD_FLAG_DID_SDTR;
-		    synchronous (host, c->device->id, (unsigned char *) 
-			hostdata->msg_buf);
-		} else {
-		    hostdata->msg_buf[4] = 0;		/* 0 offset = async */
-		    asynchronous (host, c->device->id);
-		}
-		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5);
-		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) 
-		    virt_to_bus ((void *)&hostdata->msg_buf));
-		hostdata->dsp = hostdata->script + 
-		    hostdata->E_respond_message / sizeof(u32);
-		hostdata->dsp_changed = 1;
-	    }
-	    return SPECIFIC_INT_NOTHING;
-	}
-	/* Fall through to abort if we couldn't find a cmd, and 
-	   therefore a dsa structure to twiddle */
-    case A_int_msg_wdtr:
-	hostdata->dsp = hostdata->script + hostdata->E_reject_message /
-	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_err_unexpected_phase:
-	if (hostdata->options & OPTION_DEBUG_INTR) 
-	    printk ("scsi%d : unexpected phase\n", host->host_no);
-	return SPECIFIC_INT_ABORT;
-    case A_int_err_selected:
-	if ((hostdata->chip / 100) == 8)
-	    printk ("scsi%d : selected by target %d\n", host->host_no,
-	        (int) NCR53c7x0_read8(SDID_REG_800) &7);
-	else
-            printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no,
-                (int) NCR53c7x0_read8(LCRC_REG_10));
-	hostdata->dsp = hostdata->script + hostdata->E_target_abort / 
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_err_unexpected_reselect:
-	if ((hostdata->chip / 100) == 8)
-	    printk ("scsi%d : unexpected reselect by target %d lun %d\n", 
-	        host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7,
-	        hostdata->reselected_identify & 7);
-	else
-            printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no,
-                (int) NCR53c7x0_read8(LCRC_REG_10));
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-/*
- * Since contingent allegiance conditions are cleared by the next 
- * command issued to a target, we must issue a REQUEST SENSE 
- * command after receiving a CHECK CONDITION status, before
- * another command is issued.
- * 
- * Since this NCR53c7x0_cmd will be freed after use, we don't 
- * care if we step on the various fields, so modify a few things.
- */
-    case A_int_err_check_condition: 
-#if 0
-	if (hostdata->options & OPTION_DEBUG_INTR) 
-#endif
-	    printk ("scsi%d : CHECK CONDITION\n", host->host_no);
-	if (!c) {
-	    printk("scsi%d : CHECK CONDITION with no SCSI command\n",
-		host->host_no);
-	    return SPECIFIC_INT_PANIC;
-	}
-
-	/* 
-	 * FIXME : this uses the normal one-byte selection message.
-	 * 	We may want to renegotiate for synchronous & WIDE transfers
-	 * 	since these could be the crux of our problem.
-	 *
-	 hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll
-	 * 	have to set this up so that the rest of the DSA
-	 *	agrees with this being an untagged queue'd command.
-	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1);
-
-    	/* 
-    	 * Modify the table indirect for COMMAND OUT phase, since 
-    	 * Request Sense is a six byte command.
-    	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6);
-
-        /*
-         * The CDB is now mirrored in our local non-cached
-         * structure, but keep the old structure up to date as well,
-         * just in case anyone looks at it.
-         */
-
-	/*
-	 * XXX Need to worry about data buffer alignment/cache state
-	 * XXX here, but currently never get A_int_err_check_condition,
-	 * XXX so ignore problem for now.
-         */
-	cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE;
-	cmd->cmnd[0] = c->cmnd[1] &= 0xe0;	/* Zero all but LUN */
-	cmd->cmnd[0] = c->cmnd[2] = 0;
-	cmd->cmnd[0] = c->cmnd[3] = 0;
-	cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer);
-	cmd->cmnd[0] = c->cmnd[5] = 0; 
-
-	/*
-	 * Disable dataout phase, and program datain to transfer to the 
-	 * sense buffer, and add a jump to other_transfer after the 
-    	 * command so overflow/underrun conditions are detected.
-	 */
-
-    	patch_dsa_32 (cmd->dsa, dsa_dataout, 0, 
-	    virt_to_bus(hostdata->script) + hostdata->E_other_transfer);
-    	patch_dsa_32 (cmd->dsa, dsa_datain, 0, 
-	    virt_to_bus(cmd->data_transfer_start));
-    	cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | 
-    	    DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer);
-    	cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer);
-
-	cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) 
-    	    << 24) | DBC_TCI_TRUE;
-	cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + 
-	    hostdata->E_other_transfer;
-
-    	/*
-    	 * Currently, this command is flagged as completed, ie 
-    	 * it has valid status and message data.  Reflag it as
-    	 * incomplete.  Q - need to do something so that original
-	 * status, etc are used.
-    	 */
-
-	cmd->result = cmd->cmd->result = 0xffff;		
-
-	/* 
-	 * Restart command as a REQUEST SENSE.
-	 */
-	hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select /
-	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-	return SPECIFIC_INT_NOTHING;
-    case A_int_debug_break:
-	return SPECIFIC_INT_BREAK;
-    case A_int_norm_aborted:
-	hostdata->dsp = (u32 *) hostdata->schedule;
-	hostdata->dsp_changed = 1;
-	if (cmd)
-	    abnormal_finished (cmd, DID_ERROR << 16);
-	return SPECIFIC_INT_NOTHING;
-    case A_int_norm_emulateintfly:
-	NCR53c7x0_intfly(host);
-	return SPECIFIC_INT_NOTHING;
-    case A_int_test_1:
-    case A_int_test_2:
-	hostdata->idle = 1;
-	hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1;
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk("scsi%d : test%d complete\n", host->host_no,
-		hostdata->test_completed);
-	return SPECIFIC_INT_NOTHING;
-#ifdef A_int_debug_reselected_ok
-    case A_int_debug_reselected_ok:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    	OPTION_DEBUG_DISCONNECT)) {
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    u32 *dsa;
-	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
-
-	    printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", 
-		host->host_no, NCR53c7x0_read32(DSA_REG), dsa);
-	    printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt(cmd->saved_data_pointer));
-	    print_insn (host, hostdata->script + Ent_reselected_ok / 
-    	    	    sizeof(u32), "", 1);
-	    if ((hostdata->chip / 100) == 8)
-    	        printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
-		    host->host_no, NCR53c7x0_read8(SXFER_REG),
-		    NCR53c7x0_read8(SCNTL3_REG_800));
-	    else
-    	        printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n",
-		    host->host_no, NCR53c7x0_read8(SXFER_REG));
-	    if (c) {
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script, "", 1);
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script + 2, "", 1);
-	    }
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_reselect_check
-    case A_int_debug_reselect_check:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    u32 *dsa;
-#if 0
-	    u32 *code;
-#endif
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
-	    printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n",
-		host->host_no, virt_to_bus(dsa), dsa);
-	    if (dsa) {
-		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt (cmd->saved_data_pointer));
-#if 0
-		printk("scsi%d : template code :\n", host->host_no);
-		for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) 
-		    / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); 
-		    code += print_insn (host, code, "", 1));
-#endif
-	    }
-	    print_insn (host, hostdata->script + Ent_reselected_ok / 
-    	    	    sizeof(u32), "", 1);
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_dsa_schedule
-    case A_int_debug_dsa_schedule:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    u32 *dsa;
-	    /* 
-	     * Note - this dsa is not based on location relative to 
-	     * the command structure, but to location relative to the 
-	     * DSA register 
-	     */	
-	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
-	    printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", 
-		host->host_no, virt_to_bus(dsa), dsa);
-	    if (dsa) 
-		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n"
-		       "         (temp was 0x%x (virt 0x%p))\n",
-		    host->host_no, cmd->saved_data_pointer,
-		    bus_to_virt (cmd->saved_data_pointer),
-		    NCR53c7x0_read32 (TEMP_REG),
-		    bus_to_virt (NCR53c7x0_read32(TEMP_REG)));
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_scheduled
-    case A_int_debug_scheduled:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", 
-		host->host_no, NCR53c7x0_read32(DSA_REG),
-	    	bus_to_virt(NCR53c7x0_read32(DSA_REG)));
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_idle
-    case A_int_debug_idle:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : idle\n", host->host_no);
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_cmd
-    case A_int_debug_cmd:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : command sent\n");
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_dsa_loaded
-    case A_int_debug_dsa_loaded:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no,
-		NCR53c7x0_read32(DSA_REG), 
-		bus_to_virt(NCR53c7x0_read32(DSA_REG)));
-	}
-	return SPECIFIC_INT_RESTART; 
-#endif
-#ifdef A_int_debug_reselected
-    case A_int_debug_reselected:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-	    OPTION_DEBUG_DISCONNECT)) {
-	    if ((hostdata->chip / 100) == 8)
-		printk("scsi%d : reselected by target %d lun %d\n",
-		    host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, 
-		    (int) hostdata->reselected_identify & 7);
-	    else
-		printk("scsi%d : reselected by LCRC=0x%02x lun %d\n",
-                    host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10),
-                    (int) hostdata->reselected_identify & 7);
-	    print_queues(host);
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_disconnect_msg
-    case A_int_debug_disconnect_msg:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
-	    if (c)
-		printk("scsi%d : target %d lun %d disconnecting\n", 
-		    host->host_no, c->device->id, c->device->lun);
-	    else
-		printk("scsi%d : unknown target disconnecting\n",
-		    host->host_no);
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_disconnected
-    case A_int_debug_disconnected:
-	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-		OPTION_DEBUG_DISCONNECT)) {
-	    printk ("scsi%d : disconnected, new queues are\n", 
-		host->host_no);
-	    print_queues(host);
-#if 0
-	    /* Not valid on ncr53c710! */
-    	    printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
-		host->host_no, NCR53c7x0_read8(SXFER_REG),
-		NCR53c7x0_read8(SCNTL3_REG_800));
-#endif
-	    if (c) {
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script, "", 1);
-		print_insn (host, (u32 *) 
-		    hostdata->sync[c->device->id].script + 2, "", 1);
-	    }
-	}
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_panic
-    case A_int_debug_panic:
-	printk("scsi%d : int_debug_panic received\n", host->host_no);
-	print_lots (host);
-	return SPECIFIC_INT_PANIC;
-#endif
-#ifdef A_int_debug_saved
-    case A_int_debug_saved:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT)) {
-    	    printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n",
-    	    	host->host_no, cmd->saved_data_pointer,
-		bus_to_virt (cmd->saved_data_pointer));
-    	    print_progress (c);
-    	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_restored
-    case A_int_debug_restored:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT)) {
-    	    if (cmd) {
-		int size;
-    	    	printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n",
-    	    	    host->host_no, cmd->saved_data_pointer, bus_to_virt (
-		    cmd->saved_data_pointer));
-		size = print_insn (host, (u32 *) 
-		    bus_to_virt(cmd->saved_data_pointer), "", 1);
-		size = print_insn (host, (u32 *) 
-		    bus_to_virt(cmd->saved_data_pointer) + size, "", 1);
-    	    	print_progress (c);
-	    }
-#if 0
-	    printk ("scsi%d : datapath residual %d\n",
-		host->host_no, datapath_residual (host)) ;
-#endif
-    	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_sync
-    case A_int_debug_sync:
-    	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-    	    OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
-	    unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3;
-	    if ((hostdata->chip / 100) == 8) {
-		scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800);
-		if (c) {
-		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity ||
-		    scntl3 != hostdata->sync[c->device->id].scntl3_sanity) {
-		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x, scntl3=0x%x",
-			    host->host_no, sxfer, scntl3);
-			NCR53c7x0_write8 (SXFER_REG, sxfer);
-			NCR53c7x0_write8 (SCNTL3_REG_800, scntl3);
-		    }
-		} else 
-    	    	  printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n",
-		    host->host_no, (int) sxfer, (int) scntl3);
-	    } else {
-		if (c) {
-		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) {
-		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x",
-			    host->host_no, sxfer);
-			NCR53c7x0_write8 (SXFER_REG, sxfer);
-			NCR53c7x0_write8 (SBCL_REG,
-				hostdata->sync[c->device->id].sscf_710);
-		    }
-		} else 
-    	    	  printk ("scsi%d : unknown command sxfer=0x%x\n",
-		    host->host_no, (int) sxfer);
-	    }
-	}
-    	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_datain
-	case A_int_debug_datain:
-	    if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
-		OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
-		int size;
-		if ((hostdata->chip / 100) == 8)
-		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n"
-			"         datapath residual=%d\n",
-		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
-		    (int) NCR53c7x0_read8(SXFER_REG), 
-		    (int) NCR53c7x0_read8(SCNTL3_REG_800),
-		    datapath_residual (host)) ;
-		else
-		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n"
-			"         datapath residual=%d\n",
-		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
-		    (int) NCR53c7x0_read8(SXFER_REG), 
-		    datapath_residual (host)) ;
-		print_insn (host, dsp, "", 1);
-		size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1);
-		print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1);
-	   } 
-	return SPECIFIC_INT_RESTART;
-#endif
-#ifdef A_int_debug_check_dsa
-	case A_int_debug_check_dsa:
-	    if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
-		int sdid;
-		int tmp;
-		char *where;
-		if (hostdata->chip / 100 == 8)
-		    sdid = NCR53c7x0_read8 (SDID_REG_800) & 15;
-		else {
-		    tmp = NCR53c7x0_read8 (SDID_REG_700);
-		    if (!tmp)
-			panic ("SDID_REG_700 = 0");
-		    tmp >>= 1;
-		    sdid = 0;
-		    while (tmp) {
-			tmp >>= 1;
-			sdid++;
-		    }
-		}
-		where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 
-			(DCMD_REG)) == hostdata->script + 
-		    	Ent_select_check_dsa / sizeof(u32) ?
-		    "selection" : "reselection";
-		if (c && sdid != c->device->id) {
-		    printk ("scsi%d : SDID target %d != DSA target %d at %s\n",
-			host->host_no, sdid, c->device->id, where);
-		    print_lots(host);
-		    dump_events (host, 20);
-		    return SPECIFIC_INT_PANIC;
-		}
-	    }
-	    return SPECIFIC_INT_RESTART;
-#endif
-    default:
-	if ((dsps & 0xff000000) == 0x03000000) {
-	     printk ("scsi%d : misc debug interrupt 0x%x\n",
-		host->host_no, dsps);
-	    return SPECIFIC_INT_RESTART;
-	} else if ((dsps & 0xff000000) == 0x05000000) {
-	    if (hostdata->events) {
-		struct NCR53c7x0_event *event;
-		++hostdata->event_index;
-		if (hostdata->event_index >= hostdata->event_size)
-		    hostdata->event_index = 0;
-		event = (struct NCR53c7x0_event *) hostdata->events + 
-		    hostdata->event_index;
-		event->event = (enum ncr_event) dsps;
-		event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-		if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
-		    if (hostdata->chip / 100 == 8)
-			event->target = NCR53c7x0_read8(SSID_REG_800);
-		    else {
-			unsigned char tmp, sdid;
-		        tmp = NCR53c7x0_read8 (SDID_REG_700);
-		        if (!tmp)
-			    panic ("SDID_REG_700 = 0");
-		        tmp >>= 1;
-		        sdid = 0;
-		        while (tmp) {
-			    tmp >>= 1;
-			    sdid++;
-		        }
-			event->target = sdid;
-		    }
-		}
-		else 
-			event->target = 255;
-
-		if (event->event == EVENT_RESELECT)
-		    event->lun = hostdata->reselected_identify & 0xf;
-		else if (c)
-		    event->lun = c->device->lun;
-		else
-		    event->lun = 255;
-		do_gettimeofday(&(event->time));
-		if (c) {
-		    event->pid = c->pid;
-		    memcpy ((void *) event->cmnd, (void *) c->cmnd, 
-			sizeof (event->cmnd));
-		} else {
-		    event->pid = -1;
-		}
-	    }
-	    return SPECIFIC_INT_RESTART;
-	}
-
-	printk ("scsi%d : unknown user interrupt 0x%x\n", 
-	    host->host_no, (unsigned) dsps);
-	return SPECIFIC_INT_PANIC;
-    }
-}
-
-/* 
- * XXX - the stock NCR assembler won't output the scriptu.h file,
- * which undefine's all #define'd CPP symbols from the script.h
- * file, which will create problems if you use multiple scripts
- * with the same  symbol names.
- *
- * If you insist on using NCR's assembler, you could generate
- * scriptu.h from script.h using something like 
- *
- * grep #define script.h | \
- * sed 's/#define[ 	][ 	]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \
- * > scriptu.h
- */
-
-#include "53c7xx_u.h"
-
-/* XXX - add alternate script handling code here */
-
-
-/* 
- * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host)
- *
- * Purpose :  perform a soft reset of the NCR53c7xx chip
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- * Preconditions : NCR53c7x0_init must have been called for this 
- *      host.
- * 
- */
-
-static void 
-NCR53c7x0_soft_reset (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    local_irq_save(flags);
-
-    /* Disable scsi chip and s/w level 7 ints */
-
-#ifdef CONFIG_MVME16x
-    if (MACH_IS_MVME16x)
-    {
-        volatile unsigned long v;
-
-        v = *(volatile unsigned long *)0xfff4006c;
-        v &= ~0x8000;
-        *(volatile unsigned long *)0xfff4006c = v;
-        v = *(volatile unsigned long *)0xfff4202c;
-        v &= ~0x10;
-        *(volatile unsigned long *)0xfff4202c = v;
-    }
-#endif
-    /* Anything specific for your hardware? */
-
-    /*
-     * Do a soft reset of the chip so that everything is 
-     * reinitialized to the power-on state.
-     *
-     * Basically follow the procedure outlined in the NCR53c700
-     * data manual under Chapter Six, How to Use, Steps Necessary to
-     * Start SCRIPTS, with the exception of actually starting the 
-     * script and setting up the synchronous transfer gunk.
-     */
-
-    /* Should we reset the scsi bus here??????????????????? */
-
-    NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST);
-    NCR53c7x0_write8(ISTAT_REG_700, 0);
-
-    /*
-     * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten
-     * here.  We should have some better way of working out the CF bit
-     * setting..
-     */
-
-    hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM;
-    if (hostdata->scsi_clock > 50000000)
-	hostdata->saved_dcntl |= DCNTL_700_CF_3;
-    else
-    if (hostdata->scsi_clock > 37500000)
-        hostdata->saved_dcntl |= DCNTL_700_CF_2;
-#if 0
-    else
-	/* Any clocks less than 37.5MHz? */
-#endif
-
-    if (hostdata->options & OPTION_DEBUG_TRACE)
-    	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
-    else
-    	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
-    /* Following disables snooping - snooping is not required, as non-
-     * cached pages are used for shared data, and appropriate use is
-     * made of cache_push/cache_clear.  Indeed, for 68060
-     * enabling snooping causes disk corruption of ext2fs free block
-     * bitmaps and the like.  If you have a 68060 with snooping hardwared
-     * on, then you need to enable CONFIG_060_WRITETHROUGH.
-     */
-    NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
-    /* Actually burst of eight, according to my 53c710 databook */
-    NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
-    NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
-    NCR53c7x0_write8(SBCL_REG, 0);
-    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700);
-    NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ? 
-            SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2);
-
-    /*
-     * Enable all interrupts, except parity which we only want when
-     * the user requests it.
-     */
-
-    NCR53c7x0_write8(DIEN_REG, DIEN_700_BF |
-		DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
-
-    NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ?
-	    SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC |
-		SIEN_SGE | SIEN_MA);
-
-#ifdef CONFIG_MVME16x
-    if (MACH_IS_MVME16x)
-    {
-        volatile unsigned long v;
-
-        /* Enable scsi chip and s/w level 7 ints */
-        v = *(volatile unsigned long *)0xfff40080;
-        v = (v & ~(0xf << 28)) | (4 << 28);
-        *(volatile unsigned long *)0xfff40080 = v;
-        v = *(volatile unsigned long *)0xfff4006c;
-        v |= 0x8000;
-        *(volatile unsigned long *)0xfff4006c = v;
-        v = *(volatile unsigned long *)0xfff4202c;
-        v = (v & ~0xff) | 0x10 | 4;
-        *(volatile unsigned long *)0xfff4202c = v;
-    }
-#endif
-    /* Anything needed for your hardware? */
-    local_irq_restore(flags);
-}
-
-
-/*
- * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
- * 
- * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
- * 	reused in a LIFO manner to minimize cache thrashing).
- *
- * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd
- *	structures for this device, do so.  Attempt to complete all scheduled
- *	allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on
- *	the free list.  Teach programmers not to drink and hack.
- *
- * Inputs : cmd - SCSI command
- *
- * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd;
- *	NULL on failure.
- */
-
-static void
-my_free_page (void *addr, int dummy)
-{
-    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
-     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
-     */
-    kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING);
-    free_page ((u32)addr);
-}
-
-static struct NCR53c7x0_cmd *
-allocate_cmd (Scsi_Cmnd *cmd) {
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    u32 real;			/* Real address */
-    int size;			/* Size of *tmp */
-    struct NCR53c7x0_cmd *tmp;
-    unsigned long flags;
-
-    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
-	printk ("scsi%d : num_cmds = %d, can_queue = %d\n"
-		"         target = %d, lun = %d, %s\n",
-	    host->host_no, hostdata->num_cmds, host->can_queue,
-	    cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] &
-		(1 << cmd->device->lun)) ? "already allocated" : "not allocated");
-
-/*
- * If we have not yet reserved commands for this I_T_L nexus, and
- * the device exists (as indicated by permanent Scsi_Cmnd structures
- * being allocated under 1.3.x, or being outside of scan_scsis in
- * 1.2.x), do so now.
- */
-    if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) &&
-				cmd->device && cmd->device->has_cmdblocks) {
-      if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue)
-          hostdata->extra_allocate += host->cmd_per_lun;
-      hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun);
-    }
-
-    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
-    	++hostdata->num_cmds) {
-    /* historically, kmalloc has returned unaligned addresses; pad so we
-       have enough room to ROUNDUP */
-	size = hostdata->max_cmd_size + sizeof (void *);
-#ifdef FORCE_DSA_ALIGNMENT
-	/*
-	 * 53c710 rev.0 doesn't have an add-with-carry instruction.
-	 * Ensure we allocate enough memory to force alignment.
-	 */
-	size += 256;
-#endif
-/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
-
-        if (size > 4096) {
-            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
-	    return NULL;
-	}
-        real = get_zeroed_page(GFP_ATOMIC);
-        if (real == 0)
-        	return NULL;
-        cache_push(virt_to_phys((void *)real), 4096);
-        cache_clear(virt_to_phys((void *)real), 4096);
-        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
-	tmp = ROUNDUP(real, void *);
-#ifdef FORCE_DSA_ALIGNMENT
-	{
-	    if (((u32)tmp & 0xff) > CmdPageStart)
-		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
-	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
-#if 0
-	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
-			size, real, (u32)tmp);
-#endif
-	}
-#endif
-	tmp->real = (void *)real;
-	tmp->size = size;			
-	tmp->free = ((void (*)(void *, int)) my_free_page);
-	local_irq_save(flags);
-	tmp->next = hostdata->free;
-	hostdata->free = tmp;
-	local_irq_restore(flags);
-    }
-    local_irq_save(flags);
-    tmp = (struct NCR53c7x0_cmd *) hostdata->free;
-    if (tmp) {
-	hostdata->free = tmp->next;
-    }
-    local_irq_restore(flags);
-    if (!tmp)
-	printk ("scsi%d : can't allocate command for target %d lun %d\n",
-	    host->host_no, cmd->device->id, cmd->device->lun);
-    return tmp;
-}
-
-/*
- * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
- *
- *
- * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the 
- * 	Scsi_Cmnd structure passed in cmd, including dsa and Linux field 
- * 	initialization, and dsa code relocation.
- *
- * Inputs : cmd - SCSI command
- *
- * Returns : NCR53c7x0_cmd structure corresponding to cmd,
- *	NULL on failure.
- */
-static struct NCR53c7x0_cmd *
-create_cmd (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-        host->hostdata[0];	
-    struct NCR53c7x0_cmd *tmp; 	/* NCR53c7x0_cmd structure for this command */
-    int datain,  		/* Number of instructions per phase */
-	dataout;
-    int data_transfer_instructions, /* Count of dynamic instructions */
-    	i;			/* Counter */
-    u32 *cmd_datain,		/* Address of datain/dataout code */
-	*cmd_dataout;		/* Incremented as we assemble */
-#ifdef notyet
-    unsigned char *msgptr;	/* Current byte in select message */
-    int msglen;			/* Length of whole select message */
-#endif
-    unsigned long flags;
-    u32 exp_select_indirect;	/* Used in sanity check */
-    NCR53c7x0_local_setup(cmd->device->host);
-
-    if (!(tmp = allocate_cmd (cmd)))
-	return NULL;
-
-    /*
-     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
-     * We do this because NCR53c7x0_cmd may have a special cache mode
-     * selected to cope with lack of bus snooping, etc.
-     */
-
-    memcpy(tmp->cmnd, cmd->cmnd, 12);
-    tmp->result = cmd->result;
-
-    /*
-     * Decide whether we need to generate commands for DATA IN,
-     * DATA OUT, neither, or both based on the SCSI command 
-     */
-
-    switch (cmd->cmnd[0]) {
-    /* These commands do DATA IN */
-    case INQUIRY:
-    case MODE_SENSE:
-    case READ_6:
-    case READ_10:
-    case READ_CAPACITY:
-    case REQUEST_SENSE:
-    case READ_BLOCK_LIMITS:
-    case READ_TOC:
-	datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-    	dataout = 0;
-	break;
-    /* These commands do DATA OUT */
-    case MODE_SELECT: 
-    case WRITE_6:
-    case WRITE_10:
-#if 0
-	printk("scsi%d : command is ", host->host_no);
-	__scsi_print_command(cmd->cmnd);
-#endif
-#if 0
-	printk ("scsi%d : %d scatter/gather segments\n", host->host_no,
-	    cmd->use_sg);
-#endif
-    	datain = 0;
-	dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-#if 0
-	hostdata->options |= OPTION_DEBUG_INTR;
-#endif
-	break;
-    /* 
-     * These commands do no data transfer, we should force an
-     * interrupt if a data phase is attempted on them.
-     */
-    case TEST_UNIT_READY:
-    case ALLOW_MEDIUM_REMOVAL:
-    case START_STOP:
-    	datain = dataout = 0;
-	break;
-    /*
-     * We don't know about these commands, so generate code to handle
-     * both DATA IN and DATA OUT phases.  More efficient to identify them
-     * and add them to the above cases.
-     */
-    default:
-	printk("scsi%d : datain+dataout for command ", host->host_no);
-	__scsi_print_command(cmd->cmnd);
-	datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
-    }
-
-    /*
-     * New code : so that active pointers work correctly regardless
-     * 	of where the saved data pointer is at, we want to immediately
-     * 	enter the dynamic code after selection, and on a non-data
-     * 	phase perform a CALL to the non-data phase handler, with
-     * 	returns back to this address.
-     *
-     * 	If a phase mismatch is encountered in the middle of a 
-     * 	Block MOVE instruction, we want to _leave_ that instruction
-     *	unchanged as the current case is, modify a temporary buffer,
-     *	and point the active pointer (TEMP) at that.
-     *
-     * 	Furthermore, we want to implement a saved data pointer, 
-     * 	set by the SAVE_DATA_POINTERs message.
-     *
-     * 	So, the data transfer segments will change to 
-     *		CALL data_transfer, WHEN NOT data phase
-     *		MOVE x, x, WHEN data phase
-     *		( repeat )
-     *		JUMP other_transfer
-     */
-
-    data_transfer_instructions = datain + dataout;
-
-    /*
-     * When we perform a request sense, we overwrite various things,
-     * including the data transfer code.  Make sure we have enough
-     * space to do that.
-     */
-
-    if (data_transfer_instructions < 2)
-    	data_transfer_instructions = 2;
-
-
-    /*
-     * The saved data pointer is set up so that a RESTORE POINTERS message 
-     * will start the data transfer over at the beginning.
-     */
-
-    tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
-	hostdata->E_data_transfer;
-
-    /*
-     * Initialize Linux specific fields.
-     */
-
-    tmp->cmd = cmd;
-    tmp->next = NULL;
-    tmp->flags = 0;
-    tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - 
-	hostdata->dsa_start;
-    tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start;
-
-    /* 
-     * Calculate addresses of dynamic code to fill in DSA
-     */
-
-    tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - 
-    	hostdata->dsa_start) / sizeof(u32);
-    tmp->data_transfer_end = tmp->data_transfer_start + 
-    	2 * data_transfer_instructions;
-
-    cmd_datain = datain ? tmp->data_transfer_start : NULL;
-    cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp->
-    	data_transfer_start) : NULL;
-
-    /*
-     * Fill in the NCR53c7x0_cmd structure as follows
-     * dsa, with fixed up DSA code
-     * datain code
-     * dataout code
-     */
-
-    /* Copy template code into dsa and perform all necessary fixups */
-    if (hostdata->dsa_fixup)
-    	hostdata->dsa_fixup(tmp);
-
-    patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
-    /*
-     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
-     * Do we need to change it for caching reasons?
-     */
-    patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
-
-    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {
-
-	exp_select_indirect = ((1 << cmd->device->id) << 16) |
-			(hostdata->sync[cmd->device->id].sxfer_sanity << 8);
-
-	if (hostdata->sync[cmd->device->id].select_indirect !=
-				exp_select_indirect) {
-	    printk ("scsi%d :  sanity check failed select_indirect=0x%x\n",
-		host->host_no, hostdata->sync[cmd->device->id].select_indirect);
-	    FATAL(host);
-
-	}
-    }
-
-    patch_dsa_32(tmp->dsa, dsa_select, 0,
-		hostdata->sync[cmd->device->id].select_indirect);
-
-    /*
-     * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on
-     * different commands; although it should be trivial to do them
-     * both at the same time.
-     */
-    if (hostdata->initiate_wdtr & (1 << cmd->device->id)) {
-	memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
-	    sizeof(wdtr_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
-	local_irq_save(flags);
-	hostdata->initiate_wdtr &= ~(1 << cmd->device->id);
-	local_irq_restore(flags);
-    } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {
-	memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 
-	    sizeof(sdtr_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
-	tmp->flags |= CMD_FLAG_SDTR;
-	local_irq_save(flags);
-	hostdata->initiate_sdtr &= ~(1 << cmd->device->id);
-	local_irq_restore(flags);
-    
-    }
-#if 1
-    else if (!(hostdata->talked_to & (1 << cmd->device->id)) &&
-		!(hostdata->options & OPTION_NO_ASYNC)) {
-
-	memcpy ((void *) (tmp->select + 1), (void *) async_message, 
-	    sizeof(async_message));
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message));
-	tmp->flags |= CMD_FLAG_SDTR;
-    } 
-#endif
-    else 
-    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1);
-
-    hostdata->talked_to |= (1 << cmd->device->id);
-    tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? 
-	IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun);
-    patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));
-    patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
-    	    virt_to_bus (cmd_dataout)
-	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
-    patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? 
-    	    virt_to_bus (cmd_datain) 
-	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
-    /* 
-     * XXX - need to make endian aware, should use separate variables
-     * for both status and message bytes.
-     */
-    patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1);
-/* 
- * FIXME : these only works for little endian.  We probably want to 
- * 	provide message and status fields in the NCR53c7x0_cmd 
- *	structure, and assign them to cmd->result when we're done.
- */
-#ifdef BIG_ENDIAN
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);
-    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);
-#else
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));
-#endif
-    patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 
-	virt_to_bus(&(hostdata->NCR53c7xx_msg_nop)));
-    
-    /*
-     * Generate code for zero or more of the DATA IN, DATA OUT phases 
-     * in the format 
-     *
-     * CALL data_transfer, WHEN NOT phase
-     * MOVE first buffer length, first buffer address, WHEN phase
-     * ...
-     * MOVE last buffer length, last buffer address, WHEN phase
-     * JUMP other_transfer
-     */
-
-/* 
- * See if we're getting to data transfer by generating an unconditional 
- * interrupt.
- */
-#if 0
-    if (datain) {
-	cmd_datain[0] = 0x98080000;
-	cmd_datain[1] = 0x03ffd00d;
-	cmd_datain += 2;
-    }
-#endif
-
-/* 
- * XXX - I'm undecided whether all of this nonsense is faster
- * in the long run, or whether I should just go and implement a loop
- * on the NCR chip using table indirect mode?
- *
- * In any case, this is how it _must_ be done for 53c700/700-66 chips,
- * so this stays even when we come up with something better.
- *
- * When we're limited to 1 simultaneous command, no overlapping processing,
- * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M
- * drive.
- *
- * Not bad, not good. We'll see.
- */
-
-    tmp->bounce.len = 0;	/* Assume aligned buffer */
-
-    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
-	cmd_dataout += 4, ++i) {
-	u32 vbuf = cmd->use_sg
-	    ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
-	      ((struct scatterlist *)cmd->request_buffer)[i].offset
-	    : (u32)(cmd->request_buffer);
-	u32 bbuf = virt_to_bus((void *)vbuf);
-	u32 count = cmd->use_sg ?
-	    ((struct scatterlist *)cmd->request_buffer)[i].length :
-	    cmd->request_bufflen;
-
-	/*
-	 * If we have buffers which are not aligned with 16 byte cache
-	 * lines, then we just hope nothing accesses the other parts of
-	 * those cache lines while the transfer is in progress.  That would
-	 * fill the cache, and subsequent reads of the dma data would pick
-	 * up the wrong thing.
-	 * XXX We need a bounce buffer to handle that correctly.
-	 */
-
-	if (((bbuf & 15) || (count & 15)) && (datain || dataout))
-	{
-	    /* Bounce buffer needed */
-	    if (cmd->use_sg)
-		printk ("53c7xx: Non-aligned buffer with use_sg\n");
-	    else if (datain && dataout)
-                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");
-            else if (count > 256)
-		printk ("53c7xx: Non-aligned transfer > 256 bytes\n");
-	    else
-	    {
-		    if (datain)
-		    {
-			tmp->bounce.len = count;
-			tmp->bounce.addr = vbuf;
-			bbuf = virt_to_bus(tmp->bounce.buf);
-			tmp->bounce.buf[0] = 0xff;
-			tmp->bounce.buf[1] = 0xfe;
-			tmp->bounce.buf[2] = 0xfd;
-			tmp->bounce.buf[3] = 0xfc;
-	    	    }
-	    	    if (dataout)
-	    	    {
-			memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);
-			bbuf = virt_to_bus(tmp->bounce.buf);
-		    }
-	    }
-	}
-
-	if (datain) {
-            cache_clear(virt_to_phys((void *)vbuf), count);
-	    /* CALL other_in, WHEN NOT DATA_IN */  
-	    cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 
-		DCMD_TCI_IO) << 24) | 
-		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-	    cmd_datain[1] = virt_to_bus (hostdata->script) + 
-		hostdata->E_other_in;
-	    /* MOVE count, buf, WHEN DATA_IN */
-	    cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) 
-    	    	<< 24) | count;
-	    cmd_datain[3] = bbuf;
-#if 0
-	    print_insn (host, cmd_datain, "dynamic ", 1);
-	    print_insn (host, cmd_datain + 2, "dynamic ", 1);
-#endif
-	}
-	if (dataout) {
-            cache_push(virt_to_phys((void *)vbuf), count);
-	    /* CALL other_out, WHEN NOT DATA_OUT */
-	    cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 
-		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-	    cmd_dataout[1] = virt_to_bus(hostdata->script) + 
-    	    	hostdata->E_other_out;
-	    /* MOVE count, buf, WHEN DATA+OUT */
-	    cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 
-		| count;
-	    cmd_dataout[3] = bbuf;
-#if 0
-	    print_insn (host, cmd_dataout, "dynamic ", 1);
-	    print_insn (host, cmd_dataout + 2, "dynamic ", 1);
-#endif
-	}
-    }
-
-    /*
-     * Install JUMP instructions after the data transfer routines to return
-     * control to the do_other_transfer routines.
-     */
-  
-    
-    if (datain) {
-	cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
-    	    DBC_TCI_TRUE;
-	cmd_datain[1] = virt_to_bus(hostdata->script) + 
-    	    hostdata->E_other_transfer;
-#if 0
-	print_insn (host, cmd_datain, "dynamic jump ", 1);
-#endif
-	cmd_datain += 2; 
-    }
-#if 0
-    if (datain) {
-	cmd_datain[0] = 0x98080000;
-	cmd_datain[1] = 0x03ffdeed;
-	cmd_datain += 2;
-    }
-#endif
-    if (dataout) {
-	cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
-    	    DBC_TCI_TRUE;
-	cmd_dataout[1] = virt_to_bus(hostdata->script) + 
-    	    hostdata->E_other_transfer;
-#if 0
-	print_insn (host, cmd_dataout, "dynamic jump ", 1);
-#endif
-	cmd_dataout += 2;
-    }
-
-    return tmp;
-}
-
-/*
- * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
- *      void (*done)(Scsi_Cmnd *))
- *
- * Purpose :  enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *      a pointer to the command descriptor.
- *
- * Returns : 0
- *
- * Side effects :
- *      cmd is added to the per instance driver issue_queue, with major
- *      twiddling done to the host specific fields of cmd.  If the
- *      process_issue_queue coroutine isn't running, it is restarted.
- * 
- * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to 
- *	hold our own data, and pervert the ptr field of the SCp field
- *	to create a linked list.
- */
-
-int
-NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    unsigned long flags;
-    Scsi_Cmnd *tmp;
-
-    cmd->scsi_done = done;
-    cmd->host_scribble = NULL;
-    cmd->SCp.ptr = NULL;
-    cmd->SCp.buffer = NULL;
-
-#ifdef VALID_IDS
-    /* Ignore commands on invalid IDs */
-    if (!hostdata->valid_ids[cmd->device->id]) {
-        printk("scsi%d : ignoring target %d lun %d\n", host->host_no,
-            cmd->device->id, cmd->device->lun);
-        cmd->result = (DID_BAD_TARGET << 16);
-        done(cmd);
-        return 0;
-    }
-#endif
-
-    local_irq_save(flags);
-    if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) 
-	|| ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
-	    !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun)))
-#ifdef LINUX_1_2
-	|| cmd->device->id > 7
-#else
-	|| cmd->device->id >= host->max_id
-#endif
-	|| cmd->device->id == host->this_id
-	|| hostdata->state == STATE_DISABLED) {
-	printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no,
-	    cmd->device->id, cmd->device->lun);
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	local_irq_restore(flags);
-	return 0;
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) &&
-	(hostdata->debug_count_limit == 0)) {
-	printk("scsi%d : maximum commands exceeded\n", host->host_no);
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	local_irq_restore(flags);
-	return 0;
-    }
-
-    if (hostdata->options & OPTION_DEBUG_READ_ONLY) {
-	switch (cmd->cmnd[0]) {
-	case WRITE_6:
-	case WRITE_10:
-	    printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
-		host->host_no);
-	    cmd->result = (DID_BAD_TARGET << 16);
-	    done(cmd);
-	    local_irq_restore(flags);
-	    return 0;
-	}
-    }
-
-    if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
-	    hostdata->debug_count_limit != -1) 
-	--hostdata->debug_count_limit;
-
-    cmd->result = 0xffff;	/* The NCR will overwrite message
-				       and status with valid data */
-    cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd);
-
-    /*
-     * REQUEST SENSE commands are inserted at the head of the queue 
-     * so that we do not clear the contingent allegiance condition
-     * they may be looking at.
-     */
-
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-	cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
-	hostdata->issue_queue = cmd;
-    } else {
-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
-		tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
-	tmp->SCp.ptr = (unsigned char *) cmd;
-    }
-    local_irq_restore(flags);
-    run_process_issue_queue();
-    return 0;
-}
-
-/*
- * Function : void to_schedule_list (struct Scsi_Host *host,
- * 	struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd)
- *
- * Purpose : takes a SCSI command which was just removed from the 
- *	issue queue, and deals with it by inserting it in the first
- *	free slot in the schedule list or by terminating it immediately.
- *
- * Inputs : 
- *	host - SCSI host adapter; hostdata - hostdata structure for 
- *	this adapter; cmd - a pointer to the command; should have 
- *	the host_scribble field initialized to point to a valid 
- *	
- * Side effects : 
- *      cmd is added to the per instance schedule list, with minor 
- *      twiddling done to the host specific fields of cmd.
- *
- */
-
-static __inline__ void
-to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
-    struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    Scsi_Cmnd *tmp = cmd->cmd;
-    unsigned long flags;
-    /* dsa start is negative, so subtraction is used */
-    volatile u32 *ncrcurrent;
-
-    int i;
-    NCR53c7x0_local_setup(host);
-#if 0
-    printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, 
-	virt_to_bus(hostdata->dsa), hostdata->dsa);
-#endif
-
-    local_irq_save(flags);
-    
-    /* 
-     * Work around race condition : if an interrupt fired and we 
-     * got disabled forget about this command.
-     */
-
-    if (hostdata->state == STATE_DISABLED) {
-	printk("scsi%d : driver disabled\n", host->host_no);
-	tmp->result = (DID_BAD_TARGET << 16);
-	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	hostdata->free = cmd;
-	tmp->scsi_done(tmp);
-	local_irq_restore(flags);
-	return;
-    }
-
-    for (i = host->can_queue, ncrcurrent = hostdata->schedule; 
-	i > 0  && ncrcurrent[0] != hostdata->NOP_insn;
-	--i, ncrcurrent += 2 /* JUMP instructions are two words */);
-
-    if (i > 0) {
-	++hostdata->busy[tmp->device->id][tmp->device->lun];
-	cmd->next = hostdata->running_list;
-	hostdata->running_list = cmd;
-
-	/* Restore this instruction to a NOP once the command starts */
-	cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / 
-	    sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent);
-	/* Replace the current jump operand.  */
-	ncrcurrent[1] =
-	    virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin -
-	    hostdata->E_dsa_code_template;
-	/* Replace the NOP instruction with a JUMP */
-	ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) |
-	    DBC_TCI_TRUE;
-    }  else {
-	printk ("scsi%d: no free slot\n", host->host_no);
-	disable(host);
-	tmp->result = (DID_ERROR << 16);
-	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	hostdata->free = cmd;
-	tmp->scsi_done(tmp);
-	local_irq_restore(flags);
-	return;
-    }
-
-    /* 
-     * If the NCR chip is in an idle state, start it running the scheduler
-     * immediately.  Otherwise, signal the chip to jump to schedule as 
-     * soon as it is idle.
-     */
-
-    if (hostdata->idle) {
-	hostdata->idle = 0;
-	hostdata->state = STATE_RUNNING;
-	NCR53c7x0_write32 (DSP_REG,  virt_to_bus ((void *)hostdata->schedule));
-	if (hostdata->options & OPTION_DEBUG_TRACE)
-	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-    } else {
-	NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
-    }
-
-    local_irq_restore(flags);
-}
-
-/*
- * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata 
- *	*hostdata, Scsi_Cmnd *cmd)
- *
- * Purpose : decide if we can pass the given SCSI command on to the 
- *	device in question or not.
- *  
- * Returns : non-zero when we're busy, 0 when we aren't.
- */
-
-static __inline__ int
-busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, 
-    Scsi_Cmnd *cmd) {
-    /* FIXME : in the future, this needs to accommodate SCSI-II tagged
-       queuing, and we may be able to play with fairness here a bit.
-     */
-    return hostdata->busy[cmd->device->id][cmd->device->lun];
-}
-
-/*
- * Function : process_issue_queue (void)
- *
- * Purpose : transfer commands from the issue queue to NCR start queue 
- *	of each NCR53c7/8xx in the system, avoiding kernel stack 
- *	overflows when the scsi_done() function is invoked recursively.
- * 
- * NOTE : process_issue_queue exits with interrupts *disabled*, so the 
- *	caller must reenable them if it desires.
- * 
- * NOTE : process_issue_queue should be called from both 
- *	NCR53c7x0_queue_command() and from the interrupt handler 
- *	after command completion in case NCR53c7x0_queue_command()
- * 	isn't invoked again but we've freed up resources that are
- *	needed.
- */
-
-static void 
-process_issue_queue (unsigned long flags) {
-    Scsi_Cmnd *tmp, *prev;
-    struct Scsi_Host *host;
-    struct NCR53c7x0_hostdata *hostdata;
-    int done;
-
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set process_issue_queue_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     */
-
-    do {
-	local_irq_disable(); /* Freeze request queues */
-	done = 1;
-	for (host = first_host; host && host->hostt == the_template;
-	    host = host->next) {
-	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-	    local_irq_disable();
-	    if (hostdata->issue_queue) {
-	    	if (hostdata->state == STATE_DISABLED) {
-		    tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-		    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
-		    tmp->result = (DID_BAD_TARGET << 16);
-		    if (tmp->host_scribble) {
-			((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = 
-			    hostdata->free;
-			hostdata->free = 
-			    (struct NCR53c7x0_cmd *)tmp->host_scribble;
-			tmp->host_scribble = NULL;
-		    }
-		    tmp->scsi_done (tmp);
-		    done = 0;
-		} else 
-		    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
-			prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
-			tmp->SCp.ptr) 
-			if (!tmp->host_scribble || 
-			    !busyp (host, hostdata, tmp)) {
-				if (prev)
-				    prev->SCp.ptr = tmp->SCp.ptr;
-				else
-				    hostdata->issue_queue = (Scsi_Cmnd *) 
-					tmp->SCp.ptr;
-			    tmp->SCp.ptr = NULL;
-			    if (tmp->host_scribble) {
-				if (hostdata->options & OPTION_DEBUG_QUEUES) 
-				    printk ("scsi%d : moving command for target %d lun %d to start list\n",
-					host->host_no, tmp->device->id, tmp->device->lun);
-		
-
-			    	to_schedule_list (host, hostdata, 
-				    (struct NCR53c7x0_cmd *)
-				    tmp->host_scribble);
-			    } else {
-				if (((tmp->result & 0xff) == 0xff) ||
-			    	    ((tmp->result & 0xff00) == 0xff00)) {
-				    printk ("scsi%d : danger Will Robinson!\n",
-					host->host_no);
-				    tmp->result = DID_ERROR << 16;
-				    disable (host);
-				}
-				tmp->scsi_done(tmp);
-			    }
-			    done = 0;
-			} /* if target/lun is not busy */
-	    } /* if hostdata->issue_queue */
-	    if (!done)
-		local_irq_restore(flags);
-    	} /* for host */
-    } while (!done);
-    process_issue_queue_running = 0;
-}
-
-/*
- * Function : static void intr_scsi (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle all SCSI interrupts, indicated by the setting 
- * 	of the SIP bit in the ISTAT register.
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void 
-intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    unsigned char sstat0_sist0, sist1, 		/* Registers */
-	    fatal; 				/* Did a fatal interrupt 
-						   occur ? */
-   
-    NCR53c7x0_local_setup(host);
-
-    fatal = 0;
-
-    sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG);
-    sist1 = 0;
-
-    if (hostdata->options & OPTION_DEBUG_INTR) 
-	printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no,
-	    sstat0_sist0, sist1);
-
-    /* 250ms selection timeout */
-    if (sstat0_sist0 & SSTAT0_700_STO) {
-	fatal = 1;
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    printk ("scsi%d : Selection Timeout\n", host->host_no);
-    	    if (cmd) {
-    	    	printk("scsi%d : target %d, lun %d, command ",
-		    host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-    	    	__scsi_print_command (cmd->cmd->cmnd);
-		printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no,
-		    NCR53c7x0_read32(DSP_REG),
-		    bus_to_virt(NCR53c7x0_read32(DSP_REG)));
-    	    } else {
-    	    	printk("scsi%d : no command\n", host->host_no);
-    	    }
-    	}
-/*
- * XXX - question : how do we want to handle the Illegal Instruction
- * 	interrupt, which may occur before or after the Selection Timeout
- * 	interrupt?
- */
-
-	if (1) {
-	    hostdata->idle = 1;
-	    hostdata->expecting_sto = 0;
-
-	    if (hostdata->test_running) {
-		hostdata->test_running = 0;
-		hostdata->test_completed = 3;
-	    } else if (cmd) {
-		abnormal_finished(cmd, DID_BAD_TARGET << 16);
-	    }
-#if 0	    
-	    hostdata->intrs = 0;
-#endif
-	}
-    } 
-
-/*
- * FIXME : in theory, we can also get a UDC when a STO occurs.
- */
-    if (sstat0_sist0 & SSTAT0_UDC) {
-	fatal = 1;
-	if (cmd) {
-	    printk("scsi%d : target %d lun %d unexpected disconnect\n",
-		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-	    print_lots (host);
-	    abnormal_finished(cmd, DID_ERROR << 16);
-	} else 
-	     printk("scsi%d : unexpected disconnect (no command)\n",
-		host->host_no);
-
-	hostdata->dsp = (u32 *) hostdata->schedule;
-	hostdata->dsp_changed = 1;
-    }
-
-    /* SCSI PARITY error */
-    if (sstat0_sist0 & SSTAT0_PAR) {
-	fatal = 1;
-	if (cmd && cmd->cmd) {
-	    printk("scsi%d : target %d lun %d parity error.\n",
-		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
-	    abnormal_finished (cmd, DID_PARITY << 16); 
-	} else
-	    printk("scsi%d : parity error\n", host->host_no);
-	/* Should send message out, parity error */
-
-	/* XXX - Reduce synchronous transfer rate! */
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1; 
-    /* SCSI GROSS error */
-    } 
-
-    if (sstat0_sist0 & SSTAT0_SGE) {
-	fatal = 1;
-	printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no,
-					(unsigned int)hostdata->saved2_dsa);
-	print_lots (host);
-	
-	/* 
-         * A SCSI gross error may occur when we have 
-	 *
-	 * - A synchronous offset which causes the SCSI FIFO to be overwritten.
-	 *
-	 * - A REQ which causes the maximum synchronous offset programmed in 
-	 * 	the SXFER register to be exceeded.
-	 *
-	 * - A phase change with an outstanding synchronous offset.
-	 *
-	 * - Residual data in the synchronous data FIFO, with a transfer
-	 *	other than a synchronous receive is started.$#
-	 */
-		
-
-	/* XXX Should deduce synchronous transfer rate! */
-	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-    	    sizeof(u32);
-	hostdata->dsp_changed = 1;
-    /* Phase mismatch */
-    } 
-
-    if (sstat0_sist0 & SSTAT0_MA) {
-	fatal = 1;
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk ("scsi%d : SSTAT0_MA\n", host->host_no);
-	intr_phase_mismatch (host, cmd);
-    }
-
-#if 0
-    if (sstat0_sist0 & SIST0_800_RSL) 
-	printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no);
-#endif
-    
-/*
- * If a fatal SCSI interrupt occurs, we must insure that the DMA and
- * SCSI FIFOs were flushed.
- */
-
-    if (fatal) {
-	if (!hostdata->dstat_valid) {
-	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	    hostdata->dstat_valid = 1;
-	}
-
-	if (!(hostdata->dstat & DSTAT_DFE)) {
-	  printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-	  /*
-	   * Really need to check this code for 710  RGH.
-	   * Havn't seen any problems, but maybe we should FLUSH before
-	   * clearing sometimes.
-	   */
-          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
-		;
-	  hostdata->dstat |= DSTAT_DFE;
-    	}
-    }
-}
-
-#ifdef CYCLIC_TRACE
-
-/*
- * The following implements a cyclic log of instructions executed, if you turn
- * TRACE on.  It will also print the log for you.  Very useful when debugging
- * 53c710 support, possibly not really needed any more.
- */
-
-u32 insn_log[4096];
-u32 insn_log_index = 0;
-
-void log1 (u32 i)
-{
-	insn_log[insn_log_index++] = i;
-	if (insn_log_index == 4096)
-		insn_log_index = 0;
-}
-
-void log_insn (u32 *ip)
-{
-	log1 ((u32)ip);
-	log1 (*ip);
-	log1 (*(ip+1));
-	if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)
-		log1 (*(ip+2));
-}
-
-void dump_log(void)
-{
-	int cnt = 0;
-	int i = insn_log_index;
-	int size;
-	struct Scsi_Host *host = first_host;
-
-	while (cnt < 4096) {
-		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
-		if (++i == 4096)
-			i = 0;
-		cnt++;
-		if (((insn_log[i]  >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) 
-			size = 3;
-		else
-			size = 2;
-		while (size--) {
-			printk ("%08x ", insn_log[i]);
-			if (++i == 4096)
-				i = 0;
-			cnt++;
-		}
-		printk ("\n");
-	}
-}
-#endif
-
-
-/*
- * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
- *
- * Purpose : Scan command queue for specified host, looking for completed
- *           commands.
- * 
- * Inputs : Scsi_Host pointer.
- *
- * 	This is called from the interrupt handler, when a simulated INTFLY
- * 	interrupt occurs.
- */
-
-static void
-NCR53c7x0_intfly (struct Scsi_Host *host)
-{
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
-    struct NCR53c7x0_cmd *cmd,			/* command which halted */
-	**cmd_prev_ptr;
-    unsigned long flags;				
-    char search_found = 0;			/* Got at least one ? */
-
-    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    if (hostdata->options & OPTION_DEBUG_INTR)
-    printk ("scsi%d : INTFLY\n", host->host_no); 
-
-    /*
-    * Traverse our list of running commands, and look
-    * for those with valid (non-0xff ff) status and message
-    * bytes encoded in the result which signify command
-    * completion.
-    */
-
-    local_irq_save(flags);
-restart:
-    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
-	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
-	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
-    	cmd = (struct NCR53c7x0_cmd *) cmd->next)
-    {
-	Scsi_Cmnd *tmp;
-
-	if (!cmd) {
-	    printk("scsi%d : very weird.\n", host->host_no);
-	    break;
-	}
-
-	if (!(tmp = cmd->cmd)) {
-	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
-		    host->host_no);
-	    continue;
-	}
-	/* Copy the result over now; may not be complete,
-	 * but subsequent tests may as well be done on
-	 * cached memory.
-	 */
-	tmp->result = cmd->result;
-
-	if (((tmp->result & 0xff) == 0xff) ||
-			    ((tmp->result & 0xff00) == 0xff00))
-	    continue;
-
-	search_found = 1;
-
-	if (cmd->bounce.len)
-	    memcpy ((void *)cmd->bounce.addr,
-				(void *)cmd->bounce.buf, cmd->bounce.len);
-
-	/* Important - remove from list _before_ done is called */
-	if (cmd_prev_ptr)
-	    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
-
-	--hostdata->busy[tmp->device->id][tmp->device->lun];
-	cmd->next = hostdata->free;
-	hostdata->free = cmd;
-
-	tmp->host_scribble = NULL;
-
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
-		  host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result);
-	    __scsi_print_command (tmp->cmnd);
-	}
-
-	tmp->scsi_done(tmp);
-	goto restart;
-    }
-    local_irq_restore(flags);
-
-    if (!search_found)  {
-	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
-			    host->host_no);
-    } else {
-	run_process_issue_queue();
-    }
-    return;
-}
-
-/*
- * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id)
- *
- * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
- *	the same IRQ line.  
- * 
- * Inputs : Since we're using the IRQF_DISABLED interrupt handler
- *	semantics, irq indicates the interrupt which invoked 
- *	this handler.  
- *
- * On the 710 we simualte an INTFLY with a script interrupt, and the
- * script interrupt handler will call back to this function.
- */
-
-static irqreturn_t
-NCR53c7x0_intr (int irq, void *dev_id)
-{
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host;			/* Host we are looking at */
-    unsigned char istat; 			/* Values of interrupt regs */
-    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
-    struct NCR53c7x0_cmd *cmd;			/* command which halted */
-    u32 *dsa;					/* DSA */
-    int handled = 0;
-
-#ifdef NCR_DEBUG
-    char buf[80];				/* Debugging sprintf buffer */
-    size_t buflen;				/* Length of same */
-#endif
-
-    host     = (struct Scsi_Host *)dev_id;
-    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Only read istat once per loop, since reading it again will unstack
-     * interrupts
-     */
-
-    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
-	handled = 1;
-	hostdata->dsp_changed = 0;
-	hostdata->dstat_valid = 0;
-    	hostdata->state = STATE_HALTED;
-
-	if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
-	    printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
-
-	/*
-	 * NCR53c700 and NCR53c700-66 change the current SCSI
-	 * process, hostdata->ncrcurrent, in the Linux driver so
-	 * cmd = hostdata->ncrcurrent.
-	 *
-	 * With other chips, we must look through the commands
-	 * executing and find the command structure which 
-	 * corresponds to the DSA register.
-	 */
-
-	if (hostdata->options & OPTION_700) {
-	    cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
-	} else {
-	    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-	    for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
-		cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
-		    cmd = (struct NCR53c7x0_cmd *)(cmd->next))
-		;
-	}
-	if (hostdata->options & OPTION_DEBUG_INTR) {
-	    if (cmd) {
-		printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
-		    host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id,
-		    (int) cmd->cmd->device->lun);
-		__scsi_print_command (cmd->cmd->cmnd);
-	    } else {
-		printk("scsi%d : no active command\n", host->host_no);
-	    }
-	}
-	
-	if (istat & ISTAT_SIP) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ISTAT_SIP\n", host->host_no);
-	    intr_scsi (host, cmd);
-	}
-	
-	if (istat & ISTAT_DIP) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ISTAT_DIP\n", host->host_no);
-	    intr_dma (host, cmd);
-	}
-	
-	if (!hostdata->dstat_valid) {
-	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	    hostdata->dstat_valid = 1;
-	}
-	
-	if (!(hostdata->dstat & DSTAT_DFE)) {
-	    printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-	    /* Really need to check this out for 710 RGH */
-	    NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-	    while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
-		;
-	    hostdata->dstat |= DSTAT_DFE;
-	}
-
-	if (!hostdata->idle && hostdata->state == STATE_HALTED) {
-	    if (!hostdata->dsp_changed)
-		hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
-#if 0
-	    printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
-		host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
-#endif
-		
-	    hostdata->state = STATE_RUNNING;
-	    NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
-	    if (hostdata->options & OPTION_DEBUG_TRACE) {
-#ifdef CYCLIC_TRACE
-		log_insn (hostdata->dsp);
-#else
-	    	print_insn (host, hostdata->dsp, "t ", 1);
-#endif
-		NCR53c7x0_write8 (DCNTL_REG,
-			hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
-	    }
-	}
-    }
-    return IRQ_HANDLED;
-}
-
-
-/* 
- * Function : static int abort_connected (struct Scsi_Host *host)
- *
- * Purpose : Assuming that the NCR SCSI processor is currently 
- * 	halted, break the currently established nexus.  Clean
- *	up of the NCR53c7x0_cmd and Scsi_Cmnd structures should
- *	be done on receipt of the abort interrupt.
- *
- * Inputs : host - SCSI host
- *
- */
-
-static int 
-abort_connected (struct Scsi_Host *host) {
-#ifdef NEW_ABORT
-    NCR53c7x0_local_declare();
-#endif
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-/* FIXME : this probably should change for production kernels; at the 
-   least, counter should move to a per-host structure. */
-    static int counter = 5;
-#ifdef NEW_ABORT
-    int sstat, phase, offset;
-    u32 *script;
-    NCR53c7x0_local_setup(host);
-#endif
-
-    if (--counter <= 0) {
-	disable(host);
-	return 0;
-    }
-
-    printk ("scsi%d : DANGER : abort_connected() called \n",
-	host->host_no);
-
-#ifdef NEW_ABORT
-
-/*
- * New strategy : Rather than using a generic abort routine,
- * we'll specifically try to source or sink the appropriate
- * amount of data for the phase we're currently in (taking into 
- * account the current synchronous offset) 
- */
-
-    sstat = NCR53c8x0_read8 (SSTAT2_REG);
-    offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
-    phase = sstat & SSTAT2_PHASE_MASK;
-
-/*
- * SET ATN
- * MOVE source_or_sink, WHEN CURRENT PHASE 
- * < repeat for each outstanding byte >
- * JUMP send_abort_message
- */
-
-    script = hostdata->abort_script = kmalloc (
-	8  /* instruction size */ * (
-	    1 /* set ATN */ +
-	    (!offset ? 1 : offset) /* One transfer per outstanding byte */ +
-	    1 /* send abort message */),
-	GFP_ATOMIC);
-
-
-#else /* def NEW_ABORT */
-    hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
-	    sizeof(u32);
-#endif /* def NEW_ABORT */
-    hostdata->dsp_changed = 1;
-
-/* XXX - need to flag the command as aborted after the abort_connected
- 	 code runs 
- */
-    return 0;
-}
-
-/*
- * Function : static int datapath_residual (Scsi_Host *host)
- *
- * Purpose : return residual data count of what's in the chip.
- *
- * Inputs : host - SCSI host
- */
-
-static int
-datapath_residual (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    int count, synchronous, sstat;
-    unsigned int ddir;
-
-    NCR53c7x0_local_setup(host);
-    /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */
-    count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
-	(NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
-    synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK;
-    /* COMPAT : DDIR is elsewhere on non-'8xx chips. */
-    ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
-
-    if (ddir) {
-    /* Receive */
-	if (synchronous) 
-	    count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
-	else
-	    if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF)
-		++count;
-    } else {
-    /* Send */
-	sstat = NCR53c7x0_read8 (SSTAT1_REG);
-	if (sstat & SSTAT1_OLF)
-	    ++count;
-	if (synchronous && (sstat & SSTAT1_ORF))
-	    ++count;
-    }
-    return count;
-}
-
-/* 
- * Function : static const char * sbcl_to_phase (int sbcl)_
- *
- * Purpose : Convert SBCL register to user-parsable phase representation
- *
- * Inputs : sbcl - value of sbcl register
- */
-
-
-static const char *
-sbcl_to_phase (int sbcl) {
-    switch (sbcl & SBCL_PHASE_MASK) {
-    case SBCL_PHASE_DATAIN:
-	return "DATAIN";
-    case SBCL_PHASE_DATAOUT:
-	return "DATAOUT";
-    case SBCL_PHASE_MSGIN:
-	return "MSGIN";
-    case SBCL_PHASE_MSGOUT:
-	return "MSGOUT";
-    case SBCL_PHASE_CMDOUT:
-	return "CMDOUT";
-    case SBCL_PHASE_STATIN:
-	return "STATUSIN";
-    default:
-	return "unknown";
-    }
-}
-
-/* 
- * Function : static const char * sstat2_to_phase (int sstat)_
- *
- * Purpose : Convert SSTAT2 register to user-parsable phase representation
- *
- * Inputs : sstat - value of sstat register
- */
-
-
-static const char *
-sstat2_to_phase (int sstat) {
-    switch (sstat & SSTAT2_PHASE_MASK) {
-    case SSTAT2_PHASE_DATAIN:
-	return "DATAIN";
-    case SSTAT2_PHASE_DATAOUT:
-	return "DATAOUT";
-    case SSTAT2_PHASE_MSGIN:
-	return "MSGIN";
-    case SSTAT2_PHASE_MSGOUT:
-	return "MSGOUT";
-    case SSTAT2_PHASE_CMDOUT:
-	return "CMDOUT";
-    case SSTAT2_PHASE_STATIN:
-	return "STATUSIN";
-    default:
-	return "unknown";
-    }
-}
-
-/* 
- * Function : static void intr_phase_mismatch (struct Scsi_Host *host, 
- *	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : Handle phase mismatch interrupts
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- *
- * Side effects : The abort_connected() routine is called or the NCR chip 
- *	is restarted, jumping to the command_complete entry point, or 
- *	patching the address and transfer count of the current instruction 
- *	and calling the msg_in entry point as appropriate.
- */
-
-static void 
-intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    u32 dbc_dcmd, *dsp, *dsp_next;
-    unsigned char dcmd, sbcl;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata[0];
-    int residual;
-    enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = 
-	ACTION_ABORT_PRINT;
-    const char *where = NULL;
-
-    NCR53c7x0_local_setup(host);
-
-    /*
-     * Corrective action is based on where in the SCSI SCRIPT(tm) the error 
-     * occurred, as well as which SCSI phase we are currently in.
-     */
-    dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG));
-
-    /* 
-     * Fetch the current instruction, and remove the operands for easier 
-     * interpretation.
-     */
-    dbc_dcmd = NCR53c7x0_read32(DBC_REG);
-    dcmd = (dbc_dcmd & 0xff000000) >> 24;
-    /*
-     * Like other processors, the NCR adjusts the instruction pointer before
-     * instruction decode.  Set the DSP address back to what it should
-     * be for this instruction based on its size (2 or 3 32 bit words).
-     */
-    dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
-
-
-    /*
-     * Read new SCSI phase from the SBCL lines.  Since all of our code uses 
-     * a WHEN conditional instead of an IF conditional, we don't need to 
-     * wait for a new REQ.
-     */
-    sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK;
-
-    if (!cmd) {
-	action = ACTION_ABORT_PRINT;
-	where = "no current command";
-    /*
-     * The way my SCSI SCRIPTS(tm) are architected, recoverable phase
-     * mismatches should only occur where we're doing a multi-byte  
-     * BMI instruction.  Specifically, this means 
-     *
-     *  - select messages (a SCSI-I target may ignore additional messages
-     * 		after the IDENTIFY; any target may reject a SDTR or WDTR)
-     *
-     *  - command out (targets may send a message to signal an error 
-     * 		condition, or go into STATUSIN after they've decided 
-     *		they don't like the command.
-     *
-     *	- reply_message (targets may reject a multi-byte message in the 
-     *		middle)
-     *
-     * 	- data transfer routines (command completion with buffer space
-     *		left, disconnect message, or error message)
-     */
-    } else if (((dsp >= cmd->data_transfer_start && 
-	dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) {
-	if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT|
-		DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI|
-		DCMD_BMI_OP_MOVE_I)) {
-	    residual = datapath_residual (host);
-	    if (hostdata->options & OPTION_DEBUG_DISCONNECT)
-	    	printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", 
-		    host->host_no, residual);
-
-	    /*
-	     * The first instruction is a CALL to the alternate handler for 
-	     * this data transfer phase, so we can do calls to 
-	     * munge_msg_restart as we would if control were passed 
-	     * from normal dynamic code.
-	     */
-	    if (dsp != cmd->residual + 2) {
-		cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL |
-			((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | 
-		    DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
-		cmd->residual[1] = virt_to_bus(hostdata->script)
-		    + ((dcmd & DCMD_BMI_IO)
-		       ? hostdata->E_other_in : hostdata->E_other_out);
-	    }
-
-	    /*
-	     * The second instruction is the a data transfer block
-	     * move instruction, reflecting the pointer and count at the 
-	     * time of the phase mismatch.
-	     */
-	    cmd->residual[2] = dbc_dcmd + residual;
-	    cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual;
-
-	    /*
-	     * The third and final instruction is a jump to the instruction
-	     * which follows the instruction which had to be 'split'
-	     */
-	    if (dsp != cmd->residual + 2) {
-		cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) 
-		    << 24) | DBC_TCI_TRUE;
-		cmd->residual[5] = virt_to_bus(dsp_next);
-	    }
-
-	    /*
-	     * For the sake of simplicity, transfer control to the 
-	     * conditional CALL at the start of the residual buffer.
-	     */
-	    hostdata->dsp = cmd->residual;
-	    hostdata->dsp_changed = 1;
-	    action = ACTION_CONTINUE;
-	} else {
-	    where = "non-BMI dynamic DSA code";
-	    action = ACTION_ABORT_PRINT;
-	}
-    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) {
-	/* RGH 290697:  Added +2 above, to compensate for the script
-	 * instruction which disables the selection timer. */
-	/* Release ATN */
-	NCR53c7x0_write8 (SOCL_REG, 0);
-	switch (sbcl) {
-    /* 
-     * Some devices (SQ555 come to mind) grab the IDENTIFY message
-     * sent on selection, and decide to go into COMMAND OUT phase
-     * rather than accepting the rest of the messages or rejecting
-     * them.  Handle these devices gracefully.
-     */
-	case SBCL_PHASE_CMDOUT:
-	    hostdata->dsp = dsp + 2 /* two _words_ */;
-	    hostdata->dsp_changed = 1;
-	    printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", 
-		host->host_no, cmd->cmd->device->id);
-	    cmd->flags &= ~CMD_FLAG_SDTR;
-	    action = ACTION_CONTINUE;
-	    break;
-	case SBCL_PHASE_MSGIN:
-	    hostdata->dsp = hostdata->script + hostdata->E_msg_in / 
-		sizeof(u32);
-	    hostdata->dsp_changed = 1;
-	    action = ACTION_CONTINUE;
-	    break;
-	default:
-	    where="select message out";
-	    action = ACTION_ABORT_PRINT;
-	}
-    /*
-     * Some SCSI devices will interpret a command as they read the bytes
-     * off the SCSI bus, and may decide that the command is Bogus before 
-     * they've read the entire command off the bus.
-     */
-    } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof 
-	(u32)) {
-	hostdata->dsp = hostdata->script + hostdata->E_data_transfer /
-	    sizeof (u32);
-	hostdata->dsp_changed = 1;
-	action = ACTION_CONTINUE;
-    /* FIXME : we need to handle message reject, etc. within msg_respond. */
-#ifdef notyet
-    } else if (dsp == hostdata->script + hostdata->E_reply_message) {
-	switch (sbcl) {
-    /* Any other phase mismatches abort the currently executing command.  */
-#endif
-    } else {
-	where = "unknown location";
-	action = ACTION_ABORT_PRINT;
-    }
-
-    /* Flush DMA FIFO */
-    if (!hostdata->dstat_valid) {
-	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	hostdata->dstat_valid = 1;
-    }
-    if (!(hostdata->dstat & DSTAT_DFE)) {
-      /* Really need to check this out for 710 RGH */
-      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
-      hostdata->dstat |= DSTAT_DFE;
-    }
-
-    switch (action) {
-    case ACTION_ABORT_PRINT:
-	printk("scsi%d : %s : unexpected phase %s.\n",
-	     host->host_no, where ? where : "unknown location", 
-	     sbcl_to_phase(sbcl));
-	print_lots (host);
-    /* Fall through to ACTION_ABORT */
-    case ACTION_ABORT:
-	abort_connected (host);
-	break;
-    case ACTION_CONTINUE:
-	break;
-    }
-
-#if 0
-    if (hostdata->dsp_changed) {
-	printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp);
-	print_insn (host, hostdata->dsp, "", 1);
-    }
-#endif
-}
-
-/*
- * Function : static void intr_bf (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle BUS FAULT interrupts 
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void
-intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    u32 *dsp,
-	*next_dsp,		/* Current dsp */
-    	*dsa,
-	dbc_dcmd;		/* DCMD (high eight bits) + DBC */
-    char *reason = NULL;
-    /* Default behavior is for a silent error, with a retry until we've
-       exhausted retries. */
-    enum {MAYBE, ALWAYS, NEVER} retry = MAYBE;
-    int report = 0;
-    NCR53c7x0_local_setup(host);
-
-    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
-    next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG));
-    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
-/* FIXME - check chip type  */
-    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
-
-    /*
-     * Bus faults can be caused by either a Bad Address or 
-     * Target Abort. We should check the Received Target Abort
-     * bit of the PCI status register and Master Abort Bit.
-     *
-     * 	- Master Abort bit indicates that no device claimed
-     *		the address with DEVSEL within five clocks
-     *
-     *	- Target Abort bit indicates that a target claimed it,
-     *		but changed its mind once it saw the byte enables.
-     *
-     */
-
-    /* 53c710, not PCI system */
-    report = 1;
-    reason = "Unknown";
-
-#ifndef notyet
-    report = 1;
-#endif
-    if (report && reason)
-    {
-	printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n",
-	     host->host_no, reason ? reason : "unknown");
-	print_lots (host);
-    }
-
-#ifndef notyet
-    retry = NEVER;
-#endif
-
-    /* 
-     * TODO : we should attempt to recover from any spurious bus 
-     * faults.  After X retries, we should figure that things are 
-     * sufficiently wedged, and call NCR53c7xx_reset.
-     *
-     * This code should only get executed once we've decided that we 
-     * cannot retry.
-     */
-
-    if (retry == NEVER) {
-    	printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n");
-    	FATAL (host);
-    }
-}
-
-/*
- * Function : static void intr_dma (struct Scsi_Host *host, 
- * 	struct NCR53c7x0_cmd *cmd)
- *
- * Purpose : handle all DMA interrupts, indicated by the setting 
- * 	of the DIP bit in the ISTAT register.
- *
- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
- * 	may be NULL.
- */
-
-static void 
-intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned char dstat;	/* DSTAT */	
-    u32 *dsp,
-	*next_dsp,		/* Current dsp */
-    	*dsa,
-	dbc_dcmd;		/* DCMD (high eight bits) + DBC */
-    int tmp;
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-
-    if (!hostdata->dstat_valid) {
-	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-	hostdata->dstat_valid = 1;
-    }
-    
-    dstat = hostdata->dstat;
-    
-    if (hostdata->options & OPTION_DEBUG_INTR)
-	printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat);
-
-    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
-    next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG));
-    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
-/* XXX - check chip type */
-    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-
-    /*
-     * DSTAT_ABRT is the aborted interrupt.  This is set whenever the 
-     * SCSI chip is aborted.  
-     * 
-     * With NCR53c700 and NCR53c700-66 style chips, we should only 
-     * get this when the chip is currently running the accept 
-     * reselect/select code and we have set the abort bit in the 
-     * ISTAT register.
-     *
-     */
-    
-    if (dstat & DSTAT_ABRT) {
-#if 0
-	/* XXX - add code here to deal with normal abort */
-	if ((hostdata->options & OPTION_700) && (hostdata->state ==
-	    STATE_ABORTING)) {
-	} else 
-#endif
-	{
-	    printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" 
-		   "         ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "s ", 1);
-	    FATAL (host);
-	}
-    }
-
-    /*
-     * DSTAT_SSI is the single step interrupt.  Should be generated 
-     * whenever we have single stepped or are tracing.
-     */
-
-    if (dstat & DSTAT_SSI) {
-	if (hostdata->options & OPTION_DEBUG_TRACE) {
-	    /* Don't print instr. until we write DSP at end of intr function */
-	} else if (hostdata->options & OPTION_DEBUG_SINGLE) {
-	    print_insn (host, dsp, "s ", 0);
-	    local_irq_save(flags);
-/* XXX - should we do this, or can we get away with writing dsp? */
-
-	    NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & 
-    	    	~DCNTL_SSM) | DCNTL_STD);
-	    local_irq_restore(flags);
-	} else {
-	    printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
-		   "         ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT "         mail drew@PoohSticks.ORG\n");
-    	    FATAL (host);
-    	}
-    }
-
-    /*
-     * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name 
-     * is different) is generated whenever an illegal instruction is 
-     * encountered.  
-     * 
-     * XXX - we may want to emulate INTFLY here, so we can use 
-     *    the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810  
-     *	  chips.
-     */
-
-    if (dstat & DSTAT_OPC) {
-    /* 
-     * Ascertain if this IID interrupts occurred before or after a STO 
-     * interrupt.  Since the interrupt handling code now leaves 
-     * DSP unmodified until _after_ all stacked interrupts have been
-     * processed, reading the DSP returns the original DSP register.
-     * This means that if dsp lies between the select code, and 
-     * message out following the selection code (where the IID interrupt
-     * would have to have occurred by due to the implicit wait for REQ),
-     * we have an IID interrupt resulting from a STO condition and 
-     * can ignore it.
-     */
-
-	if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) &&
-	    (dsp <= (hostdata->script + hostdata->E_select_msgout / 
-    	    sizeof(u32) + 8))) || (hostdata->test_running == 2)) {
-	    if (hostdata->options & OPTION_DEBUG_INTR) 
-		printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n",
-		    host->host_no);
-	    if (hostdata->expecting_iid) {
-		hostdata->expecting_iid = 0;
-		hostdata->idle = 1;
-		if (hostdata->test_running == 2) {
-		    hostdata->test_running = 0;
-		    hostdata->test_completed = 3;
-		} else if (cmd) 
-			abnormal_finished (cmd, DID_BAD_TARGET << 16);
-	    } else {
-		hostdata->expecting_sto = 1;
-	    }
-    /*
-     * We can't guarantee we'll be able to execute the WAIT DISCONNECT
-     * instruction within the 3.4us of bus free and arbitration delay
-     * that a target can RESELECT in and assert REQ after we've dropped
-     * ACK.  If this happens, we'll get an illegal instruction interrupt.
-     * Doing away with the WAIT DISCONNECT instructions broke everything,
-     * so instead I'll settle for moving one WAIT DISCONNECT a few 
-     * instructions closer to the CLEAR ACK before it to minimize the
-     * chances of this happening, and handle it if it occurs anyway.
-     *
-     * Simply continue with what we were doing, and control should
-     * be transferred to the schedule routine which will ultimately
-     * pass control onto the reselection or selection (not yet)
-     * code.
-     */
-	} else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) &
-	    SBCL_REQ)) {
-	    if (!(hostdata->options & OPTION_NO_PRINT_RACE))
-	    {
-		printk("scsi%d: REQ before WAIT DISCONNECT IID\n", 
-		    host->host_no);
-		hostdata->options |= OPTION_NO_PRINT_RACE;
-	    }
-	} else {
-	    printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no);
-	    print_lots (host);
-	    printk(KERN_ALERT "         mail Richard@sleepie.demon.co.uk with ALL\n"
-		              "         boot messages and diagnostic output\n");
-    	    FATAL (host);
-	}
-    }
-
-    /* 
-     * DSTAT_BF are bus fault errors.  DSTAT_800_BF is valid for 710 also.
-     */
-    
-    if (dstat & DSTAT_800_BF) {
-	intr_bf (host, cmd);
-    }
-	
-
-    /* 
-     * DSTAT_SIR interrupts are generated by the execution of 
-     * the INT instruction.  Since the exact values available 
-     * are determined entirely by the SCSI script running, 
-     * and are local to a particular script, a unique handler
-     * is called for each script.
-     */
-
-    if (dstat & DSTAT_SIR) {
-	if (hostdata->options & OPTION_DEBUG_INTR)
-	    printk ("scsi%d : DSTAT_SIR\n", host->host_no);
-	switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) {
-	case SPECIFIC_INT_NOTHING:
-	case SPECIFIC_INT_RESTART:
-	    break;
-	case SPECIFIC_INT_ABORT:
-	    abort_connected(host);
-	    break;
-	case SPECIFIC_INT_PANIC:
-	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT "          dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
-    	    FATAL (host);
-	    break;
-	case SPECIFIC_INT_BREAK:
-	    intr_break (host, cmd);
-	    break;
-	default:
-	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
-	    print_insn (host, dsp, KERN_ALERT "", 1);
-	    printk(KERN_ALERT"          dstat_sir_intr() returned unknown value %d\n", 
-		tmp);
-    	    FATAL (host);
-	}
-    } 
-}
-
-/*
- * Function : static int print_insn (struct Scsi_Host *host, 
- * 	u32 *insn, int kernel)
- *
- * Purpose : print numeric representation of the instruction pointed
- * 	to by insn to the debugging or kernel message buffer
- *	as appropriate.  
- *
- * 	If desired, a user level program can interpret this 
- * 	information.
- *
- * Inputs : host, insn - host, pointer to instruction, prefix - 
- *	string to prepend, kernel - use printk instead of debugging buffer.
- *
- * Returns : size, in u32s, of instruction printed.
- */
-
-/*
- * FIXME: should change kernel parameter so that it takes an ENUM
- * 	specifying severity - either KERN_ALERT or KERN_PANIC so
- *	all panic messages are output with the same severity.
- */
-
-static int 
-print_insn (struct Scsi_Host *host, const u32 *insn, 
-    const char *prefix, int kernel) {
-    char buf[160], 		/* Temporary buffer and pointer.  ICKY 
-				   arbitrary length.  */
-
-		
-	*tmp;			
-    unsigned char dcmd;		/* dcmd register for *insn */
-    int size;
-
-    /* 
-     * Check to see if the instruction pointer is not bogus before 
-     * indirecting through it; avoiding red-zone at start of 
-     * memory.
-     *
-     * FIXME: icky magic needs to happen here on non-intel boxes which
-     * don't have kernel memory mapped in like this.  Might be reasonable
-     * to use vverify()?
-     */
-
-    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
-	virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
-	((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
-	virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
-	size = 0;
-	sprintf (buf, "%s%p: address out of range\n",
-	    prefix, insn);
-    } else {
-/* 
- * FIXME : (void *) cast in virt_to_bus should be unnecessary, because
- * 	it should take const void * as argument.
- */
-#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
-	sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", 
-	    (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,  
-	    insn[0], insn[1], bus_to_virt (insn[1]));
-#else
-	/* Remove virtual addresses to reduce output, as they are the same */
-	sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", 
-	    (prefix ? prefix : ""), (u32)insn, ((u32)insn -
-		(u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, 
-	    insn[0], insn[1]);
-#endif
-	tmp = buf + strlen(buf);
-	if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  {
-#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
-	    sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], 
-		bus_to_virt(insn[2]));
-#else
-	    /* Remove virtual addr to reduce output, as it is the same */
-	    sprintf (tmp, " 0x%08x\n", insn[2]);
-#endif
-	    size = 3;
-	} else {
-	    sprintf (tmp, "\n");
-	    size = 2;
-	}
-    }
-
-    if (kernel) 
-	printk ("%s", buf);
-#ifdef NCR_DEBUG
-    else {
-	size_t len = strlen(buf);
-	debugger_kernel_write(host, buf, len);
-    }
-#endif
-    return size;
-}
-
-/*
- * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd)
- * 
- * Purpose : Abort an errant SCSI command, doing all necessary
- *	cleanup of the issue_queue, running_list, shared Linux/NCR
- *	dsa issue and reconnect queues.
- *
- * Inputs : cmd - command to abort, code - entire result field
- *
- * Returns : 0 on success, -1 on failure.
- */
-
-int 
-NCR53c7xx_abort (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
-	host->hostdata[0] : NULL;
-    unsigned long flags;
-    struct NCR53c7x0_cmd *curr, **prev;
-    Scsi_Cmnd *me, **last;
-#if 0
-    static long cache_pid = -1;
-#endif
-
-
-    if (!host) {
-	printk ("Bogus SCSI command pid %ld; no host structure\n",
-	    cmd->pid);
-	return SCSI_ABORT_ERROR;
-    } else if (!hostdata) {
-	printk ("Bogus SCSI host %d; no hostdata\n", host->host_no);
-	return SCSI_ABORT_ERROR;
-    }
-    NCR53c7x0_local_setup(host);
-
-/*
- * CHECK : I don't think that reading ISTAT will unstack any interrupts,
- *	since we need to write the INTF bit to clear it, and SCSI/DMA
- * 	interrupts don't clear until we read SSTAT/SIST and DSTAT registers.
- *	
- *	See that this is the case.  Appears to be correct on the 710, at least.
- *
- * I suspect that several of our failures may be coming from a new fatal
- * interrupt (possibly due to a phase mismatch) happening after we've left
- * the interrupt handler, but before the PIC has had the interrupt condition
- * cleared.
- */
-
-    if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) {
-	printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
-	    cmd->pid);
-	NCR53c7x0_intr (host->irq, NULL, NULL);
-	return SCSI_ABORT_BUSY;
-    }
-	
-    local_irq_save(flags);
-#if 0
-    if (cache_pid == cmd->pid) 
-	panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
-    else
-	cache_pid = cmd->pid;
-#endif
-	
-
-/*
- * The command could be hiding in the issue_queue.  This would be very
- * nice, as commands can't be moved from the high level driver's issue queue 
- * into the shared queue until an interrupt routine is serviced, and this
- * moving is atomic.  
- *
- * If this is the case, we don't have to worry about anything - we simply
- * pull the command out of the old queue, and call it aborted.
- */
-
-    for (me = (Scsi_Cmnd *) hostdata->issue_queue, 
-         last = (Scsi_Cmnd **) &(hostdata->issue_queue);
-	 me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr), 
-	 me = (Scsi_Cmnd *)me->SCp.ptr);
-
-    if (me) {
-	*last = (Scsi_Cmnd *) me->SCp.ptr;
-	if (me->host_scribble) {
-	    ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free;
-	    hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble;
-	    me->host_scribble = NULL;
-	}
-	cmd->result = DID_ABORT << 16;
-	cmd->scsi_done(cmd);
-	printk ("scsi%d : found command %ld in Linux issue queue\n", 
-	    host->host_no, me->pid);
-	local_irq_restore(flags);
-    	run_process_issue_queue();
-	return SCSI_ABORT_SUCCESS;
-    }
-
-/* 
- * That failing, the command could be in our list of already executing 
- * commands.  If this is the case, drastic measures are called for.  
- */ 
-
-    for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, 
-    	 prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list);
-	 curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) 
-         &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next);
-
-    if (curr) {
-	if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) {
-            cmd->result = curr->result;
-	    if (prev)
-		*prev = (struct NCR53c7x0_cmd *) curr->next;
-	    curr->next = (struct NCR53c7x0_cmd *) hostdata->free;
-	    cmd->host_scribble = NULL;
-	    hostdata->free = curr;
-	    cmd->scsi_done(cmd);
-	printk ("scsi%d : found finished command %ld in running list\n", 
-	    host->host_no, cmd->pid);
-	    local_irq_restore(flags);
-	    return SCSI_ABORT_NOT_RUNNING;
-	} else {
-	    printk ("scsi%d : DANGER : command running, can not abort.\n",
-		cmd->device->host->host_no);
-	    local_irq_restore(flags);
-	    return SCSI_ABORT_BUSY;
-	}
-    }
-
-/* 
- * And if we couldn't find it in any of our queues, it must have been 
- * a dropped interrupt.
- */
-
-    curr = (struct NCR53c7x0_cmd *) cmd->host_scribble;
-    if (curr) {
-	curr->next = hostdata->free;
-	hostdata->free = curr;
-	cmd->host_scribble = NULL;
-    }
-
-    if (curr == NULL || ((curr->result & 0xff00) == 0xff00) ||
-		((curr->result & 0xff) == 0xff)) {
-	printk ("scsi%d : did this command ever run?\n", host->host_no);
-	    cmd->result = DID_ABORT << 16;
-    } else {
-	printk ("scsi%d : probably lost INTFLY, normal completion\n", 
-	    host->host_no);
-        cmd->result = curr->result;
-/* 
- * FIXME : We need to add an additional flag which indicates if a 
- * command was ever counted as BUSY, so if we end up here we can
- * decrement the busy count if and only if it is necessary.
- */
-        --hostdata->busy[cmd->device->id][cmd->device->lun];
-    }
-    local_irq_restore(flags);
-    cmd->scsi_done(cmd);
-
-/* 
- * We need to run process_issue_queue since termination of this command 
- * may allow another queued command to execute first? 
- */
-    return SCSI_ABORT_NOT_RUNNING;
-}
-
-/*
- * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) 
- * 
- * Purpose : perform a hard reset of the SCSI bus and NCR
- * 	chip.
- *
- * Inputs : cmd - command which caused the SCSI RESET
- *
- * Returns : 0 on success.
- */
- 
-int 
-NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    int found = 0;
-    struct NCR53c7x0_cmd * c;
-    Scsi_Cmnd *tmp;
-    /*
-     * When we call scsi_done(), it's going to wake up anything sleeping on the
-     * resources which were in use by the aborted commands, and we'll start to 
-     * get new commands.
-     *
-     * We can't let this happen until after we've re-initialized the driver
-     * structures, and can't reinitialize those structures until after we've 
-     * dealt with their contents.
-     *
-     * So, we need to find all of the commands which were running, stick
-     * them on a linked list of completed commands (we'll use the host_scribble
-     * pointer), do our reinitialization, and then call the done function for
-     * each command.  
-     */
-    Scsi_Cmnd *nuke_list = NULL;
-    struct Scsi_Host *host = cmd->device->host;
-    struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-    ncr_halt (host);
-    print_lots (host);
-    dump_events (host, 30);
-    ncr_scsi_reset (host);
-    for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */,
-	0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer)
-	if (tmp == cmd) {
-	    found = 1;
-	    break;
-	}
-	    
-    /* 
-     * If we didn't find the command which caused this reset in our running
-     * list, then we've lost it.  See that it terminates normally anyway.
-     */
-    if (!found) {
-    	c = (struct NCR53c7x0_cmd *) cmd->host_scribble;
-    	if (c) {
-	    cmd->host_scribble = NULL;
-    	    c->next = hostdata->free;
-    	    hostdata->free = c;
-    	} else
-	    printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid);
-	cmd->SCp.buffer = (struct scatterlist *) nuke_list;
-	nuke_list = cmd;
-    }
-
-    NCR53c7x0_driver_init (host);
-    hostdata->soft_reset (host);
-    if (hostdata->resets == 0) 
-	disable(host);
-    else if (hostdata->resets != -1)
-	--hostdata->resets;
-    local_irq_restore(flags);
-    for (; nuke_list; nuke_list = tmp) {
-	tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
-    	nuke_list->result = DID_RESET << 16;
-	nuke_list->scsi_done (nuke_list);
-    }
-    local_irq_restore(flags);
-    return SCSI_RESET_SUCCESS;
-}
-
-/*
- * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and 
- * therefore shares the scsicam_bios_param function.
- */
-
-/*
- * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn)
- *
- * Purpose : convert instructions stored at NCR pointer into data 
- *	pointer offset.
- * 
- * Inputs : cmd - SCSI command; insn - pointer to instruction.  Either current
- *	DSP, or saved data pointer.
- *
- * Returns : offset on success, -1 on failure.
- */
-
-
-static int 
-insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0];
-    struct NCR53c7x0_cmd *ncmd = 
-	(struct NCR53c7x0_cmd *) cmd->host_scribble;
-    int offset = 0, buffers;
-    struct scatterlist *segment;
-    char *ptr;
-    int found = 0;
-
-/*
- * With the current code implementation, if the insn is inside dynamically 
- * generated code, the data pointer will be the instruction preceding 
- * the next transfer segment.
- */
-
-    if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) &&
-	((insn >= ncmd->data_transfer_start &&  
-    	    insn < ncmd->data_transfer_end) ||
-    	(insn >= ncmd->residual &&
-    	    insn < (ncmd->residual + 
-    	    	sizeof(ncmd->residual))))) {
-	    ptr = bus_to_virt(insn[3]);
-
-	    if ((buffers = cmd->use_sg)) {
-    	    	for (offset = 0, 
-		     	segment = (struct scatterlist *) cmd->request_buffer;
-    	    	     buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && 
-    	    	    	    (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
-    	    	     --buffers, offset += segment->length, ++segment)
-#if 0
-		    printk("scsi%d: comparing 0x%p to 0x%p\n", 
-			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
-#else
-		    ;
-#endif
-    	    	    offset += ptr - ((char *)page_address(segment->page)+segment->offset);
-    	    } else {
-		found = 1;
-    	    	offset = ptr - (char *) (cmd->request_buffer);
-    	    }
-    } else if ((insn >= hostdata->script + 
-		hostdata->E_data_transfer / sizeof(u32)) &&
-	       (insn <= hostdata->script +
-		hostdata->E_end_data_transfer / sizeof(u32))) {
-    	found = 1;
-	offset = 0;
-    }
-    return found ? offset : -1;
-}
-
-
-
-/*
- * Function : void print_progress (Scsi_Cmnd *cmd) 
- * 
- * Purpose : print the current location of the saved data pointer
- *
- * Inputs : cmd - command we are interested in
- *
- */
-
-static void 
-print_progress (Scsi_Cmnd *cmd) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_cmd *ncmd = 
-	(struct NCR53c7x0_cmd *) cmd->host_scribble;
-    int offset, i;
-    char *where;
-    u32 *ptr;
-    NCR53c7x0_local_setup (cmd->device->host);
-
-    if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0)
-    {
-	printk("\nNCR53c7x0_cmd fields:\n");
-	printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n",
-	    ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0],
-	    ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]);
-	printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]);
-    }
-
-    for (i = 0; i < 2; ++i) {
-	if (check_address ((unsigned long) ncmd, 
-	    sizeof (struct NCR53c7x0_cmd)) == -1) 
-	    continue;
-	if (!i) {
-	    where = "saved";
-	    ptr = bus_to_virt(ncmd->saved_data_pointer);
-	} else {
-	    where = "active";
-	    ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) -
-		NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) *
-		sizeof(u32));
-	} 
-	offset = insn_to_offset (cmd, ptr);
-
-	if (offset != -1) 
-	    printk ("scsi%d : %s data pointer at offset %d\n",
-		cmd->device->host->host_no, where, offset);
-	else {
-	    int size;
-	    printk ("scsi%d : can't determine %s data pointer offset\n",
-		cmd->device->host->host_no, where);
-	    if (ncmd) {
-		size = print_insn (cmd->device->host,
-		    bus_to_virt(ncmd->saved_data_pointer), "", 1);
-		print_insn (cmd->device->host,
-		    bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32),
-		    "", 1);
-	    }
-	}
-    }
-}
-
-
-static void 
-print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int i, len;
-    char *ptr;
-    Scsi_Cmnd *cmd;
-
-    if (check_address ((unsigned long) dsa, hostdata->dsa_end - 
-	hostdata->dsa_start) == -1) {
-	printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa);
-	return;
-    }
-    printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n"
-	    "        + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" ,
-    	    prefix ? prefix : "",
-    	    host->host_no,  virt_to_bus (dsa), dsa, hostdata->dsa_msgout,
-    	    dsa[hostdata->dsa_msgout / sizeof(u32)],
-	    dsa[hostdata->dsa_msgout / sizeof(u32) + 1],
-	    bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]));
-
-    /* 
-     * Only print messages if they're sane in length so we don't
-     * blow the kernel printk buffer on something which won't buy us
-     * anything.
-     */
-
-    if (dsa[hostdata->dsa_msgout / sizeof(u32)] < 
-	    sizeof (hostdata->free->select)) 
-	for (i = dsa[hostdata->dsa_msgout / sizeof(u32)],
-	    ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); 
-	    i > 0 && !check_address ((unsigned long) ptr, 1);
-	    ptr += len, i -= len) {
-	    printk("               ");
-	    len = spi_print_msg(ptr);
-	    printk("\n");
-	    if (!len)
-		break;
-	}
-
-    printk("        + %d : select_indirect = 0x%x\n",
-	hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]);
-    cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
-    printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
-	   (u32) virt_to_bus(cmd));
-    /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
-    if (cmd) {
-	printk("               result = 0x%x, target = %d, lun = %d, cmd = ",
-	    cmd->result, cmd->device->id, cmd->device->lun);
-	__scsi_print_command(cmd->cmnd);
-    } else
-	printk("\n");
-    printk("        + %d : dsa_next = 0x%x\n", hostdata->dsa_next,
-	dsa[hostdata->dsa_next / sizeof(u32)]);
-    if (cmd) { 
-	printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n"
-	       "                   script : ",
-	    host->host_no, cmd->device->id,
-	    hostdata->sync[cmd->device->id].sxfer_sanity,
-	    hostdata->sync[cmd->device->id].scntl3_sanity);
-	for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i)
-	    printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]);
-	printk ("\n");
-    	print_progress (cmd);
-    }
-}
-/*
- * Function : void print_queues (Scsi_Host *host) 
- * 
- * Purpose : print the contents of the NCR issue and reconnect queues
- *
- * Inputs : host - SCSI host we are interested in
- *
- */
-
-static void 
-print_queues (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    u32 *dsa, *next_dsa;
-    volatile u32 *ncrcurrent;
-    int left;
-    Scsi_Cmnd *cmd, *next_cmd;
-    unsigned long flags;
-
-    printk ("scsi%d : issue queue\n", host->host_no);
-
-    for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; 
-	    left >= 0 && cmd; 
-	    cmd = next_cmd) {
-	next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
-	local_irq_save(flags);
-	if (cmd->host_scribble) {
-	    if (check_address ((unsigned long) (cmd->host_scribble), 
-		sizeof (cmd->host_scribble)) == -1)
-		printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n",
-		    host->host_no, cmd->pid);
-	    /* print_dsa does sanity check on address, no need to check */
-	    else
-	    	print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble)
-		    -> dsa, "");
-	} else 
-	    printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
-		host->host_no, cmd->pid, cmd->device->id, cmd->device->lun);
-	local_irq_restore(flags);
-    }
-
-    if (left <= 0) {
-	printk ("scsi%d : loop detected in issue queue\n",
-	    host->host_no);
-    }
-
-    /*
-     * Traverse the NCR reconnect and start DSA structures, printing out 
-     * each element until we hit the end or detect a loop.  Currently,
-     * the reconnect structure is a linked list; and the start structure
-     * is an array.  Eventually, the reconnect structure will become a 
-     * list as well, since this simplifies the code.
-     */
-
-    printk ("scsi%d : schedule dsa array :\n", host->host_no);
-    for (left = host->can_queue, ncrcurrent = hostdata->schedule;
-	    left > 0; ncrcurrent += 2, --left)
-	if (ncrcurrent[0] != hostdata->NOP_insn) 
-/* FIXME : convert pointer to dsa_begin to pointer to dsa. */
-	    print_dsa (host, bus_to_virt (ncrcurrent[1] - 
-		(hostdata->E_dsa_code_begin - 
-		hostdata->E_dsa_code_template)), "");
-    printk ("scsi%d : end schedule dsa array\n", host->host_no);
-    
-    printk ("scsi%d : reconnect_dsa_head :\n", host->host_no);
-	    
-    for (left = host->can_queue, 
-	dsa = bus_to_virt (hostdata->reconnect_dsa_head);
-	left >= 0 && dsa; 
-	dsa = next_dsa) {
-	local_irq_save(flags);
-	if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
-	    printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
-		dsa);
-	    next_dsa = NULL;
-	}
-	else 
-	{
-	    next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
-	    print_dsa (host, dsa, "");
-	}
-	local_irq_restore(flags);
-    }
-    printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
-    if (left < 0)
-	printk("scsi%d: possible loop in ncr reconnect list\n",
-	    host->host_no);
-}
-
-static void
-print_lots (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    u32 *dsp_next, *dsp, *dsa, dbc_dcmd;
-    unsigned char dcmd, sbcl;
-    int i, size;
-    NCR53c7x0_local_setup(host);
-
-    if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) {
-    	dbc_dcmd = NCR53c7x0_read32(DBC_REG);
-    	dcmd = (dbc_dcmd & 0xff000000) >> 24;
-    	dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
-	dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-	sbcl = NCR53c7x0_read8 (SBCL_REG);
-	    
-	/*
-	 * For the 53c710, the following will report value 0 for SCNTL3
-	 * and STEST0 - we don't have these registers.
-	 */
-    	printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n"
-		"         DSA=0x%lx (virt 0x%p)\n"
-	        "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n"
-		"         SXFER=0x%x, SCNTL3=0x%x\n"
-		"         %s%s%sphase=%s, %d bytes in SCSI FIFO\n"
-		"         SCRATCH=0x%x, saved2_dsa=0x%0lx\n",
-	    host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG),
-		bus_to_virt(NCR53c7x0_read32(DNAD_REG)),
-	    virt_to_bus(dsa), dsa,
-	    NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), 
-	    bus_to_virt (NCR53c7x0_read32(TEMP_REG)),
-	    (int) NCR53c7x0_read8(hostdata->dmode),
-	    (int) NCR53c7x0_read8(SXFER_REG), 
-	    ((hostdata->chip / 100) == 8) ?
-		(int) NCR53c7x0_read8(SCNTL3_REG_800) : 0,
-	    (sbcl & SBCL_BSY) ? "BSY " : "",
-	    (sbcl & SBCL_SEL) ? "SEL " : "",
-	    (sbcl & SBCL_REQ) ? "REQ " : "",
-	    sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ?
-	    	SSTAT1_REG : SSTAT2_REG)),
-	    (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? 
-		SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT,
-	    ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) :
-		NCR53c7x0_read32(SCRATCHA_REG_800),
-	    hostdata->saved2_dsa);
-	printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, 
-	    virt_to_bus(dsp), dsp);
-    	for (i = 6; i > 0; --i, dsp += size)
-	    size = print_insn (host, dsp, "", 1);
-	if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON)  {
-	    if ((hostdata->chip / 100) == 8)
-	        printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n",
-		    host->host_no, NCR53c7x0_read8 (SDID_REG_800),
-		    NCR53c7x0_read8 (SSID_REG_800));
-	    else
-		printk ("scsi%d : connected (SDID=0x%x)\n",
-		    host->host_no, NCR53c7x0_read8 (SDID_REG_700));
-	    print_dsa (host, dsa, "");
-	}
-
-#if 1
-	print_queues (host);
-#endif
-    }
-}
-
-/*
- * Function : static int shutdown (struct Scsi_Host *host)
- * 
- * Purpose : does a clean (we hope) shutdown of the NCR SCSI 
- *	chip.  Use prior to dumping core, unloading the NCR driver,
- * 
- * Returns : 0 on success
- */
-static int 
-shutdown (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-/* Get in a state where we can reset the SCSI bus */
-    ncr_halt (host);
-    ncr_scsi_reset (host);
-    hostdata->soft_reset(host);
-
-    disable (host);
-    local_irq_restore(flags);
-    return 0;
-}
-
-/*
- * Function : void ncr_scsi_reset (struct Scsi_Host *host)
- *
- * Purpose : reset the SCSI bus.
- */
-
-static void 
-ncr_scsi_reset (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    NCR53c7x0_local_setup(host);
-    local_irq_save(flags);
-    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
-    udelay(25);	/* Minimum amount of time to assert RST */
-    NCR53c7x0_write8(SCNTL1_REG, 0);
-    local_irq_restore(flags);
-}
-
-/* 
- * Function : void hard_reset (struct Scsi_Host *host)
- *
- */
-
-static void 
-hard_reset (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long flags;
-    local_irq_save(flags);
-    ncr_scsi_reset(host);
-    NCR53c7x0_driver_init (host);
-    if (hostdata->soft_reset)
-	hostdata->soft_reset (host);
-    local_irq_restore(flags);
-}
-
-
-/*
- * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host,
- *	int free, int issue)
- *
- * Purpose : return a linked list (using the SCp.buffer field as next,
- *	so we don't perturb hostdata.  We don't use a field of the 
- *	NCR53c7x0_cmd structure since we may not have allocated one 
- *	for the command causing the reset.) of Scsi_Cmnd structures that 
- *  	had propagated below the Linux issue queue level.  If free is set, 
- *	free the NCR53c7x0_cmd structures which are associated with 
- *	the Scsi_Cmnd structures, and clean up any internal 
- *	NCR lists that the commands were on.  If issue is set,
- *	also return commands in the issue queue.
- *
- * Returns : linked list of commands
- *
- * NOTE : the caller should insure that the NCR chip is halted
- *	if the free flag is set. 
- */
-
-static Scsi_Cmnd *
-return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    struct NCR53c7x0_cmd *c;
-    int i;
-    u32 *ncrcurrent;
-    Scsi_Cmnd *list = NULL, *tmp;
-    for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; 
-    	c = (struct NCR53c7x0_cmd *) c->next)  {
-	if (c->cmd->SCp.buffer) {
-	    printk ("scsi%d : loop detected in running list!\n", host->host_no);
-	    break;
-	} else {
-	    printk ("Duh? Bad things happening in the NCR driver\n");
-	    break;
-	}
-
-	c->cmd->SCp.buffer = (struct scatterlist *) list;
-	list = c->cmd;
-	if (free) {
-    	    c->next = hostdata->free;
-    	    hostdata->free = c;
-	}
-    }
-
-    if (free) { 
-	for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
-	    i < host->can_queue; ++i, ncrcurrent += 2) {
-	    ncrcurrent[0] = hostdata->NOP_insn;
-	    ncrcurrent[1] = 0xdeadbeef;
-	}
-	hostdata->ncrcurrent = NULL;
-    }
-
-    if (issue) {
-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) {
-	    if (tmp->SCp.buffer) {
-		printk ("scsi%d : loop detected in issue queue!\n", 
-			host->host_no);
-		break;
-	    }
-	    tmp->SCp.buffer = (struct scatterlist *) list;
-	    list = tmp;
-	}
-	if (free)
-	    hostdata->issue_queue = NULL;
-		
-    }
-    return list;
-}
-
-/* 
- * Function : static int disable (struct Scsi_Host *host)
- *
- * Purpose : disables the given NCR host, causing all commands
- * 	to return a driver error.  Call this so we can unload the
- * 	module during development and try again.  Eventually, 
- * 	we should be able to find clean workarounds for these
- * 	problems.
- *
- * Inputs : host - hostadapter to twiddle
- *
- * Returns : 0 on success.
- */
-
-static int 
-disable (struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    unsigned long flags;
-    Scsi_Cmnd *nuke_list, *tmp;
-    local_irq_save(flags);
-    if (hostdata->state != STATE_HALTED)
-	ncr_halt (host);
-    nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
-    hard_reset (host);
-    hostdata->state = STATE_DISABLED;
-    local_irq_restore(flags);
-    printk ("scsi%d : nuking commands\n", host->host_no);
-    for (; nuke_list; nuke_list = tmp) {
-	    tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
-	    nuke_list->result = DID_ERROR << 16;
-	    nuke_list->scsi_done(nuke_list);
-    }
-    printk ("scsi%d : done. \n", host->host_no);
-    printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n",
-    	host->host_no);
-    return 0;
-}
-
-/*
- * Function : static int ncr_halt (struct Scsi_Host *host)
- * 
- * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
- *
- * Inputs : host - SCSI chip to halt
- *
- * Returns : 0 on success
- */
-
-static int 
-ncr_halt (struct Scsi_Host *host) {
-    NCR53c7x0_local_declare();
-    unsigned long flags;
-    unsigned char istat, tmp;
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    int stage;
-    NCR53c7x0_local_setup(host);
-
-    local_irq_save(flags);
-    /* Stage 0 : eat all interrupts
-       Stage 1 : set ABORT
-       Stage 2 : eat all but abort interrupts
-       Stage 3 : eat all interrupts
-     */
-    for (stage = 0;;) {
-	if (stage == 1) {
-	    NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
-	    ++stage;
-	}
-	istat = NCR53c7x0_read8 (hostdata->istat);
-	if (istat & ISTAT_SIP) {
-	    tmp = NCR53c7x0_read8(SSTAT0_REG);
-	} else if (istat & ISTAT_DIP) {
-	    tmp = NCR53c7x0_read8(DSTAT_REG);
-	    if (stage == 2) {
-		if (tmp & DSTAT_ABRT) {
-		    NCR53c7x0_write8(hostdata->istat, 0);
-		    ++stage;
-		} else {
-		    printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", 
-			host->host_no);
-		    disable (host);
-	    	}
-    	    }
-	}
-	if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
-	    if (stage == 0)
-	    	++stage;
-	    else if (stage == 3)
-		break;
-	}
-    }
-    hostdata->state = STATE_HALTED;
-    local_irq_restore(flags);
-#if 0
-    print_lots (host);
-#endif
-    return 0;
-}
-
-/* 
- * Function: event_name (int event)
- * 
- * Purpose: map event enum into user-readable strings.
- */
-
-static const char *
-event_name (int event) {
-    switch (event) {
-    case EVENT_NONE:		return "none";
-    case EVENT_ISSUE_QUEUE:	return "to issue queue";
-    case EVENT_START_QUEUE:	return "to start queue";
-    case EVENT_SELECT:		return "selected";
-    case EVENT_DISCONNECT:	return "disconnected";
-    case EVENT_RESELECT:	return "reselected";
-    case EVENT_COMPLETE:	return "completed";
-    case EVENT_IDLE:		return "idle";
-    case EVENT_SELECT_FAILED:	return "select failed";
-    case EVENT_BEFORE_SELECT:	return "before select";
-    case EVENT_RESELECT_FAILED:	return "reselect failed";
-    default:			return "unknown";
-    }
-}
-
-/*
- * Function : void dump_events (struct Scsi_Host *host, count)
- *
- * Purpose : print last count events which have occurred.
- */ 
-static void
-dump_events (struct Scsi_Host *host, int count) {
-    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata[0];
-    struct NCR53c7x0_event event;
-    int i;
-    unsigned long flags;
-    if (hostdata->events) {
-	if (count > hostdata->event_size)
-	    count = hostdata->event_size;
-	for (i = hostdata->event_index; count > 0; 
-	    i = (i ? i - 1 : hostdata->event_size -1), --count) {
-/*
- * By copying the event we're currently examining with interrupts
- * disabled, we can do multiple printk(), etc. operations and 
- * still be guaranteed that they're happening on the same 
- * event structure.
- */
-	    local_irq_save(flags);
-#if 0
-	    event = hostdata->events[i];
-#else
-	    memcpy ((void *) &event, (void *) &(hostdata->events[i]),
-		sizeof(event));
-#endif
-
-	    local_irq_restore(flags);
-	    printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
-		host->host_no, event_name (event.event), count,
-		(long) event.time.tv_sec, (long) event.time.tv_usec,
-		event.target, event.lun);
-	    if (event.dsa) 
-		printk ("         event for dsa 0x%lx (virt 0x%p)\n", 
-		    virt_to_bus(event.dsa), event.dsa);
-	    if (event.pid != -1) {
-		printk ("         event for pid %ld ", event.pid);
-		__scsi_print_command (event.cmnd);
-	    }
-	}
-    }
-}
-
-/*
- * Function: check_address
- *
- * Purpose: Check to see if a possibly corrupt pointer will fault the 
- *	kernel.
- *
- * Inputs: addr - address; size - size of area
- *
- * Returns: 0 if area is OK, -1 on error.
- *
- * NOTES: should be implemented in terms of vverify on kernels 
- *	that have it.
- */
-
-static int 
-check_address (unsigned long addr, int size) {
-    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
-}
-
-#ifdef MODULE
-int 
-NCR53c7x0_release(struct Scsi_Host *host) {
-    struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata[0];
-    struct NCR53c7x0_cmd *cmd, *tmp;
-    shutdown (host);
-    if (host->irq != SCSI_IRQ_NONE)
-	{
-	    int irq_count;
-	    struct Scsi_Host *tmp;
-	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
-		if (tmp->hostt == the_template && tmp->irq == host->irq)
-		    ++irq_count;
-	    if (irq_count == 1)
-		free_irq(host->irq, NULL);
-	}
-    if (host->dma_channel != DMA_NONE)
-	free_dma(host->dma_channel);
-    if (host->io_port)
-	release_region(host->io_port, host->n_io_port);
-    
-    for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, 
-	--hostdata->num_cmds) {
-	tmp = (struct NCR53c7x0_cmd *) cmd->next;
-    /* 
-     * If we're going to loop, try to stop it to get a more accurate
-     * count of the leaked commands.
-     */
-	cmd->next = NULL;
-	if (cmd->free)
-	    cmd->free ((void *) cmd->real, cmd->size);
-    }
-    if (hostdata->num_cmds)
-	printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
-	    host->host_no, hostdata->num_cmds);
-
-    vfree(hostdata->events);
-
-    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
-     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
-     */
-    kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING);
-    free_pages ((u32)hostdata, 1);
-    return 1;
-}
-#endif /* def MODULE */
diff --git a/drivers/scsi/53c7xx.h b/drivers/scsi/53c7xx.h
deleted file mode 100644
index 218f3b9..0000000
--- a/drivers/scsi/53c7xx.h
+++ /dev/null
@@ -1,1608 +0,0 @@
-/*
- * 53c710 driver.  Modified from Drew Eckhardts driver
- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * I have left the code for the 53c8xx family in here, because it didn't
- * seem worth removing it.  The possibility of IO_MAPPED chips rather
- * than MEMORY_MAPPED remains, in case someone wants to add support for
- * 53c710 chips on Intel PCs (some older machines have them on the
- * motherboard).
- *
- * NOTE THERE MAY BE PROBLEMS WITH CASTS IN read8 AND Co.
- */
-
-/*
- * NCR 53c{7,8}0x0 driver, header file
- *
- * Sponsored by
- *      iX Multiuser Multitasking Magazine
- *	Hannover, Germany
- *	hm@ix.de	
- *
- * Copyright 1993, 1994, 1995 Drew Eckhardt
- *      Visionary Computing 
- *      (Unix and Linux consulting and custom programming)
- *      drew@PoohSticks.ORG
- *	+1 (303) 786-7975
- *
- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
- * 
- * PRE-ALPHA
- *
- * For more information, please consult 
- *
- * NCR 53C700/53C700-66
- * SCSI I/O Processor
- * Data Manual
- *
- * NCR 53C810
- * PCI-SCSI I/O Processor 
- * Data Manual
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * +1 (719) 578-3400
- *
- * Toll free literature number
- * +1 (800) 334-5454
- *
- */
-
-#ifndef NCR53c710_H
-#define NCR53c710_H
-
-#ifndef HOSTS_C
-
-/* SCSI control 0 rw, default = 0xc0 */ 
-#define SCNTL0_REG 		0x00	
-#define SCNTL0_ARB1		0x80	/* 0 0 = simple arbitration */
-#define SCNTL0_ARB2		0x40	/* 1 1 = full arbitration */
-#define SCNTL0_STRT		0x20	/* Start Sequence */
-#define SCNTL0_WATN		0x10	/* Select with ATN */
-#define SCNTL0_EPC		0x08	/* Enable parity checking */
-/* Bit 2 is reserved on 800 series chips */
-#define SCNTL0_EPG_700		0x04	/* Enable parity generation */
-#define SCNTL0_AAP		0x02	/*  ATN/ on parity error */
-#define SCNTL0_TRG		0x01	/* Target mode */
-
-/* SCSI control 1 rw, default = 0x00 */
-
-#define SCNTL1_REG 		0x01	
-#define SCNTL1_EXC		0x80	/* Extra Clock Cycle of Data setup */
-#define SCNTL1_ADB		0x40	/*  contents of SODL on bus */
-#define SCNTL1_ESR_700		0x20	/* Enable SIOP response to selection 
-					   and reselection */
-#define SCNTL1_DHP_800		0x20	/* Disable halt on parity error or ATN
-					   target mode only */
-#define SCNTL1_CON		0x10	/* Connected */
-#define SCNTL1_RST		0x08	/* SCSI RST/ */
-#define SCNTL1_AESP		0x04	/* Force bad parity */
-#define SCNTL1_SND_700		0x02	/* Start SCSI send */
-#define SCNTL1_IARB_800		0x02	/* Immediate Arbitration, start
-					   arbitration immediately after
-					   busfree is detected */
-#define SCNTL1_RCV_700		0x01	/* Start SCSI receive */
-#define SCNTL1_SST_800		0x01	/* Start SCSI transfer */
-
-/* SCSI control 2 rw, */
-
-#define SCNTL2_REG_800		0x02	
-#define SCNTL2_800_SDU		0x80	/* SCSI disconnect unexpected */
-
-/* SCSI control 3 rw */
-
-#define SCNTL3_REG_800 		0x03	
-#define SCNTL3_800_SCF_SHIFT	4
-#define SCNTL3_800_SCF_MASK	0x70
-#define SCNTL3_800_SCF2		0x40	/* Synchronous divisor */
-#define SCNTL3_800_SCF1		0x20	/* 0x00 = SCLK/3 */
-#define SCNTL3_800_SCF0		0x10	/* 0x10 = SCLK/1 */
-					/* 0x20 = SCLK/1.5 
-					   0x30 = SCLK/2 
-					   0x40 = SCLK/3 */
-	    
-#define SCNTL3_800_CCF_SHIFT	0
-#define SCNTL3_800_CCF_MASK	0x07
-#define SCNTL3_800_CCF2		0x04	/* 0x00 50.01 to 66 */
-#define SCNTL3_800_CCF1		0x02	/* 0x01 16.67 to 25 */
-#define SCNTL3_800_CCF0		0x01	/* 0x02	25.01 - 37.5 
-					   0x03	37.51 - 50 
-					   0x04 50.01 - 66 */
-
-/*  
- * SCSI destination ID rw - the appropriate bit is set for the selected
- * target ID.  This is written by the SCSI SCRIPTS processor.
- * default = 0x00
- */
-#define SDID_REG_700  		0x02	
-#define SDID_REG_800		0x06
-
-#define GP_REG_800		0x07	/* General purpose IO */
-#define GP_800_IO1		0x02
-#define GP_800_IO2		0x01
-
-/* SCSI interrupt enable rw, default = 0x00 */
-#define SIEN_REG_700		0x03	
-#define SIEN0_REG_800		0x40
-#define SIEN_MA			0x80	/* Phase mismatch (ini) or ATN (tgt) */
-#define SIEN_FC			0x40	/* Function complete */
-#define SIEN_700_STO		0x20	/* Selection or reselection timeout */
-#define SIEN_800_SEL		0x20	/* Selected */
-#define SIEN_700_SEL		0x10	/* Selected or reselected */
-#define SIEN_800_RESEL		0x10	/* Reselected */
-#define SIEN_SGE		0x08	/* SCSI gross error */
-#define SIEN_UDC		0x04	/* Unexpected disconnect */
-#define SIEN_RST		0x02	/* SCSI RST/ received */
-#define SIEN_PAR		0x01	/* Parity error */
-
-/* 
- * SCSI chip ID rw
- * NCR53c700 : 
- * 	When arbitrating, the highest bit is used, when reselection or selection
- * 	occurs, the chip responds to all IDs for which a bit is set.
- * 	default = 0x00 
- * NCR53c810 : 
- *	Uses bit mapping
- */
-#define SCID_REG		0x04	
-/* Bit 7 is reserved on 800 series chips */
-#define SCID_800_RRE		0x40	/* Enable response to reselection */
-#define SCID_800_SRE		0x20	/* Enable response to selection */
-/* Bits four and three are reserved on 800 series chips */
-#define SCID_800_ENC_MASK	0x07	/* Encoded SCSI ID */
-
-/* SCSI transfer rw, default = 0x00 */
-#define SXFER_REG		0x05
-#define SXFER_DHP		0x80	/* Disable halt on parity */
-
-#define SXFER_TP2		0x40	/* Transfer period msb */
-#define SXFER_TP1		0x20
-#define SXFER_TP0		0x10	/* lsb */
-#define SXFER_TP_MASK		0x70
-/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */
-#define SXFER_TP_SHIFT		5
-#define SXFER_TP_4		0x00	/* Divisors */
-#define SXFER_TP_5		0x10<<1
-#define SXFER_TP_6		0x20<<1
-#define SXFER_TP_7		0x30<<1
-#define SXFER_TP_8		0x40<<1
-#define SXFER_TP_9		0x50<<1
-#define SXFER_TP_10		0x60<<1
-#define SXFER_TP_11		0x70<<1
-
-#define SXFER_MO3		0x08	/* Max offset msb */
-#define SXFER_MO2		0x04
-#define SXFER_MO1		0x02
-#define SXFER_MO0		0x01	/* lsb */
-#define SXFER_MO_MASK		0x0f
-#define SXFER_MO_SHIFT		0
-
-/* 
- * SCSI output data latch rw
- * The contents of this register are driven onto the SCSI bus when 
- * the Assert Data Bus bit of the SCNTL1 register is set and 
- * the CD, IO, and MSG bits of the SOCL register match the SCSI phase
- */
-#define SODL_REG_700		0x06	
-#define SODL_REG_800		0x54
-
-
-/* 
- * SCSI output control latch rw, default = 0 
- * Note that when the chip is being manually programmed as an initiator,
- * the MSG, CD, and IO bits must be set correctly for the phase the target
- * is driving the bus in.  Otherwise no data transfer will occur due to 
- * phase mismatch.
- */
-
-#define SOCL_REG		0x07
-#define SOCL_REQ		0x80	/*  REQ */
-#define SOCL_ACK		0x40	/*  ACK */
-#define SOCL_BSY		0x20	/*  BSY */
-#define SOCL_SEL		0x10	/*  SEL */
-#define SOCL_ATN		0x08	/*  ATN */
-#define SOCL_MSG		0x04	/*  MSG */
-#define SOCL_CD			0x02	/*  C/D */
-#define SOCL_IO			0x01	/*  I/O */
-
-/* 
- * SCSI first byte received latch ro 
- * This register contains the first byte received during a block MOVE 
- * SCSI SCRIPTS instruction, including
- * 
- * Initiator mode	Target mode
- * Message in		Command
- * Status		Message out
- * Data in		Data out
- *
- * It also contains the selecting or reselecting device's ID and our 
- * ID.
- *
- * Note that this is the register the various IF conditionals can 
- * operate on.
- */
-#define SFBR_REG		0x08	
-
-/* 
- * SCSI input data latch ro
- * In initiator mode, data is latched into this register on the rising
- * edge of REQ/. In target mode, data is latched on the rising edge of 
- * ACK/
- */
-#define SIDL_REG_700		0x09
-#define SIDL_REG_800		0x50
-
-/* 
- * SCSI bus data lines ro 
- * This register reflects the instantaneous status of the SCSI data 
- * lines.  Note that SCNTL0 must be set to disable parity checking, 
- * otherwise reading this register will latch new parity.
- */
-#define SBDL_REG_700		0x0a
-#define SBDL_REG_800		0x58
-
-#define SSID_REG_800		0x0a
-#define SSID_800_VAL		0x80	/* Exactly two bits asserted at sel */
-#define SSID_800_ENCID_MASK	0x07	/* Device which performed operation */
-
-
-/* 
- * SCSI bus control lines rw, 
- * instantaneous readout of control lines 
- */
-#define SBCL_REG		0x0b 	
-#define SBCL_REQ		0x80	/*  REQ ro */
-#define SBCL_ACK		0x40	/*  ACK ro */
-#define SBCL_BSY		0x20	/*  BSY ro */
-#define SBCL_SEL		0x10	/*  SEL ro */
-#define SBCL_ATN		0x08	/*  ATN ro */
-#define SBCL_MSG		0x04	/*  MSG ro */
-#define SBCL_CD			0x02	/*  C/D ro */
-#define SBCL_IO			0x01	/*  I/O ro */
-#define SBCL_PHASE_CMDOUT	SBCL_CD
-#define SBCL_PHASE_DATAIN	SBCL_IO
-#define SBCL_PHASE_DATAOUT	0
-#define SBCL_PHASE_MSGIN	(SBCL_CD|SBCL_IO|SBCL_MSG)
-#define SBCL_PHASE_MSGOUT	(SBCL_CD|SBCL_MSG)
-#define SBCL_PHASE_STATIN	(SBCL_CD|SBCL_IO)
-#define SBCL_PHASE_MASK		(SBCL_CD|SBCL_IO|SBCL_MSG)
-/* 
- * Synchronous SCSI Clock Control bits 
- * 0 - set by DCNTL 
- * 1 - SCLK / 1.0
- * 2 - SCLK / 1.5
- * 3 - SCLK / 2.0 
- */
-#define SBCL_SSCF1		0x02	/* wo, -66 only */
-#define SBCL_SSCF0		0x01	/* wo, -66 only */
-#define SBCL_SSCF_MASK		0x03
-
-/* 
- * XXX note : when reading the DSTAT and STAT registers to clear interrupts,
- * insure that 10 clocks elapse between the two  
- */
-/* DMA status ro */
-#define DSTAT_REG		0x0c	
-#define DSTAT_DFE		0x80	/* DMA FIFO empty */
-#define DSTAT_800_MDPE		0x40	/* Master Data Parity Error */
-#define DSTAT_800_BF		0x20	/* Bus Fault */
-#define DSTAT_ABRT		0x10	/* Aborted - set on error */
-#define DSTAT_SSI		0x08	/* SCRIPTS single step interrupt */
-#define DSTAT_SIR		0x04	/* SCRIPTS interrupt received - 
-					   set when INT instruction is 
-					   executed */
-#define DSTAT_WTD		0x02	/* Watchdog timeout detected */
-#define DSTAT_OPC		0x01	/* Illegal instruction */
-#define DSTAT_800_IID		0x01	/* Same thing, different name */
-
-
-/* NCR53c800 moves this stuff into SIST0 */
-#define SSTAT0_REG		0x0d	/* SCSI status 0 ro */
-#define SIST0_REG_800		0x42	
-#define SSTAT0_MA		0x80	/* ini : phase mismatch,
-					 * tgt : ATN/ asserted 
-					 */
-#define SSTAT0_CMP		0x40	/* function complete */
-#define SSTAT0_700_STO		0x20	/* Selection or reselection timeout */
-#define SIST0_800_SEL		0x20	/* Selected */
-#define SSTAT0_700_SEL		0x10	/* Selected or reselected */
-#define SIST0_800_RSL		0x10	/* Reselected */
-#define SSTAT0_SGE		0x08	/* SCSI gross error */
-#define SSTAT0_UDC		0x04	/* Unexpected disconnect */
-#define SSTAT0_RST		0x02	/* SCSI RST/ received */
-#define SSTAT0_PAR		0x01	/* Parity error */
-
-/* And uses SSTAT0 for what was SSTAT1 */
-
-#define SSTAT1_REG		0x0e	/* SCSI status 1 ro */
-#define SSTAT1_ILF		0x80	/* SIDL full */
-#define SSTAT1_ORF		0x40	/* SODR full */
-#define SSTAT1_OLF		0x20	/* SODL full */
-#define SSTAT1_AIP		0x10	/* Arbitration in progress */
-#define SSTAT1_LOA		0x08	/* Lost arbitration */
-#define SSTAT1_WOA		0x04	/* Won arbitration */
-#define SSTAT1_RST		0x02	/* Instant readout of RST/ */
-#define SSTAT1_SDP		0x01	/* Instant readout of SDP/ */
-
-#define SSTAT2_REG		0x0f	/* SCSI status 2 ro */
-#define SSTAT2_FF3		0x80 	/* number of bytes in synchronous */
-#define SSTAT2_FF2		0x40	/* data FIFO */
-#define SSTAT2_FF1		0x20	
-#define SSTAT2_FF0		0x10
-#define SSTAT2_FF_MASK		0xf0
-#define SSTAT2_FF_SHIFT		4
-
-/* 
- * Latched signals, latched on the leading edge of REQ/ for initiators,
- * ACK/ for targets.
- */
-#define SSTAT2_SDP		0x08	/* SDP */
-#define SSTAT2_MSG		0x04	/* MSG */
-#define SSTAT2_CD		0x02	/* C/D */
-#define SSTAT2_IO		0x01	/* I/O */
-#define SSTAT2_PHASE_CMDOUT	SSTAT2_CD
-#define SSTAT2_PHASE_DATAIN	SSTAT2_IO
-#define SSTAT2_PHASE_DATAOUT	0
-#define SSTAT2_PHASE_MSGIN	(SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
-#define SSTAT2_PHASE_MSGOUT	(SSTAT2_CD|SSTAT2_MSG)
-#define SSTAT2_PHASE_STATIN	(SSTAT2_CD|SSTAT2_IO)
-#define SSTAT2_PHASE_MASK	(SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
-
-
-/* NCR53c700-66 only */
-#define SCRATCHA_REG_00		0x10    /* through  0x13 Scratch A rw */
-/* NCR53c710 and higher */
-#define DSA_REG			0x10	/* DATA structure address */
-
-#define CTEST0_REG_700		0x14	/* Chip test 0 ro */
-#define CTEST0_REG_800		0x18	/* Chip test 0 rw, general purpose */
-/* 0x80 - 0x04 are reserved */
-#define CTEST0_700_RTRG		0x02	/* Real target mode */
-#define CTEST0_700_DDIR		0x01	/* Data direction, 1 = 
-					 * SCSI bus to host, 0  =
-					 * host to SCSI.
-					 */
-
-#define CTEST1_REG_700		0x15	/* Chip test 1 ro */
-#define CTEST1_REG_800		0x19	/* Chip test 1 ro */
-#define CTEST1_FMT3		0x80	/* Identify which byte lanes are empty */
-#define CTEST1_FMT2		0x40 	/* in the DMA FIFO */
-#define CTEST1_FMT1		0x20
-#define CTEST1_FMT0		0x10
-
-#define CTEST1_FFL3		0x08	/* Identify which bytes lanes are full */
-#define CTEST1_FFL2		0x04	/* in the DMA FIFO */
-#define CTEST1_FFL1		0x02
-#define CTEST1_FFL0		0x01
-
-#define CTEST2_REG_700		0x16	/* Chip test 2 ro */
-#define CTEST2_REG_800		0x1a	/* Chip test 2 ro */
-
-#define CTEST2_800_DDIR		0x80	/* 1 = SCSI->host */
-#define CTEST2_800_SIGP		0x40	/* A copy of SIGP in ISTAT.
-					   Reading this register clears */
-#define CTEST2_800_CIO		0x20	/* Configured as IO */.
-#define CTEST2_800_CM		0x10	/* Configured as memory */
-
-/* 0x80 - 0x40 are reserved on 700 series chips */
-#define CTEST2_700_SOFF		0x20	/* SCSI Offset Compare,
-					 * As an initiator, this bit is 
-					 * one when the synchronous offset
-					 * is zero, as a target this bit 
-					 * is one when the synchronous 
-					 * offset is at the maximum
-					 * defined in SXFER
-					 */
-#define CTEST2_700_SFP		0x10	/* SCSI FIFO parity bit,
-					 * reading CTEST3 unloads a byte
-					 * from the FIFO and sets this
-					 */
-#define CTEST2_700_DFP		0x08	/* DMA FIFO parity bit,
-					 * reading CTEST6 unloads a byte
-					 * from the FIFO and sets this
-					 */
-#define CTEST2_TEOP		0x04	/* SCSI true end of process,
-					 * indicates a totally finished
-					 * transfer
-					 */
-#define CTEST2_DREQ		0x02	/* Data request signal */
-/* 0x01 is reserved on 700 series chips */
-#define CTEST2_800_DACK		0x01	
-
-/* 
- * Chip test 3 ro 
- * Unloads the bottom byte of the eight deep SCSI synchronous FIFO,
- * check SSTAT2 FIFO full bits to determine size.  Note that a GROSS
- * error results if a read is attempted on this register.  Also note 
- * that 16 and 32 bit reads of this register will cause corruption.
- */
-#define CTEST3_REG_700		0x17	
-/*  Chip test 3 rw */
-#define CTEST3_REG_800		0x1b
-#define CTEST3_800_V3		0x80	/* Chip revision */
-#define CTEST3_800_V2		0x40
-#define CTEST3_800_V1		0x20
-#define CTEST3_800_V0		0x10
-#define CTEST3_800_FLF		0x08	/* Flush DMA FIFO */
-#define CTEST3_800_CLF		0x04	/* Clear DMA FIFO */
-#define CTEST3_800_FM		0x02	/* Fetch mode pin */
-/* bit 0 is reserved on 800 series chips */
-
-#define CTEST4_REG_700		0x18	/* Chip test 4 rw */
-#define CTEST4_REG_800		0x21	/* Chip test 4 rw */
-/* 0x80 is reserved on 700 series chips */
-#define CTEST4_800_BDIS		0x80	/* Burst mode disable */
-#define CTEST4_ZMOD		0x40	/* High impedance mode */
-#define CTEST4_SZM		0x20	/* SCSI bus high impedance */
-#define CTEST4_700_SLBE		0x10	/* SCSI loopback enabled */
-#define CTEST4_800_SRTM		0x10	/* Shadow Register Test Mode */
-#define CTEST4_700_SFWR		0x08	/* SCSI FIFO write enable, 
-					 * redirects writes from SODL
-					 * to the SCSI FIFO.
-					 */
-#define CTEST4_800_MPEE		0x08	/* Enable parity checking
-					   during master cycles on PCI
-					   bus */
-
-/* 
- * These bits send the contents of the CTEST6 register to the appropriate
- * byte lane of the 32 bit DMA FIFO.  Normal operation is zero, otherwise 
- * the high bit means the low two bits select the byte lane.
- */
-#define CTEST4_FBL2		0x04	
-#define CTEST4_FBL1		0x02
-#define CTEST4_FBL0		0x01	
-#define CTEST4_FBL_MASK		0x07
-#define CTEST4_FBL_0		0x04	/* Select DMA FIFO byte lane 0 */
-#define CTEST4_FBL_1		0x05	/* Select DMA FIFO byte lane 1 */
-#define CTEST4_FBL_2		0x06	/* Select DMA FIFO byte lane 2 */
-#define CTEST4_FBL_3		0x07	/* Select DMA FIFO byte lane 3 */
-#define CTEST4_800_SAVE		(CTEST4_800_BDIS)
-
-
-#define CTEST5_REG_700		0x19	/* Chip test 5 rw */
-#define CTEST5_REG_800		0x22	/* Chip test 5 rw */
-/* 
- * Clock Address Incrementor.  When set, it increments the 
- * DNAD register to the next bus size boundary.  It automatically 
- * resets itself when the operation is complete.
- */
-#define CTEST5_ADCK		0x80
-/*
- * Clock Byte Counter.  When set, it decrements the DBC register to
- * the next bus size boundary.
- */
-#define CTEST5_BBCK		0x40
-/*
- * Reset SCSI Offset.  Setting this bit to 1 clears the current offset
- * pointer in the SCSI synchronous offset counter (SSTAT).  This bit
- * is set to 1 if a SCSI Gross Error Condition occurs.  The offset should
- * be cleared when a synchronous transfer fails.  When written, it is 
- * automatically cleared after the SCSI synchronous offset counter is 
- * reset.
- */
-/* Bit 5 is reserved on 800 series chips */
-#define CTEST5_700_ROFF		0x20
-/* 
- * Master Control for Set or Reset pulses. When 1, causes the low 
- * four bits of register to set when set, 0 causes the low bits to
- * clear when set.
- */
-#define CTEST5_MASR 		0x10	
-#define CTEST5_DDIR		0x08	/* DMA direction */
-/*
- * Bits 2-0 are reserved on 800 series chips
- */
-#define CTEST5_700_EOP		0x04	/* End of process */
-#define CTEST5_700_DREQ		0x02	/* Data request */
-#define CTEST5_700_DACK		0x01	/* Data acknowledge */
-
-/* 
- * Chip test 6 rw - writing to this register writes to the byte 
- * lane in the DMA FIFO as determined by the FBL bits in the CTEST4
- * register.
- */
-#define CTEST6_REG_700		0x1a
-#define CTEST6_REG_800		0x23
-
-#define CTEST7_REG		0x1b	/* Chip test 7 rw */
-/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */
-#define CTEST7_10_CDIS		0x80	/* Cache burst disable */
-#define CTEST7_10_SC1		0x40	/* Snoop control bits */
-#define CTEST7_10_SC0		0x20	
-#define CTEST7_10_SC_MASK	0x60
-/* 0x20 is reserved on the NCR53c700 */
-#define CTEST7_0060_FM		0x20	/* Fetch mode */
-#define CTEST7_STD		0x10	/* Selection timeout disable */
-#define CTEST7_DFP		0x08	/* DMA FIFO parity bit for CTEST6 */
-#define CTEST7_EVP		0x04	/* 1 = host bus even parity, 0 = odd */
-#define CTEST7_10_TT1		0x02	/* Transfer type */
-#define CTEST7_00_DC		0x02	/* Set to drive DC low during instruction 
-					   fetch */
-#define CTEST7_DIFF		0x01	/* Differential mode */
-
-#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF )
-
-
-#define TEMP_REG		0x1c	/* through 0x1f Temporary stack rw */
-
-#define DFIFO_REG		0x20	/* DMA FIFO rw */
-/* 
- * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been
- * moved into the CTEST8 register.
- */
-#define DFIFO_00_FLF		0x80	/* Flush DMA FIFO to memory */
-#define DFIFO_00_CLF		0x40	/* Clear DMA and SCSI FIFOs */
-#define DFIFO_BO6		0x40
-#define DFIFO_BO5		0x20
-#define DFIFO_BO4		0x10
-#define DFIFO_BO3		0x08
-#define DFIFO_BO2		0x04 
-#define DFIFO_BO1		0x02
-#define DFIFO_BO0		0x01
-#define DFIFO_10_BO_MASK	0x7f	/* 7 bit counter */
-#define DFIFO_00_BO_MASK	0x3f	/* 6 bit counter */
-
-/* 
- * Interrupt status rw 
- * Note that this is the only register which can be read while SCSI
- * SCRIPTS are being executed.
- */
-#define ISTAT_REG_700		0x21
-#define ISTAT_REG_800		0x14
-#define ISTAT_ABRT		0x80	/* Software abort, write 
-					 *1 to abort, wait for interrupt. */
-/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */
-#define ISTAT_10_SRST		0x40	/* software reset */
-#define ISTAT_10_SIGP		0x20	/* signal script */
-/* 0x10 is reserved on NCR53c700 series chips */
-#define ISTAT_800_SEM		0x10	/* semaphore */
-#define ISTAT_CON		0x08	/* 1 when connected */
-#define ISTAT_800_INTF		0x04	/* Interrupt on the fly */
-#define ISTAT_700_PRE		0x04	/* Pointer register empty.
-					 * Set to 1 when DSPS and DSP
-					 * registers are empty in pipeline
-					 * mode, always set otherwise.
-					 */
-#define ISTAT_SIP		0x02	/* SCSI interrupt pending from
-					 * SCSI portion of SIOP see
-					 * SSTAT0
-					 */
-#define ISTAT_DIP		0x01	/* DMA interrupt pending 
-					 * see DSTAT
-					 */
-
-/* NCR53c700-66 and NCR53c710 only */
-#define CTEST8_REG		0x22	/* Chip test 8 rw */
-#define CTEST8_0066_EAS		0x80	/* Enable alternate SCSI clock,
-					 * ie read from SCLK/ rather than CLK/
-					 */
-#define CTEST8_0066_EFM		0x40	/* Enable fetch and master outputs */
-#define CTEST8_0066_GRP		0x20	/* Generate Receive Parity for 
-					 * pass through.  This insures that 
-					 * bad parity won't reach the host 
-					 * bus.
-					 */
-#define CTEST8_0066_TE		0x10	/* TolerANT enable.  Enable 
-					 * active negation, should only
-					 * be used for slow SCSI 
-					 * non-differential.
-					 */
-#define CTEST8_0066_HSC		0x08	/* Halt SCSI clock */
-#define CTEST8_0066_SRA		0x04	/* Shorten REQ/ACK filtering,
-					 * must be set for fast SCSI-II
-					 * speeds.
-					 */
-#define CTEST8_0066_DAS		0x02	/* Disable automatic target/initiator
-					 * switching.
-					 */
-#define CTEST8_0066_LDE		0x01	/* Last disconnect enable.
-					 * The status of pending 
-					 * disconnect is maintained by
-					 * the core, eliminating
-					 * the possibility of missing a 
-					 * selection or reselection
-					 * while waiting to fetch a 
-					 * WAIT DISCONNECT opcode.
-					 */
-
-#define CTEST8_10_V3		0x80	/* Chip revision */
-#define CTEST8_10_V2		0x40
-#define CTEST8_10_V1		0x20	
-#define CTEST8_10_V0		0x10
-#define CTEST8_10_V_MASK	0xf0	
-#define CTEST8_10_FLF		0x08	/* Flush FIFOs */
-#define CTEST8_10_CLF		0x04	/* Clear FIFOs */
-#define CTEST8_10_FM		0x02	/* Fetch pin mode */
-#define CTEST8_10_SM		0x01	/* Snoop pin mode */
-
-
-/* 
- * The CTEST9 register may be used to differentiate between a
- * NCR53c700 and a NCR53c710.  
- *
- * Write 0xff to this register.
- * Read it.
- * If the contents are 0xff, it is a NCR53c700
- * If the contents are 0x00, it is a NCR53c700-66 first revision
- * If the contents are some other value, it is some other NCR53c700-66
- */
-#define CTEST9_REG_00		0x23	/* Chip test 9 ro */
-#define LCRC_REG_10		0x23	
-
-/*
- * 0x24 through 0x27 are the DMA byte counter register.  Instructions
- * write their high 8 bits into the DCMD register, the low 24 bits into
- * the DBC register.
- *
- * Function is dependent on the command type being executed.
- */
-
- 
-#define DBC_REG			0x24
-/* 
- * For Block Move Instructions, DBC is a 24 bit quantity representing 
- *     the number of bytes to transfer.
- * For Transfer Control Instructions, DBC is bit fielded as follows : 
- */
-/* Bits 20 - 23 should be clear */
-#define DBC_TCI_TRUE		(1 << 19) 	/* Jump when true */
-#define DBC_TCI_COMPARE_DATA	(1 << 18)	/* Compare data */
-#define DBC_TCI_COMPARE_PHASE	(1 << 17)	/* Compare phase with DCMD field */
-#define DBC_TCI_WAIT_FOR_VALID	(1 << 16)	/* Wait for REQ */
-/* Bits 8 - 15 are reserved on some implementations ? */
-#define DBC_TCI_MASK_MASK	0xff00 		/* Mask for data compare */
-#define DBC_TCI_MASK_SHIFT	8
-#define DBC_TCI_DATA_MASK	0xff		/* Data to be compared */ 
-#define DBC_TCI_DATA_SHIFT	0
-
-#define DBC_RWRI_IMMEDIATE_MASK	0xff00		/* Immediate data */
-#define DBC_RWRI_IMMEDIATE_SHIFT 8		/* Amount to shift */
-#define DBC_RWRI_ADDRESS_MASK	0x3f0000	/* Register address */
-#define DBC_RWRI_ADDRESS_SHIFT 	16
-
-
-/*
- * DMA command r/w
- */
-#define DCMD_REG		0x27	
-#define DCMD_TYPE_MASK		0xc0	/* Masks off type */
-#define DCMD_TYPE_BMI		0x00	/* Indicates a Block Move instruction */
-#define DCMD_BMI_IO		0x01	/* I/O, CD, and MSG bits selecting   */
-#define DCMD_BMI_CD		0x02	/* the phase for the block MOVE      */
-#define DCMD_BMI_MSG		0x04	/* instruction 			     */
-
-#define DCMD_BMI_OP_MASK	0x18	/* mask for opcode */
-#define DCMD_BMI_OP_MOVE_T	0x00	/* MOVE */
-#define DCMD_BMI_OP_MOVE_I	0x08	/* MOVE Initiator */
-
-#define DCMD_BMI_INDIRECT	0x20	/*  Indirect addressing */
-
-#define DCMD_TYPE_TCI		0x80	/* Indicates a Transfer Control 
-					   instruction */
-#define DCMD_TCI_IO		0x01	/* I/O, CD, and MSG bits selecting   */
-#define DCMD_TCI_CD		0x02	/* the phase for the block MOVE      */
-#define DCMD_TCI_MSG		0x04	/* instruction 			     */
-#define DCMD_TCI_OP_MASK	0x38	/* mask for opcode */
-#define DCMD_TCI_OP_JUMP	0x00	/* JUMP */
-#define DCMD_TCI_OP_CALL	0x08	/* CALL */
-#define DCMD_TCI_OP_RETURN	0x10	/* RETURN */
-#define DCMD_TCI_OP_INT		0x18	/* INT */
-
-#define DCMD_TYPE_RWRI		0x40	/* Indicates I/O or register Read/Write
-					   instruction */
-#define DCMD_RWRI_OPC_MASK	0x38	/* Opcode mask */
-#define DCMD_RWRI_OPC_WRITE	0x28	/* Write SFBR to register */
-#define DCMD_RWRI_OPC_READ	0x30	/* Read register to SFBR */
-#define DCMD_RWRI_OPC_MODIFY	0x38	/* Modify in place */
-
-#define DCMD_RWRI_OP_MASK	0x07
-#define DCMD_RWRI_OP_MOVE	0x00
-#define DCMD_RWRI_OP_SHL	0x01
-#define DCMD_RWRI_OP_OR		0x02
-#define DCMD_RWRI_OP_XOR	0x03
-#define DCMD_RWRI_OP_AND	0x04
-#define DCMD_RWRI_OP_SHR	0x05
-#define DCMD_RWRI_OP_ADD	0x06
-#define DCMD_RWRI_OP_ADDC	0x07
-
-#define DCMD_TYPE_MMI		0xc0	/* Indicates a Memory Move instruction 
-					   (three words) */
-
-
-#define DNAD_REG		0x28	/* through 0x2b DMA next address for 
-					   data */
-#define DSP_REG			0x2c	/* through 0x2f DMA SCRIPTS pointer rw */
-#define DSPS_REG		0x30	/* through 0x33 DMA SCRIPTS pointer 
-					   save rw */
-#define DMODE_REG_00		0x34 	/* DMA mode rw */
-#define DMODE_00_BL1	0x80	/* Burst length bits */
-#define DMODE_00_BL0	0x40
-#define DMODE_BL_MASK	0xc0
-/* Burst lengths (800) */
-#define DMODE_BL_2	0x00	/* 2 transfer */
-#define DMODE_BL_4	0x40	/* 4 transfers */
-#define DMODE_BL_8	0x80	/* 8 transfers */
-#define DMODE_BL_16	0xc0	/* 16 transfers */
-
-#define DMODE_10_BL_1	0x00	/* 1 transfer */
-#define DMODE_10_BL_2	0x40	/* 2 transfers */
-#define DMODE_10_BL_4	0x80	/* 4 transfers */
-#define DMODE_10_BL_8	0xc0	/* 8 transfers */
-#define DMODE_10_FC2	0x20	/* Driven to FC2 pin */
-#define DMODE_10_FC1	0x10	/* Driven to FC1 pin */
-#define DMODE_710_PD	0x08	/* Program/data on FC0 pin */
-#define DMODE_710_UO	0x02	/* User prog. output */
-
-#define DMODE_700_BW16	0x20	/* Host buswidth = 16 */
-#define DMODE_700_286	0x10	/* 286 mode */
-#define DMODE_700_IOM	0x08	/* Transfer to IO port */
-#define DMODE_700_FAM	0x04	/* Fixed address mode */
-#define DMODE_700_PIPE	0x02	/* Pipeline mode disables 
-					 * automatic fetch / exec 
-					 */
-#define DMODE_MAN	0x01		/* Manual start mode, 
-					 * requires a 1 to be written
-					 * to the start DMA bit in the DCNTL
-					 * register to run scripts 
-					 */
-
-#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 )
-
-/* NCR53c800 series only */
-#define SCRATCHA_REG_800	0x34	/* through 0x37 Scratch A rw */
-/* NCR53c710 only */
-#define SCRATCHB_REG_10		0x34	/* through 0x37 scratch B rw */
-
-#define DMODE_REG_10    	0x38	/* DMA mode rw, NCR53c710 and newer */
-#define DMODE_800_SIOM		0x20	/* Source IO = 1 */
-#define DMODE_800_DIOM		0x10	/* Destination IO = 1 */
-#define DMODE_800_ERL		0x08	/* Enable Read Line */
-
-/* 35-38 are reserved on 700 and 700-66 series chips */
-#define DIEN_REG		0x39	/* DMA interrupt enable rw */
-/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */
-#define DIEN_800_MDPE		0x40	/* Master data parity error */
-#define DIEN_800_BF		0x20	/* BUS fault */
-#define DIEN_700_BF		0x20	/* BUS fault */
-#define DIEN_ABRT		0x10	/* Enable aborted interrupt */
-#define DIEN_SSI		0x08	/* Enable single step interrupt */
-#define DIEN_SIR		0x04	/* Enable SCRIPTS INT command 
-					 * interrupt
-					 */
-/* 0x02 is reserved on 800 series chips */
-#define DIEN_700_WTD		0x02	/* Enable watchdog timeout interrupt */
-#define DIEN_700_OPC		0x01	/* Enable illegal instruction 
-					 * interrupt 
-					 */
-#define DIEN_800_IID		0x01	/*  Same meaning, different name */ 
-
-/*
- * DMA watchdog timer rw
- * set in 16 CLK input periods.
- */
-#define DWT_REG			0x3a
-
-/* DMA control rw */
-#define DCNTL_REG		0x3b
-#define DCNTL_700_CF1		0x80	/* Clock divisor bits */
-#define DCNTL_700_CF0		0x40
-#define DCNTL_700_CF_MASK	0xc0
-/* Clock divisors 			   Divisor SCLK range (MHZ) */
-#define DCNTL_700_CF_2		0x00    /* 2.0	   37.51-50.00 */
-#define DCNTL_700_CF_1_5	0x40	/* 1.5	   25.01-37.50 */
-#define DCNTL_700_CF_1		0x80	/* 1.0     16.67-25.00 */
-#define DCNTL_700_CF_3		0xc0	/* 3.0	   50.01-66.67 (53c700-66) */
-
-#define DCNTL_700_S16		0x20	/* Load scripts 16 bits at a time */
-#define DCNTL_SSM		0x10	/* Single step mode */
-#define DCNTL_700_LLM		0x08	/* Low level mode, can only be set 
-					 * after selection */
-#define DCNTL_800_IRQM		0x08	/* Totem pole IRQ pin */
-#define DCNTL_STD		0x04	/* Start DMA / SCRIPTS */
-/* 0x02 is reserved */
-#define DCNTL_00_RST		0x01	/* Software reset, resets everything
-					 * but 286 mode bit  in DMODE. On the
-					 * NCR53c710, this bit moved to CTEST8
-					 */
-#define DCNTL_10_COM		0x01	/* 700 software compatibility mode */
-#define DCNTL_10_EA		0x20	/* Enable Ack - needed for MVME16x */
-
-#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16)
-
-
-/* NCR53c700-66 only */
-#define SCRATCHB_REG_00		0x3c	/* through 0x3f scratch b rw */
-#define SCRATCHB_REG_800	0x5c	/* through 0x5f scratch b rw */
-/* NCR53c710 only */
-#define ADDER_REG_10		0x3c	/* Adder, NCR53c710 only */
-
-#define SIEN1_REG_800		0x41
-#define SIEN1_800_STO		0x04	/* selection/reselection timeout */
-#define SIEN1_800_GEN		0x02	/* general purpose timer */
-#define SIEN1_800_HTH		0x01	/* handshake to handshake */
-
-#define SIST1_REG_800		0x43
-#define SIST1_800_STO		0x04	/* selection/reselection timeout */
-#define SIST1_800_GEN		0x02	/* general purpose timer */
-#define SIST1_800_HTH		0x01	/* handshake to handshake */
-
-#define SLPAR_REG_800		0x44	/* Parity */
-
-#define MACNTL_REG_800		0x46	/* Memory access control */
-#define MACNTL_800_TYP3		0x80
-#define MACNTL_800_TYP2		0x40
-#define MACNTL_800_TYP1		0x20
-#define MACNTL_800_TYP0		0x10
-#define MACNTL_800_DWR		0x08
-#define MACNTL_800_DRD		0x04
-#define MACNTL_800_PSCPT	0x02
-#define MACNTL_800_SCPTS	0x01
-
-#define GPCNTL_REG_800		0x47	/* General Purpose Pin Control */
-
-/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */
-#define STIME0_REG_800		0x48	/* SCSI Timer Register 0 */
-#define STIME0_800_HTH_MASK	0xf0	/* Handshake to Handshake timeout */
-#define STIME0_800_HTH_SHIFT	4
-#define STIME0_800_SEL_MASK	0x0f	/* Selection timeout */
-#define STIME0_800_SEL_SHIFT	0
-
-#define STIME1_REG_800		0x49
-#define STIME1_800_GEN_MASK	0x0f	/* General purpose timer */
-
-#define RESPID_REG_800		0x4a	/* Response ID, bit fielded.  8
-					   bits on narrow chips, 16 on WIDE */
-
-#define STEST0_REG_800		0x4c	
-#define STEST0_800_SLT		0x08	/* Selection response logic test */
-#define STEST0_800_ART		0x04	/* Arbitration priority encoder test */
-#define STEST0_800_SOZ		0x02	/* Synchronous offset zero */
-#define STEST0_800_SOM		0x01	/* Synchronous offset maximum */
-
-#define STEST1_REG_800		0x4d
-#define STEST1_800_SCLK		0x80	/* Disable SCSI clock */
-
-#define STEST2_REG_800		0x4e	
-#define STEST2_800_SCE		0x80	/* Enable SOCL/SODL */
-#define STEST2_800_ROF		0x40	/* Reset SCSI sync offset */
-#define STEST2_800_SLB		0x10	/* Enable SCSI loopback mode */
-#define STEST2_800_SZM		0x08	/* SCSI high impedance mode */
-#define STEST2_800_EXT		0x02	/* Extend REQ/ACK filter 30 to 60ns */
-#define STEST2_800_LOW		0x01	/* SCSI low level mode */
-
-#define STEST3_REG_800		0x4f	 
-#define STEST3_800_TE		0x80	/* Enable active negation */
-#define STEST3_800_STR		0x40	/* SCSI FIFO test read */
-#define STEST3_800_HSC		0x20	/* Halt SCSI clock */
-#define STEST3_800_DSI		0x10	/* Disable single initiator response */
-#define STEST3_800_TTM		0x04	/* Time test mode */
-#define STEST3_800_CSF		0x02	/* Clear SCSI FIFO */
-#define STEST3_800_STW		0x01	/* SCSI FIFO test write */
-
-#define OPTION_PARITY 		0x1	/* Enable parity checking */
-#define OPTION_TAGGED_QUEUE	0x2	/* Enable SCSI-II tagged queuing */
-#define OPTION_700		0x8	/* Always run NCR53c700 scripts */
-#define OPTION_INTFLY		0x10	/* Use INTFLY interrupts */
-#define OPTION_DEBUG_INTR	0x20	/* Debug interrupts */
-#define OPTION_DEBUG_INIT_ONLY	0x40	/* Run initialization code and 
-					   simple test code, return
-					   DID_NO_CONNECT if any SCSI
-					   commands are attempted. */
-#define OPTION_DEBUG_READ_ONLY	0x80	/* Return DID_ERROR if any 
-					   SCSI write is attempted */
-#define OPTION_DEBUG_TRACE	0x100	/* Animated trace mode, print 
-					   each address and instruction 
-					   executed to debug buffer. */
-#define OPTION_DEBUG_SINGLE	0x200	/* stop after executing one 
-					   instruction */
-#define OPTION_SYNCHRONOUS	0x400	/* Enable sync SCSI.  */
-#define OPTION_MEMORY_MAPPED	0x800	/* NCR registers have valid 
-					   memory mapping */
-#define OPTION_IO_MAPPED	0x1000  /* NCR registers have valid
-					     I/O mapping */
-#define OPTION_DEBUG_PROBE_ONLY	0x2000  /* Probe only, don't even init */
-#define OPTION_DEBUG_TESTS_ONLY	0x4000  /* Probe, init, run selected tests */
-#define OPTION_DEBUG_TEST0	0x08000 /* Run test 0 */
-#define OPTION_DEBUG_TEST1	0x10000 /* Run test 1 */
-#define OPTION_DEBUG_TEST2	0x20000 /* Run test 2 */
-#define OPTION_DEBUG_DUMP	0x40000 /* Dump commands */
-#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */
-#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */
-#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */
-#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */
-#define OPTION_DEBUG_DSA 0x800000
-#define OPTION_DEBUG_CORRUPTION	0x1000000	/* Detect script corruption */
-#define OPTION_DEBUG_SDTR       0x2000000	/* Debug SDTR problem */
-#define OPTION_DEBUG_MISMATCH 	0x4000000 	/* Debug phase mismatches */
-#define OPTION_DISCONNECT	0x8000000	/* Allow disconnect */
-#define OPTION_DEBUG_DISCONNECT 0x10000000	
-#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000	/* Negotiate sync. transfers
-						   on power up */
-#define OPTION_DEBUG_QUEUES	0x80000000	
-#define OPTION_DEBUG_ALLOCATION 0x100000000LL
-#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL	/* Sanity check SXFER and 
-						   SCNTL3 registers */
-#define OPTION_NO_ASYNC	0x400000000LL		/* Don't automagically send
-						   SDTR for async transfers when
-						   we haven't been told to do
-						   a synchronous transfer. */
-#define OPTION_NO_PRINT_RACE 0x800000000LL	/* Don't print message when
-						   the reselect/WAIT DISCONNECT
-						   race condition hits */
-#if !defined(PERM_OPTIONS)
-#define PERM_OPTIONS 0
-#endif
-				
-/*
- * Some data which is accessed by the NCR chip must be 4-byte aligned.
- * For some hosts the default is less than that (eg. 68K uses 2-byte).
- * Alignment has only been forced where it is important; also if one
- * 32 bit structure field is aligned then it is assumed that following
- * 32 bit fields are also aligned.  Take care when adding fields
- * which are other than 32 bit.
- */
-
-struct NCR53c7x0_synchronous {
-    u32 select_indirect			/* Value used for indirect selection */
-	__attribute__ ((aligned (4)));
-    u32 sscf_710;			/* Used to set SSCF bits for 710 */
-    u32 script[8];			/* Size ?? Script used when target is 
-						reselected */
-    unsigned char synchronous_want[5];	/* Per target desired SDTR */
-/* 
- * Set_synchronous programs these, select_indirect and current settings after
- * int_debug_should show a match.
- */
-    unsigned char sxfer_sanity, scntl3_sanity;
-};
-
-#define CMD_FLAG_SDTR 		1	/* Initiating synchronous 
-					   transfer negotiation */
-#define CMD_FLAG_WDTR		2	/* Initiating wide transfer
-					   negotiation */
-#define CMD_FLAG_DID_SDTR	4	/* did SDTR */
-#define CMD_FLAG_DID_WDTR	8	/* did WDTR */
-
-struct NCR53c7x0_table_indirect {
-    u32 count;
-    void *address;
-};
-
-enum ncr_event { 
-    EVENT_NONE = 0,
-/* 
- * Order is IMPORTANT, since these must correspond to the event interrupts
- * in 53c7,8xx.scr 
- */
-
-    EVENT_ISSUE_QUEUE = 0x5000000,	/* 0 Command was added to issue queue */
-    EVENT_START_QUEUE,			/* 1 Command moved to start queue */
-    EVENT_SELECT,			/* 2 Command completed selection */
-    EVENT_DISCONNECT,			/* 3 Command disconnected */
-    EVENT_RESELECT,			/* 4 Command reselected */
-    EVENT_COMPLETE,		        /* 5 Command completed */
-    EVENT_IDLE,				/* 6 */
-    EVENT_SELECT_FAILED,		/* 7 */
-    EVENT_BEFORE_SELECT,		/* 8 */
-    EVENT_RESELECT_FAILED		/* 9 */
-};
-
-struct NCR53c7x0_event {
-    enum ncr_event event;	/* What type of event */
-    unsigned char target;
-    unsigned char lun;
-    struct timeval time;	
-    u32 *dsa;			/* What's in the DSA register now (virt) */
-/* 
- * A few things from that SCSI pid so we know what happened after 
- * the Scsi_Cmnd structure in question may have disappeared.
- */
-    unsigned long pid;		/* The SCSI PID which caused this 
-				   event */
-    unsigned char cmnd[12];
-};
-
-/*
- * Things in the NCR53c7x0_cmd structure are split into two parts :
- *
- * 1.  A fixed portion, for things which are not accessed directly by static NCR
- *	code (ie, are referenced only by the Linux side of the driver,
- *	or only by dynamically generated code).  
- *
- * 2.  The DSA portion, for things which are accessed directly by static NCR
- *	code.
- *
- * This is a little ugly, but it 
- * 1.  Avoids conflicts between the NCR code's picture of the structure, and 
- * 	Linux code's idea of what it looks like.
- *
- * 2.  Minimizes the pain in the Linux side of the code needed 
- * 	to calculate real dsa locations for things, etc.
- * 
- */
-
-struct NCR53c7x0_cmd {
-    void *real;				/* Real, unaligned address for
-					   free function */
-    void (* free)(void *, int);		/* Command to deallocate; NULL
-					   for structures allocated with
-					   scsi_register, etc. */
-    Scsi_Cmnd *cmd;			/* Associated Scsi_Cmnd 
-					   structure, Scsi_Cmnd points
-					   at NCR53c7x0_cmd using 
-					   host_scribble structure */
-
-    int size;				/* scsi_malloc'd size of this 
-					   structure */
-
-    int flags;				/* CMD_* flags */
-
-    unsigned char      cmnd[12];	/* CDB, copied from Scsi_Cmnd */
-    int                result;		/* Copy to Scsi_Cmnd when done */
-
-    struct {				/* Private non-cached bounce buffer */
-        unsigned char buf[256];
-	u32	      addr;
-        u32           len;
-    } bounce;
-
-/*
- * SDTR and WIDE messages are an either/or affair
- * in this message, since we will go into message out and send
- * _the whole mess_ without dropping out of message out to 
- * let the target go into message in after sending the first 
- * message.
- */
-
-    unsigned char select[11];		/* Select message, includes
-					   IDENTIFY
-					   (optional) QUEUE TAG
- 				 	   (optional) SDTR or WDTR
-					 */
-
-
-    volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free,
-					    running, eventually finished */
-    					 
-
-    u32 *data_transfer_start;		/* Start of data transfer routines */
-    u32 *data_transfer_end;		/* Address after end of data transfer o
-    	    	    	    	    	   routines */
-/* 
- * The following three fields were moved from the DSA proper to here
- * since only dynamically generated NCR code refers to them, meaning
- * we don't need dsa_* absolutes, and it is simpler to let the 
- * host code refer to them directly.
- */
-
-/* 
- * HARD CODED : residual and saved_residual need to agree with the sizes
- * used in NCR53c7,8xx.scr.  
- * 
- * FIXME: we want to consider the case where we have odd-length 
- *	scatter/gather buffers and a WIDE transfer, in which case 
- *	we'll need to use the CHAIN MOVE instruction.  Ick.
- */
-    u32 residual[6] __attribute__ ((aligned (4)));
-					/* Residual data transfer which
-					   allows pointer code to work
-					   right.
-
-    	    	    	    	    	    [0-1] : Conditional call to 
-    	    	    	    	    	    	appropriate other transfer 
-    	    	    	    	    	    	routine.
-    	    	    	    	    	    [2-3] : Residual block transfer
-    	    	    	    	    	    	instruction.
-    	    	    	    	    	    [4-5] : Jump to instruction
-    	    	    	    	    	    	after splice.
-					 */
-    u32 saved_residual[6]; 		/* Copy of old residual, so we 
-					   can get another partial 
-					   transfer and still recover 
-    	    	    	    	    	 */
-    	    	
-    u32 saved_data_pointer;		/* Saved data pointer */
-
-    u32 dsa_next_addr;		        /* _Address_ of dsa_next field  
-					   in this dsa for RISCy 
-					   style constant. */
-
-    u32 dsa_addr;			/* Address of dsa; RISCy style
-					   constant */
-
-    u32 dsa[0];				/* Variable length (depending
-					   on host type, number of scatter /
-					   gather buffers, etc).  */
-};
-
-struct NCR53c7x0_break {
-    u32 *address, old_instruction[2];
-    struct NCR53c7x0_break *next;
-    unsigned char old_size;		/* Size of old instruction */
-};
-
-/* Indicates that the NCR is not executing code */
-#define STATE_HALTED	0		
-/* 
- * Indicates that the NCR is executing the wait for select / reselect 
- * script.  Only used when running NCR53c700 compatible scripts, only 
- * state during which an ABORT is _not_ considered an error condition.
- */
-#define STATE_WAITING	1		
-/* Indicates that the NCR is executing other code. */
-#define STATE_RUNNING	2		
-/* 
- * Indicates that the NCR was being aborted.
- */
-#define STATE_ABORTING	3
-/* Indicates that the NCR was successfully aborted. */
-#define STATE_ABORTED 4
-/* Indicates that the NCR has been disabled due to a fatal error */
-#define STATE_DISABLED 5
-
-/* 
- * Where knowledge of SCSI SCRIPT(tm) specified values are needed 
- * in an interrupt handler, an interrupt handler exists for each 
- * different SCSI script so we don't have name space problems.
- * 
- * Return values of these handlers are as follows : 
- */
-#define SPECIFIC_INT_NOTHING 	0	/* don't even restart */
-#define SPECIFIC_INT_RESTART	1	/* restart at the next instruction */
-#define SPECIFIC_INT_ABORT	2	/* recoverable error, abort cmd */
-#define SPECIFIC_INT_PANIC	3	/* unrecoverable error, panic */
-#define SPECIFIC_INT_DONE	4	/* normal command completion */
-#define SPECIFIC_INT_BREAK	5	/* break point encountered */
-
-struct NCR53c7x0_hostdata {
-    int size;				/* Size of entire Scsi_Host
-					   structure */
-    int board;				/* set to board type, useful if 
-					   we have host specific things,
-					   ie, a general purpose I/O 
-					   bit is being used to enable
-					   termination, etc. */
-
-    int chip;				/* set to chip type; 700-66 is
-					   700-66, rest are last three
-					   digits of part number */
-
-    char valid_ids[8];			/* Valid SCSI ID's for adapter */
-
-    u32 *dsp;				/* dsp to restart with after
-					   all stacked interrupts are
-					   handled. */
-
-    unsigned dsp_changed:1;		/* Has dsp changed within this
-					   set of stacked interrupts ? */
-
-    unsigned char dstat;		/* Most recent value of dstat */
-    unsigned dstat_valid:1;
-
-    unsigned expecting_iid:1;		/* Expect IID interrupt */
-    unsigned expecting_sto:1;		/* Expect STO interrupt */
-    
-    /* 
-     * The code stays cleaner if we use variables with function
-     * pointers and offsets that are unique for the different
-     * scripts rather than having a slew of switch(hostdata->chip) 
-     * statements.
-     * 
-     * It also means that the #defines from the SCSI SCRIPTS(tm)
-     * don't have to be visible outside of the script-specific
-     * instructions, preventing name space pollution.
-     */
-
-    void (* init_fixup)(struct Scsi_Host *host);
-    void (* init_save_regs)(struct Scsi_Host *host);
-    void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd);
-    void (* soft_reset)(struct Scsi_Host *host);
-    int (* run_tests)(struct Scsi_Host *host);
-
-    /*
-     * Called when DSTAT_SIR is set, indicating an interrupt generated
-     * by the INT instruction, where values are unique for each SCSI
-     * script.  Should return one of the SPEC_* values.
-     */
-
-    int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
-
-    int dsa_len; /* Size of DSA structure */
-
-    /*
-     * Location of DSA fields for the SCSI SCRIPT corresponding to this 
-     * chip.  
-     */
-
-    s32 dsa_start;			
-    s32 dsa_end;			
-    s32 dsa_next;
-    s32 dsa_prev;
-    s32 dsa_cmnd;
-    s32 dsa_select;
-    s32 dsa_msgout;
-    s32 dsa_cmdout;
-    s32 dsa_dataout;
-    s32 dsa_datain;
-    s32 dsa_msgin;
-    s32 dsa_msgout_other;
-    s32 dsa_write_sync;
-    s32 dsa_write_resume;
-    s32 dsa_check_reselect;
-    s32 dsa_status;
-    s32 dsa_saved_pointer;
-    s32 dsa_jump_dest;
-
-    /* 
-     * Important entry points that generic fixup code needs
-     * to know about, fixed up.
-     */
-
-    s32 E_accept_message;
-    s32 E_command_complete;		
-    s32 E_data_transfer;
-    s32 E_dsa_code_template;
-    s32 E_dsa_code_template_end;
-    s32 E_end_data_transfer;
-    s32 E_msg_in;
-    s32 E_initiator_abort;
-    s32 E_other_transfer;
-    s32 E_other_in;
-    s32 E_other_out;
-    s32 E_target_abort;
-    s32 E_debug_break;	
-    s32 E_reject_message;
-    s32 E_respond_message;
-    s32 E_select;
-    s32 E_select_msgout;
-    s32 E_test_0;
-    s32 E_test_1;
-    s32 E_test_2;
-    s32 E_test_3;
-    s32 E_dsa_zero;
-    s32 E_cmdout_cmdout;
-    s32 E_wait_reselect;
-    s32 E_dsa_code_begin;
-
-    long long options;			/* Bitfielded set of options enabled */
-    volatile u32 test_completed;	/* Test completed */
-    int test_running;			/* Test currently running */
-    s32 test_source
-	__attribute__ ((aligned (4)));
-    volatile s32 test_dest;
-
-    volatile int state;			/* state of driver, only used for 
-					   OPTION_700 */
-
-    unsigned char  dmode;		/* 
-					 * set to the address of the DMODE 
-					 * register for this chip.
-					 */
-    unsigned char istat;		/* 
-    	    	    	    	    	 * set to the address of the ISTAT 
-    	    	    	    	    	 * register for this chip.
-    	    	    	    	    	 */
-  
-    int scsi_clock;			/* 
-					 * SCSI clock in HZ. 0 may be used 
-					 * for unknown, although this will
-					 * disable synchronous negotiation.
-					 */
-
-    volatile int intrs;			/* Number of interrupts */
-    volatile int resets;		/* Number of SCSI resets */
-    unsigned char saved_dmode;	
-    unsigned char saved_ctest4;
-    unsigned char saved_ctest7;
-    unsigned char saved_dcntl;
-    unsigned char saved_scntl3;
-
-    unsigned char this_id_mask;
-
-    /* Debugger information */
-    struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */
-	*breakpoint_current;		/* Current breakpoint being stepped 
-					   through, NULL if we are running 
-					   normally. */
-#ifdef NCR_DEBUG
-    int debug_size;			/* Size of debug buffer */
-    volatile int debug_count;		/* Current data count */
-    volatile char *debug_buf;		/* Output ring buffer */
-    volatile char *debug_write;		/* Current write pointer */
-    volatile char *debug_read;		/* Current read pointer */
-#endif /* def NCR_DEBUG */
-
-    /* XXX - primitive debugging junk, remove when working ? */
-    int debug_print_limit;		/* Number of commands to print
-					   out exhaustive debugging
-					   information for if 
-					   OPTION_DEBUG_DUMP is set */ 
-
-    unsigned char debug_lun_limit[16];	/* If OPTION_DEBUG_TARGET_LIMIT
-					   set, puke if commands are sent
-					   to other target/lun combinations */
-
-    int debug_count_limit;		/* Number of commands to execute
-					   before puking to limit debugging 
-					   output */
-				    
-
-    volatile unsigned idle:1;			/* set to 1 if idle */
-
-    /* 
-     * Table of synchronous+wide transfer parameters set on a per-target
-     * basis.
-     */
-    
-    volatile struct NCR53c7x0_synchronous sync[16]
-	__attribute__ ((aligned (4)));
-
-    volatile Scsi_Cmnd *issue_queue
-	__attribute__ ((aligned (4)));
-						/* waiting to be issued by
-						   Linux driver */
-    volatile struct NCR53c7x0_cmd *running_list;	
-						/* commands running, maintained
-						   by Linux driver */
-
-    volatile struct NCR53c7x0_cmd *ncrcurrent;	/* currently connected 
-						   nexus, ONLY valid for
-						   NCR53c700/NCR53c700-66
-						 */
-
-    volatile struct NCR53c7x0_cmd *spare;	/* pointer to spare,
-    	    	    	    	    	    	   allocated at probe time,
-    	    	    	    	    	    	   which we can use for 
-						   initialization */
-    volatile struct NCR53c7x0_cmd *free;
-    int max_cmd_size;				/* Maximum size of NCR53c7x0_cmd
-					    	   based on number of 
-						   scatter/gather segments, etc.
-						   */
-    volatile int num_cmds;			/* Number of commands 
-						   allocated */
-    volatile int extra_allocate;
-    volatile unsigned char cmd_allocated[16];	/* Have we allocated commands
-						   for this target yet?  If not,
-						   do so ASAP */
-    volatile unsigned char busy[16][8];     	/* number of commands 
-						   executing on each target
-    	    	    	    	    	    	 */
-    /* 
-     * Eventually, I'll switch to a coroutine for calling 
-     * cmd->done(cmd), etc. so that we can overlap interrupt
-     * processing with this code for maximum performance.
-     */
-    
-    volatile struct NCR53c7x0_cmd *finished_queue;	
-						
-    /* Shared variables between SCRIPT and host driver */
-    volatile u32 *schedule
-	__attribute__ ((aligned (4)));		/* Array of JUMPs to dsa_begin
-						   routines of various DSAs.  
-						   When not in use, replace
-						   with jump to next slot */
-
-
-    volatile unsigned char msg_buf[16];		/* buffer for messages
-						   other than the command
-						   complete message */
-
-    /* Per-target default synchronous and WIDE messages */
-    volatile unsigned char synchronous_want[16][5];
-    volatile unsigned char wide_want[16][4];
-
-    /* Bit fielded set of targets we want to speak synchronously with */ 
-    volatile u16 initiate_sdtr;	
-    /* Bit fielded set of targets we want to speak wide with */
-    volatile u16 initiate_wdtr;
-    /* Bit fielded list of targets we've talked to. */
-    volatile u16 talked_to;
-
-    /* Array of bit-fielded lun lists that we need to request_sense */
-    volatile unsigned char request_sense[16];
-
-    u32 addr_reconnect_dsa_head
-	__attribute__ ((aligned (4)));		/* RISCy style constant,
-						   address of following */
-    volatile u32 reconnect_dsa_head;	
-    /* Data identifying nexus we are trying to match during reselection */
-    volatile unsigned char reselected_identify; /* IDENTIFY message */
-    volatile unsigned char reselected_tag;	/* second byte of queue tag 
-						   message or 0 */
-
-    /* These were static variables before we moved them */
-
-    s32 NCR53c7xx_zero
-	__attribute__ ((aligned (4)));
-    s32 NCR53c7xx_sink;
-    u32 NOP_insn;
-    char NCR53c7xx_msg_reject;
-    char NCR53c7xx_msg_abort;
-    char NCR53c7xx_msg_nop;
-
-    /*
-     * Following item introduced by RGH to support NCRc710, which is
-     * VERY brain-dead when it come to memory moves
-     */
-
-			  /* DSA save area used only by the NCR chip */
-    volatile unsigned long saved2_dsa
-	__attribute__ ((aligned (4)));
-
-    volatile unsigned long emulated_intfly
-	__attribute__ ((aligned (4)));
-
-    volatile int event_size, event_index;
-    volatile struct NCR53c7x0_event *events;
-
-    /* If we need to generate code to kill off the currently connected 
-       command, this is where we do it. Should have a BMI instruction
-       to source or sink the current data, followed by a JUMP
-       to abort_connected */
-
-    u32 *abort_script;
-
-    int script_count;				/* Size of script in words */
-    u32 script[0];				/* Relocated SCSI script */
-
-};
-
-#define SCSI_IRQ_NONE	255
-#define DMA_NONE	255
-#define IRQ_AUTO	254
-#define DMA_AUTO	254
-
-#define BOARD_GENERIC	0
-
-#define NCR53c7x0_insn_size(insn)					\
-    (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2)
-    
-
-#define NCR53c7x0_local_declare()					\
-    volatile unsigned char *NCR53c7x0_address_memory;			\
-    unsigned int NCR53c7x0_address_io;					\
-    int NCR53c7x0_memory_mapped
-
-#define NCR53c7x0_local_setup(host)					\
-    NCR53c7x0_address_memory = (void *) (host)->base;			\
-    NCR53c7x0_address_io = (unsigned int) (host)->io_port;		\
-    NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *) 		\
-	host->hostdata[0])-> options & OPTION_MEMORY_MAPPED 
-
-#ifdef BIG_ENDIAN
-/* These could be more efficient, given that we are always memory mapped,
- * but they don't give the same problems as the write macros, so leave
- * them. */
-#ifdef __mc68000__
-#define NCR53c7x0_read8(address) 					\
-    ((unsigned int)raw_inb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) )
-
-#define NCR53c7x0_read16(address) 					\
-    ((unsigned int)raw_inw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)))
-#else
-#define NCR53c7x0_read8(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) :	\
-	inb(NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_read16(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) :	\
-	inw(NCR53c7x0_address_io + (address)))
-#endif /* mc68000 */
-#else
-#define NCR53c7x0_read8(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readb((u32)NCR53c7x0_address_memory + (u32)(address)) :	\
-	inb(NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_read16(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int)readw((u32)NCR53c7x0_address_memory + (u32)(address)) :	\
-	inw(NCR53c7x0_address_io + (address)))
-#endif
-
-#ifdef __mc68000__
-#define NCR53c7x0_read32(address) 					\
-    ((unsigned int) raw_inl((u32)NCR53c7x0_address_memory + (u32)(address)))
-#else
-#define NCR53c7x0_read32(address) 					\
-    (NCR53c7x0_memory_mapped ? 						\
-	(unsigned int) readl((u32)NCR53c7x0_address_memory + (u32)(address)) : 	\
-	inl(NCR53c7x0_address_io + (address)))
-#endif /* mc68000*/
-
-#ifdef BIG_ENDIAN
-/* If we are big-endian, then we are not Intel, so probably don't have
- * an i/o map as well as a memory map.  So, let's assume memory mapped.
- * Also, I am having terrible problems trying to persuade the compiler
- * not to lay down code which does a read after write for these macros.
- * If you remove 'volatile' from writeb() and friends it is ok....
- */
-
-#define NCR53c7x0_write8(address,value) 				\
-	*(volatile unsigned char *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) = (value)
-
-#define NCR53c7x0_write16(address,value) 				\
-	*(volatile unsigned short *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) = (value)
-
-#define NCR53c7x0_write32(address,value) 				\
-	*(volatile unsigned long *)					\
-		((u32)NCR53c7x0_address_memory + ((u32)(address))) = (value)
-
-#else
-
-#define NCR53c7x0_write8(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writeb((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outb((value), NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_write16(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writew((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outw((value), NCR53c7x0_address_io + (address)))
-
-#define NCR53c7x0_write32(address,value) 				\
-    (NCR53c7x0_memory_mapped ? 						\
-     ({writel((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :	\
-	outl((value), NCR53c7x0_address_io + (address)))
-
-#endif
-
-/* Patch arbitrary 32 bit words in the script */
-#define patch_abs_32(script, offset, symbol, value)			\
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i) {					\
-	    (script)[A_##symbol##_used[i] - (offset)] += (value);	\
-	    if (hostdata->options & OPTION_DEBUG_FIXUP) 		\
-	      printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\
-		host->host_no, #symbol, i, A_##symbol##_used[i] - 	\
-		(int)(offset), #script, (script)[A_##symbol##_used[i] -	\
-		(offset)]);						\
-    	}
-
-/* Patch read/write instruction immediate field */
-#define patch_abs_rwri_data(script, offset, symbol, value)		\
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i)					\
-    	    (script)[A_##symbol##_used[i] - (offset)] =			\
-	    	((script)[A_##symbol##_used[i] - (offset)] & 		\
-	    	~DBC_RWRI_IMMEDIATE_MASK) | 				\
-    	    	(((value) << DBC_RWRI_IMMEDIATE_SHIFT) &		\
-		 DBC_RWRI_IMMEDIATE_MASK)
-
-/* Patch transfer control instruction data field */
-#define patch_abs_tci_data(script, offset, symbol, value)	        \
-    	for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof 		\
-    	    (u32)); ++i)					\
-    	    (script)[A_##symbol##_used[i] - (offset)] =			\
-	    	((script)[A_##symbol##_used[i] - (offset)] & 		\
-	    	~DBC_TCI_DATA_MASK) | 					\
-    	    	(((value) << DBC_TCI_DATA_SHIFT) &			\
-		 DBC_TCI_DATA_MASK)
-
-/* Patch field in dsa structure (assignment should be +=?) */
-#define patch_dsa_32(dsa, symbol, word, value)				\
-	{								\
-	(dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32)	\
-	    + (word)] = (value);					\
-	if (hostdata->options & OPTION_DEBUG_DSA)			\
-	    printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n",	\
-		#dsa, #symbol, hostdata->##symbol, 			\
-		(word), (u32) (value));					\
-	}
-
-/* Paranoid people could use panic() here. */
-#define FATAL(host) shutdown((host));
-
-extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
-			  unsigned long base, int io_port, int irq, int dma,
-			  long long options, int clock);
-
-#endif /* NCR53c710_C */
-#endif /* NCR53c710_H */
diff --git a/drivers/scsi/53c7xx.scr b/drivers/scsi/53c7xx.scr
deleted file mode 100644
index 9c5694a..0000000
--- a/drivers/scsi/53c7xx.scr
+++ /dev/null
@@ -1,1591 +0,0 @@
-#undef DEBUG
-#undef EVENTS
-#undef NO_SELECTION_TIMEOUT
-#define BIG_ENDIAN
-
-; 53c710 driver.  Modified from Drew Eckhardts driver
-; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-;
-; I have left the script for the 53c8xx family in here, as it is likely
-; to be useful to see what I changed when bug hunting.
-
-; NCR 53c810 driver, main script
-; Sponsored by 
-;	iX Multiuser Multitasking Magazine
-;	hm@ix.de
-;
-; Copyright 1993, 1994, 1995 Drew Eckhardt
-;      Visionary Computing 
-;      (Unix and Linux consulting and custom programming)
-;      drew@PoohSticks.ORG
-;      +1 (303) 786-7975
-;
-; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-;
-; PRE-ALPHA
-;
-; For more information, please consult 
-;
-; NCR 53C810
-; PCI-SCSI I/O Processor
-; Data Manual
-;
-; NCR 53C710 
-; SCSI I/O Processor
-; Programmers Guide
-;
-; NCR Microelectronics
-; 1635 Aeroplaza Drive
-; Colorado Springs, CO 80916
-; 1+ (719) 578-3400
-;
-; Toll free literature number
-; +1 (800) 334-5454
-;
-; IMPORTANT : This code is self modifying due to the limitations of 
-;	the NCR53c7,8xx series chips.  Persons debugging this code with
-;	the remote debugger should take this into account, and NOT set
-;	breakpoints in modified instructions.
-;
-; Design:
-; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
-; microcontroller using a simple instruction set.   
-;
-; So, to minimize the effects of interrupt latency, and to maximize 
-; throughput, this driver offloads the practical maximum amount 
-; of processing to the SCSI chip while still maintaining a common
-; structure.
-;
-; Where tradeoffs were needed between efficiency on the older
-; chips and the newer NCR53c800 series, the NCR53c800 series 
-; was chosen.
-;
-; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
-; automate SCSI transfers without host processor intervention, this 
-; isn't the case with the NCR53c710 and newer chips which allow 
-;
-; - reads and writes to the internal registers from within the SCSI
-; 	scripts, allowing the SCSI SCRIPTS(tm) code to save processor
-; 	state so that multiple threads of execution are possible, and also
-; 	provide an ALU for loop control, etc.
-; 
-; - table indirect addressing for some instructions. This allows 
-;	pointers to be located relative to the DSA ((Data Structure
-;	Address) register.
-;
-; These features make it possible to implement a mailbox style interface,
-; where the same piece of code is run to handle I/O for multiple threads
-; at once minimizing our need to relocate code.  Since the NCR53c700/
-; NCR53c800 series have a unique combination of features, making a 
-; a standard ingoing/outgoing mailbox system, costly, I've modified it.
-;
-; - Mailboxes are a mixture of code and data.  This lets us greatly
-; 	simplify the NCR53c810 code and do things that would otherwise
-;	not be possible.
-;
-; The saved data pointer is now implemented as follows :
-;
-; 	Control flow has been architected such that if control reaches
-;	munge_save_data_pointer, on a restore pointers message or 
-;	reconnection, a jump to the address formerly in the TEMP register
-;	will allow the SCSI command to resume execution.
-;
-
-;
-; Note : the DSA structures must be aligned on 32 bit boundaries,
-; since the source and destination of MOVE MEMORY instructions 
-; must share the same alignment and this is the alignment of the
-; NCR registers.
-;
-
-; For some systems (MVME166, for example) dmode is always the same, so don't
-; waste time writing it
-
-#if 1
-#define DMODE_MEMORY_TO_NCR
-#define DMODE_MEMORY_TO_MEMORY
-#define DMODE_NCR_TO_MEMORY
-#else
-#define DMODE_MEMORY_TO_NCR    MOVE dmode_memory_to_ncr TO DMODE
-#define DMODE_MEMORY_TO_MEMORY MOVE dmode_memory_to_memory TO DMODE
-#define DMODE_NCR_TO_MEMORY    MOVE dmode_ncr_to_memory TO DMODE
-#endif
-
-ABSOLUTE dsa_temp_lun = 0		; Patch to lun for current dsa
-ABSOLUTE dsa_temp_next = 0		; Patch to dsa next for current dsa
-ABSOLUTE dsa_temp_addr_next = 0		; Patch to address of dsa next address 
-					; 	for current dsa
-ABSOLUTE dsa_temp_sync = 0		; Patch to address of per-target
-					;	sync routine
-ABSOLUTE dsa_sscf_710 = 0		; Patch to address of per-target
-					;	sscf value (53c710)
-ABSOLUTE dsa_temp_target = 0		; Patch to id for current dsa
-ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
-					; 	saved data pointer
-ABSOLUTE dsa_temp_addr_residual = 0	; Patch to address of per-command
-					;	current residual code
-ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
-					; saved residual code
-ABSOLUTE dsa_temp_addr_new_value = 0	; Address of value for JUMP operand
-ABSOLUTE dsa_temp_addr_array_value = 0 	; Address to copy to
-ABSOLUTE dsa_temp_addr_dsa_value = 0	; Address of this DSA value
-
-;
-; Once a device has initiated reselection, we need to compare it 
-; against the singly linked list of commands which have disconnected
-; and are pending reselection.  These commands are maintained in 
-; an unordered singly linked list of DSA structures, through the
-; DSA pointers at their 'centers' headed by the reconnect_dsa_head
-; pointer.
-; 
-; To avoid complications in removing commands from the list,
-; I minimize the amount of expensive (at eight operations per
-; addition @ 500-600ns each) pointer operations which must
-; be done in the NCR driver by precomputing them on the 
-; host processor during dsa structure generation.
-;
-; The fixed-up per DSA code knows how to recognize the nexus
-; associated with the corresponding SCSI command, and modifies
-; the source and destination pointers for the MOVE MEMORY 
-; instruction which is executed when reselected_ok is called
-; to remove the command from the list.  Similarly, DSA is 
-; loaded with the address of the next DSA structure and
-; reselected_check_next is called if a failure occurs.
-;
-; Perhaps more concisely, the net effect of the mess is 
-;
-; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
-;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
-; 	src = &dsa->next;
-; 	if (target_id == dsa->id && target_lun == dsa->lun) {
-; 		*dest = *src;
-; 		break;
-;         }	
-; }
-;
-; if (!dsa)
-;           error (int_err_unexpected_reselect);
-; else  
-;     longjmp (dsa->jump_resume, 0);
-;
-; 	
-
-#if (CHIP != 700) && (CHIP != 70066)
-; Define DSA structure used for mailboxes
-ENTRY dsa_code_template
-dsa_code_template:
-ENTRY dsa_code_begin
-dsa_code_begin:
-; RGH: Don't care about TEMP and DSA here
-	DMODE_MEMORY_TO_NCR
-	MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-	; We are about to go and select the device, so must set SSCF bits
-	MOVE MEMORY 4, dsa_sscf_710, addr_scratch
-#ifdef BIG_ENDIAN
-	MOVE SCRATCH3 TO SFBR
-#else
-	MOVE SCRATCH0 TO SFBR
-#endif
-	MOVE SFBR TO SBCL
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#else
-	CALL scratch_to_dsa
-#endif
-	CALL select
-; Handle the phase mismatch which may have resulted from the 
-; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
-; may or may not be necessary, and we should update script_asm.pl
-; to handle multiple pieces.
-    CLEAR ATN
-    CLEAR ACK
-
-; Replace second operand with address of JUMP instruction dest operand
-; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
-ENTRY dsa_code_fix_jump
-dsa_code_fix_jump:
-	MOVE MEMORY 4, NOP_insn, 0
-	JUMP select_done
-
-; wrong_dsa loads the DSA register with the value of the dsa_next
-; field.
-;
-wrong_dsa:
-#if (CHIP == 710)
-;                NOTE DSA is corrupt when we arrive here!
-#endif
-;		Patch the MOVE MEMORY INSTRUCTION such that 
-;		the destination address is the address of the OLD 
-;		next pointer.
-;
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
-	DMODE_MEMORY_TO_NCR
-;
-; 	Move the _contents_ of the next pointer into the DSA register as 
-;	the next I_T_L or I_T_L_Q tupple to check against the established
-;	nexus.
-;
-	MOVE MEMORY 4, dsa_temp_next, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#else
-	CALL scratch_to_dsa
-#endif
-	JUMP reselected_check_next
-
-ABSOLUTE dsa_save_data_pointer = 0
-ENTRY dsa_code_save_data_pointer
-dsa_code_save_data_pointer:
-#if (CHIP == 710)
-	; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
-	; We MUST return with DSA correct
-    	MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_saved
-#endif
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-	JUMP jump_temp
-#else
-    	DMODE_NCR_TO_MEMORY
-    	MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
-    	DMODE_MEMORY_TO_MEMORY
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_saved
-#endif
-    	RETURN
-#endif
-ABSOLUTE dsa_restore_pointers = 0
-ENTRY dsa_code_restore_pointers
-dsa_code_restore_pointers:
-#if (CHIP == 710)
-	; TEMP and DSA are corrupt when we get here, but who cares!
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-        CLEAR ACK
-	; Restore DSA, note we don't care about TEMP
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#ifdef DEBUG
-        INT int_debug_restored
-#endif
-	JUMP jump_temp
-#else
-    	DMODE_MEMORY_TO_NCR
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
-    	DMODE_MEMORY_TO_MEMORY
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-        CLEAR ACK
-#ifdef DEBUG
-        INT int_debug_restored
-#endif
-    	RETURN
-#endif
-
-ABSOLUTE dsa_check_reselect = 0
-; dsa_check_reselect determines whether or not the current target and
-; lun match the current DSA
-ENTRY dsa_code_check_reselect
-dsa_code_check_reselect:
-#if (CHIP == 710)
-	/* Arrives here with DSA correct */
-	/* Assumes we are always ID 7 */
-	MOVE LCRC TO SFBR		; LCRC has our ID and his ID bits set
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
-#else
-	MOVE SSID TO SFBR		; SSID contains 3 bit target ID
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
-#endif
-;
-; Hack - move to scratch first, since SFBR is not writeable
-; 	via the CPU and hence a MOVE MEMORY instruction.
-;
-	DMODE_MEMORY_TO_NCR
-	MOVE MEMORY 1, reselected_identify, addr_scratch
-	DMODE_MEMORY_TO_MEMORY
-#ifdef BIG_ENDIAN
-	; BIG ENDIAN ON MVME16x
-	MOVE SCRATCH3 TO SFBR
-#else
-	MOVE SCRATCH0 TO SFBR
-#endif
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-; Are you sure about that?  richard@sleepie.demon.co.uk
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
-;		Patch the MOVE MEMORY INSTRUCTION such that
-;		the source address is the address of this dsa's
-;		next pointer.
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
-	CALL reselected_ok
-#if (CHIP == 710)
-;	Restore DSA following memory moves in reselected_ok
-;	dsa_temp_sync doesn't really care about DSA, but it has an
-;	optional debug INT so a valid DSA is a good idea.
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-	CALL dsa_temp_sync	
-; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
-; transfer parameters! 
-	CLEAR ACK
-; Implicitly restore pointers on reselection, so a RETURN
-; will transfer control back to the right spot.
-    	CALL REL (dsa_code_restore_pointers)
-    	RETURN
-ENTRY dsa_zero
-dsa_zero:
-ENTRY dsa_code_template_end
-dsa_code_template_end:
-
-; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
-; dsa_zero, puke.
-
-ABSOLUTE dsa_fields_start =  0	; Sanity marker
-				; 	pad 48 bytes (fix this RSN)
-ABSOLUTE dsa_next = 48		; len 4 Next DSA
- 				; del 4 Previous DSA address
-ABSOLUTE dsa_cmnd = 56		; len 4 Scsi_Cmnd * for this thread.
-ABSOLUTE dsa_select = 60	; len 4 Device ID, Period, Offset for 
-			 	;	table indirect select
-ABSOLUTE dsa_msgout = 64	; len 8 table indirect move parameter for 
-				;       select message
-ABSOLUTE dsa_cmdout = 72	; len 8 table indirect move parameter for 
-				;	command
-ABSOLUTE dsa_dataout = 80	; len 4 code pointer for dataout
-ABSOLUTE dsa_datain = 84	; len 4 code pointer for datain
-ABSOLUTE dsa_msgin = 88		; len 8 table indirect move for msgin
-ABSOLUTE dsa_status = 96 	; len 8 table indirect move for status byte
-ABSOLUTE dsa_msgout_other = 104	; len 8 table indirect for normal message out
-				; (Synchronous transfer negotiation, etc).
-ABSOLUTE dsa_end = 112
-
-ABSOLUTE schedule = 0 		; Array of JUMP dsa_begin or JUMP (next),
-				; terminated by a call to JUMP wait_reselect
-
-; Linked lists of DSA structures
-ABSOLUTE reconnect_dsa_head = 0	; Link list of DSAs which can reconnect
-ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
-				; address of reconnect_dsa_head
-
-; These select the source and destination of a MOVE MEMORY instruction
-ABSOLUTE dmode_memory_to_memory = 0x0
-ABSOLUTE dmode_memory_to_ncr = 0x0
-ABSOLUTE dmode_ncr_to_memory = 0x0
-
-ABSOLUTE addr_scratch = 0x0
-ABSOLUTE addr_temp = 0x0
-#if (CHIP == 710)
-ABSOLUTE saved_dsa = 0x0
-ABSOLUTE emulfly = 0x0
-ABSOLUTE addr_dsa = 0x0
-#endif
-#endif /* CHIP != 700 && CHIP != 70066 */
-
-; Interrupts - 
-; MSB indicates type
-; 0	handle error condition
-; 1 	handle message 
-; 2 	handle normal condition
-; 3	debugging interrupt
-; 4 	testing interrupt 
-; Next byte indicates specific error
-
-; XXX not yet implemented, I'm not sure if I want to - 
-; Next byte indicates the routine the error occurred in
-; The LSB indicates the specific place the error occurred
- 
-ABSOLUTE int_err_unexpected_phase = 0x00000000	; Unexpected phase encountered
-ABSOLUTE int_err_selected = 0x00010000		; SELECTED (nee RESELECTED)
-ABSOLUTE int_err_unexpected_reselect = 0x00020000 
-ABSOLUTE int_err_check_condition = 0x00030000	
-ABSOLUTE int_err_no_phase = 0x00040000
-ABSOLUTE int_msg_wdtr = 0x01000000		; WDTR message received
-ABSOLUTE int_msg_sdtr = 0x01010000		; SDTR received
-ABSOLUTE int_msg_1 = 0x01020000			; single byte special message
-						; received
-
-ABSOLUTE int_norm_select_complete = 0x02000000	; Select complete, reprogram
-						; registers.
-ABSOLUTE int_norm_reselect_complete = 0x02010000	; Nexus established
-ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
-ABSOLUTE int_norm_disconnected = 0x02030000	; Disconnected 
-ABSOLUTE int_norm_aborted =0x02040000		; Aborted *dsa
-ABSOLUTE int_norm_reset = 0x02050000		; Generated BUS reset.
-ABSOLUTE int_norm_emulateintfly = 0x02060000	; 53C710 Emulated intfly
-ABSOLUTE int_debug_break = 0x03000000		; Break point
-#ifdef DEBUG
-ABSOLUTE int_debug_scheduled = 0x03010000	; new I/O scheduled 
-ABSOLUTE int_debug_idle = 0x03020000		; scheduler is idle
-ABSOLUTE int_debug_dsa_loaded = 0x03030000	; dsa reloaded
-ABSOLUTE int_debug_reselected = 0x03040000	; NCR reselected
-ABSOLUTE int_debug_head = 0x03050000		; issue head overwritten
-ABSOLUTE int_debug_disconnected = 0x03060000	; disconnected
-ABSOLUTE int_debug_disconnect_msg = 0x03070000	; got message to disconnect
-ABSOLUTE int_debug_dsa_schedule = 0x03080000	; in dsa_schedule
-ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
-ABSOLUTE int_debug_reselected_ok = 0x030a0000 	; Reselection accepted
-#endif
-ABSOLUTE int_debug_panic = 0x030b0000		; Panic driver
-#ifdef DEBUG
-ABSOLUTE int_debug_saved = 0x030c0000 		; save/restore pointers
-ABSOLUTE int_debug_restored = 0x030d0000
-ABSOLUTE int_debug_sync = 0x030e0000		; Sanity check synchronous 
-						; parameters. 
-ABSOLUTE int_debug_datain = 0x030f0000		; going into data in phase 
-						; now.
-ABSOLUTE int_debug_check_dsa = 0x03100000	; Sanity check DSA against
-						; SDID.
-#endif
-
-ABSOLUTE int_test_1 = 0x04000000		; Test 1 complete
-ABSOLUTE int_test_2 = 0x04010000		; Test 2 complete
-ABSOLUTE int_test_3 = 0x04020000		; Test 3 complete
-
-
-; These should start with 0x05000000, with low bits incrementing for 
-; each one.
-
-#ifdef EVENTS
-ABSOLUTE int_EVENT_SELECT = 0
-ABSOLUTE int_EVENT_DISCONNECT = 0
-ABSOLUTE int_EVENT_RESELECT = 0
-ABSOLUTE int_EVENT_COMPLETE = 0
-ABSOLUTE int_EVENT_IDLE = 0
-ABSOLUTE int_EVENT_SELECT_FAILED = 0
-ABSOLUTE int_EVENT_BEFORE_SELECT = 0
-ABSOLUTE int_EVENT_RESELECT_FAILED = 0
-#endif
-						
-ABSOLUTE NCR53c7xx_msg_abort = 0	; Pointer to abort message
-ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
-ABSOLUTE NCR53c7xx_zero	= 0		; long with zero in it, use for source
-ABSOLUTE NCR53c7xx_sink = 0		; long to dump worthless data in
-ABSOLUTE NOP_insn = 0			; NOP instruction
-
-; Pointer to message, potentially multi-byte
-ABSOLUTE msg_buf = 0
-
-; Pointer to holding area for reselection information
-ABSOLUTE reselected_identify = 0
-ABSOLUTE reselected_tag = 0
-
-; Request sense command pointer, it's a 6 byte command, should
-; be constant for all commands since we always want 16 bytes of 
-; sense and we don't need to change any fields as we did under 
-; SCSI-I when we actually cared about the LUN field.
-;EXTERNAL NCR53c7xx_sense		; Request sense command
-
-#if (CHIP != 700) && (CHIP != 70066)
-; dsa_schedule  
-; PURPOSE : after a DISCONNECT message has been received, and pointers
-;	saved, insert the current DSA structure at the head of the 
-; 	disconnected queue and fall through to the scheduler.
-;
-; CALLS : OK
-;
-; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
-;	of disconnected commands
-;
-; MODIFIES : SCRATCH, reconnect_dsa_head
-; 
-; EXITS : always passes control to schedule
-
-ENTRY dsa_schedule
-dsa_schedule:
-#ifdef DEBUG
-    INT int_debug_dsa_schedule
-#endif
-
-;
-; Calculate the address of the next pointer within the DSA 
-; structure of the command that is currently disconnecting
-;
-#if (CHIP == 710)
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_next TO SCRATCH0
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
-
-; Point the next field of this DSA structure at the current disconnected 
-; list
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
-    DMODE_MEMORY_TO_MEMORY
-dsa_schedule_insert:
-    MOVE MEMORY 4, reconnect_dsa_head, 0 
-
-; And update the head pointer.
-#if (CHIP == 710)
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
-    DMODE_MEMORY_TO_MEMORY
-/* Temporarily, see what happens. */
-#ifndef ORIGINAL
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-#endif
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-    WAIT DISCONNECT
-#ifdef EVENTS
-    INT int_EVENT_DISCONNECT;
-#endif
-#ifdef DEBUG
-    INT int_debug_disconnected
-#endif
-    JUMP schedule
-#endif 
-
-;
-; select
-;
-; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
-;	On success, the current DSA structure is removed from the issue 
-;	queue.  Usually, this is entered as a fall-through from schedule,
-;	although the contingent allegiance handling code will write
-;	the select entry address to the DSP to restart a command as a 
-;	REQUEST SENSE.  A message is sent (usually IDENTIFY, although
-;	additional SDTR or WDTR messages may be sent).  COMMAND OUT
-;	is handled.
-;
-; INPUTS : DSA - SCSI command, issue_dsa_head
-;
-; CALLS : NOT OK
-;
-; MODIFIES : SCRATCH, issue_dsa_head
-;
-; EXITS : on reselection or selection, go to select_failed
-;	otherwise, RETURN so control is passed back to 
-;	dsa_begin.
-;
-
-ENTRY select
-select:
-
-#ifdef EVENTS
-    INT int_EVENT_BEFORE_SELECT
-#endif
-
-#ifdef DEBUG
-    INT int_debug_scheduled
-#endif
-    CLEAR TARGET
-
-; XXX
-;
-; In effect, SELECTION operations are backgrounded, with execution
-; continuing until code which waits for REQ or a fatal interrupt is 
-; encountered.
-;
-; So, for more performance, we could overlap the code which removes 
-; the command from the NCRs issue queue with the selection, but 
-; at this point I don't want to deal with the error recovery.
-;
-
-#if (CHIP != 700) && (CHIP != 70066)
-#if (CHIP == 710)
-    ; Enable selection timer
-#ifdef NO_SELECTION_TIMEOUT
-    MOVE CTEST7 & 0xff TO CTEST7
-#else
-    MOVE CTEST7 & 0xef TO CTEST7
-#endif
-#endif
-    SELECT ATN FROM dsa_select, select_failed
-    JUMP select_msgout, WHEN MSG_OUT
-ENTRY select_msgout
-select_msgout:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    MOVE FROM dsa_msgout, WHEN MSG_OUT
-#else
-ENTRY select_msgout
-    SELECT ATN 0, select_failed
-select_msgout:
-    MOVE 0, 0, WHEN MSGOUT
-#endif
-
-#ifdef EVENTS
-   INT int_EVENT_SELECT
-#endif
-   RETURN
-
-; 
-; select_done
-; 
-; PURPOSE: continue on to normal data transfer; called as the exit 
-;	point from dsa_begin.
-;
-; INPUTS: dsa
-;
-; CALLS: OK
-;
-;
-
-select_done:
-#if (CHIP == 710)
-; NOTE DSA is corrupt when we arrive here!
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-
-#ifdef DEBUG
-ENTRY select_check_dsa
-select_check_dsa:
-    INT int_debug_check_dsa
-#endif
-
-; After a successful selection, we should get either a CMD phase or 
-; some transfer request negotiation message.
-
-    JUMP cmdout, WHEN CMD
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
-
-select_msg_in:
-    CALL msg_in, WHEN MSG_IN
-    JUMP select_msg_in, WHEN MSG_IN
-
-cmdout:
-    INT int_err_unexpected_phase, WHEN NOT CMD
-#if (CHIP == 700)
-    INT int_norm_selected
-#endif
-ENTRY cmdout_cmdout
-cmdout_cmdout:
-#if (CHIP != 700) && (CHIP != 70066)
-    MOVE FROM dsa_cmdout, WHEN CMD
-#else
-    MOVE 0, 0, WHEN CMD
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-;
-; data_transfer  
-; other_out
-; other_in
-; other_transfer
-;
-; PURPOSE : handle the main data transfer for a SCSI command in 
-;	several parts.  In the first part, data_transfer, DATA_IN
-;	and DATA_OUT phases are allowed, with the user provided
-;	code (usually dynamically generated based on the scatter/gather
-;	list associated with a SCSI command) called to handle these 
-;	phases.
-;
-;	After control has passed to one of the user provided 
-;	DATA_IN or DATA_OUT routines, back calls are made to 
-;	other_transfer_in or other_transfer_out to handle non-DATA IN
-;	and DATA OUT phases respectively, with the state of the active
-;	data pointer being preserved in TEMP.
-;
-;	On completion, the user code passes control to other_transfer
-;	which causes DATA_IN and DATA_OUT to result in unexpected_phase
-;	interrupts so that data overruns may be trapped.
-;
-; INPUTS : DSA - SCSI command
-;
-; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
-;	other_transfer
-;
-; MODIFIES : SCRATCH
-;
-; EXITS : if STATUS IN is detected, signifying command completion,
-;	the NCR jumps to command_complete.  If MSG IN occurs, a 
-;	CALL is made to msg_in.  Otherwise, other_transfer runs in 
-;	an infinite loop.
-;	
-
-ENTRY data_transfer
-data_transfer:
-    JUMP cmdout_cmdout, WHEN CMD
-    CALL msg_in, WHEN MSG_IN
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    JUMP do_dataout, WHEN DATA_OUT
-    JUMP do_datain, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP data_transfer
-ENTRY end_data_transfer
-end_data_transfer:
-
-;
-; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
-; should be fixed up whenever the nexus changes so it can point to the 
-; correct routine for that command.
-;
-
-#if (CHIP != 700) && (CHIP != 70066)
-; Nasty jump to dsa->dataout
-do_dataout:
-#if (CHIP == 710)
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0	
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
-    DMODE_MEMORY_TO_MEMORY
-dataout_to_jump:
-    MOVE MEMORY 4, 0, dataout_jump + 4 
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-dataout_jump:
-    JUMP 0
-
-; Nasty jump to dsa->dsain
-do_datain:
-#if (CHIP == 710)
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-#else
-    CALL dsa_to_scratch
-#endif
-    MOVE SCRATCH0 + dsa_datain TO SCRATCH0	
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
-    DMODE_MEMORY_TO_MEMORY
-ENTRY datain_to_jump
-datain_to_jump:
-    MOVE MEMORY 4, 0, datain_jump + 4
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-#ifdef DEBUG
-    INT int_debug_datain
-#endif
-datain_jump:
-    JUMP 0
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-
-; Note that other_out and other_in loop until a non-data phase
-; is discovered, so we only execute return statements when we
-; can go on to the next data phase block move statement.
-
-ENTRY other_out
-other_out:
-#if 0
-    INT 0x03ffdead
-#endif
-    INT int_err_unexpected_phase, WHEN CMD
-    JUMP msg_in_restart, WHEN MSG_IN 
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP other_out, WHEN NOT DATA_OUT
-#if (CHIP == 710)
-; TEMP should be OK, as we got here from a call in the user dataout code.
-#endif
-    RETURN
-
-ENTRY other_in
-other_in:
-#if 0
-    INT 0x03ffdead
-#endif
-    INT int_err_unexpected_phase, WHEN CMD
-    JUMP msg_in_restart, WHEN MSG_IN 
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-    JUMP command_complete, WHEN STATUS
-    JUMP other_in, WHEN NOT DATA_IN
-#if (CHIP == 710)
-; TEMP should be OK, as we got here from a call in the user datain code.
-#endif
-    RETURN
-
-
-ENTRY other_transfer
-other_transfer:
-    INT int_err_unexpected_phase, WHEN CMD
-    CALL msg_in, WHEN MSG_IN
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-    INT int_err_unexpected_phase, WHEN DATA_IN
-    JUMP command_complete, WHEN STATUS
-    JUMP other_transfer
-
-;
-; msg_in_restart
-; msg_in
-; munge_msg
-;
-; PURPOSE : process messages from a target.  msg_in is called when the 
-;	caller hasn't read the first byte of the message.  munge_message
-;	is called when the caller has read the first byte of the message,
-;	and left it in SFBR.  msg_in_restart is called when the caller 
-;	hasn't read the first byte of the message, and wishes RETURN
-;	to transfer control back to the address of the conditional
-;	CALL instruction rather than to the instruction after it.
-;
-;	Various int_* interrupts are generated when the host system
-;	needs to intervene, as is the case with SDTR, WDTR, and
-;	INITIATE RECOVERY messages.
-;
-;	When the host system handles one of these interrupts,
-;	it can respond by reentering at reject_message, 
-;	which rejects the message and returns control to
-;	the caller of msg_in or munge_msg, accept_message
-;	which clears ACK and returns control, or reply_message
-;	which sends the message pointed to by the DSA 
-;	msgout_other table indirect field.
-;
-;	DISCONNECT messages are handled by moving the command
-;	to the reconnect_dsa_queue.
-#if (CHIP == 710)
-; NOTE: DSA should be valid when we get here - we cannot save both it
-;	and TEMP in this routine.
-#endif
-;
-; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
-;	only)
-;
-; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
-;
-; MODIFIES : SCRATCH, DSA on DISCONNECT
-;
-; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
-;	and normal return from message handlers running under
-;	Linux, control is returned to the caller.  Receipt
-;	of DISCONNECT messages pass control to dsa_schedule.
-;
-ENTRY msg_in_restart
-msg_in_restart:
-; XXX - hackish
-;
-; Since it's easier to debug changes to the statically 
-; compiled code, rather than the dynamically generated 
-; stuff, such as
-;
-; 	MOVE x, y, WHEN data_phase
-; 	CALL other_z, WHEN NOT data_phase
-; 	MOVE x, y, WHEN data_phase
-;
-; I'd like to have certain routines (notably the message handler)
-; restart on the conditional call rather than the next instruction.
-;
-; So, subtract 8 from the return address
-
-    MOVE TEMP0 + 0xf8 TO TEMP0
-    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
-    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
-    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
-
-ENTRY msg_in
-msg_in:
-    MOVE 1, msg_buf, WHEN MSG_IN
-
-munge_msg:
-    JUMP munge_extended, IF 0x01		; EXTENDED MESSAGE
-    JUMP munge_2, IF 0x20, AND MASK 0xdf	; two byte message
-;
-; XXX - I've seen a handful of broken SCSI devices which fail to issue
-; 	a SAVE POINTERS message before disconnecting in the middle of 
-; 	a transfer, assuming that the DATA POINTER will be implicitly 
-; 	restored.  
-;
-; Historically, I've often done an implicit save when the DISCONNECT
-; message is processed.  We may want to consider having the option of 
-; doing that here. 
-;
-    JUMP munge_save_data_pointer, IF 0x02	; SAVE DATA POINTER
-    JUMP munge_restore_pointers, IF 0x03	; RESTORE POINTERS 
-    JUMP munge_disconnect, IF 0x04		; DISCONNECT
-    INT int_msg_1, IF 0x07			; MESSAGE REJECT
-    INT int_msg_1, IF 0x0f			; INITIATE RECOVERY
-#ifdef EVENTS 
-    INT int_EVENT_SELECT_FAILED 
-#endif
-    JUMP reject_message
-
-munge_2:
-    JUMP reject_message
-;
-; The SCSI standard allows targets to recover from transient 
-; error conditions by backing up the data pointer with a 
-; RESTORE POINTERS message.  
-;	
-; So, we must save and restore the _residual_ code as well as 
-; the current instruction pointer.  Because of this messiness,
-; it is simpler to put dynamic code in the dsa for this and to
-; just do a simple jump down there. 
-;
-
-munge_save_data_pointer:
-#if (CHIP == 710)
-    ; We have something in TEMP here, so first we must save that
-    MOVE TEMP0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE TEMP1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE TEMP2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE TEMP3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, jump_temp + 4
-    ; Now restore DSA
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-    MOVE DSA0 + dsa_save_data_pointer TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH3
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
-    DMODE_MEMORY_TO_MEMORY
-jump_dsa_save:
-    JUMP 0
-
-munge_restore_pointers:
-#if (CHIP == 710)
-    ; The code at dsa_restore_pointers will RETURN, but we don't care
-    ; about TEMP here, as it will overwrite it anyway.
-#endif
-    MOVE DSA0 + dsa_restore_pointers TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-    MOVE SFBR TO SCRATCH3
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
-    DMODE_MEMORY_TO_MEMORY
-jump_dsa_restore:
-    JUMP 0
-
-
-munge_disconnect:
-#ifdef DEBUG
-    INT int_debug_disconnect_msg
-#endif
-
-/* 
- * Before, we overlapped processing with waiting for disconnect, but
- * debugging was beginning to appear messy.  Temporarily move things
- * to just before the WAIT DISCONNECT.
- */
- 
-#ifdef ORIGINAL
-#if (CHIP == 710)
-; Following clears Unexpected Disconnect bit.  What do we do?
-#else
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-#endif
-
-#if (CHIP != 700) && (CHIP != 70066)
-    JUMP dsa_schedule
-#else
-    WAIT DISCONNECT
-    INT int_norm_disconnected
-#endif
-
-munge_extended:
-    CLEAR ACK
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN
-    MOVE 1, msg_buf + 1, WHEN MSG_IN
-    JUMP munge_extended_2, IF 0x02
-    JUMP munge_extended_3, IF 0x03 
-    JUMP reject_message
-
-munge_extended_2:
-    CLEAR ACK
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-    JUMP reject_message, IF NOT 0x02	; Must be WDTR
-    CLEAR ACK
-    MOVE 1, msg_buf + 3, WHEN MSG_IN
-    INT int_msg_wdtr
-
-munge_extended_3:
-    CLEAR ACK
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-    JUMP reject_message, IF NOT 0x01	; Must be SDTR
-    CLEAR ACK
-    MOVE 2, msg_buf + 3, WHEN MSG_IN
-    INT int_msg_sdtr
-
-ENTRY reject_message
-reject_message:
-    SET ATN
-    CLEAR ACK
-    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
-    RETURN
-
-ENTRY accept_message
-accept_message:
-    CLEAR ATN
-    CLEAR ACK
-    RETURN
-
-ENTRY respond_message
-respond_message:
-    SET ATN
-    CLEAR ACK
-    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
-    RETURN
-
-;
-; command_complete
-;
-; PURPOSE : handle command termination when STATUS IN is detected by reading
-;	a status byte followed by a command termination message. 
-;
-;	Normal termination results in an INTFLY instruction, and 
-;	the host system can pick out which command terminated by 
-;	examining the MESSAGE and STATUS buffers of all currently 
-;	executing commands;
-;
-;	Abnormal (CHECK_CONDITION) termination results in an
-;	int_err_check_condition interrupt so that a REQUEST SENSE
-;	command can be issued out-of-order so that no other command
-;	clears the contingent allegiance condition.
-;	
-;
-; INPUTS : DSA - command	
-;
-; CALLS : OK
-;
-; EXITS : On successful termination, control is passed to schedule.
-;	On abnormal termination, the user will usually modify the 
-;	DSA fields and corresponding buffers and return control
-;	to select.
-;
-
-ENTRY command_complete
-command_complete:
-    MOVE FROM dsa_status, WHEN STATUS
-#if (CHIP != 700) && (CHIP != 70066)
-    MOVE SFBR TO SCRATCH0		; Save status
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-ENTRY command_complete_msgin
-command_complete_msgin:
-    MOVE FROM dsa_msgin, WHEN MSG_IN
-; Indicate that we should be expecting a disconnect
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#else
-    ; Above code cleared the Unexpected Disconnect bit, what do we do?
-#endif
-    CLEAR ACK
-#if (CHIP != 700) && (CHIP != 70066)
-    WAIT DISCONNECT
-
-;
-; The SCSI specification states that when a UNIT ATTENTION condition
-; is pending, as indicated by a CHECK CONDITION status message,
-; the target shall revert to asynchronous transfers.  Since
-; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
-; basis, and returning control to our scheduler could work on a command
-; running on another lun on that target using the old parameters, we must
-; interrupt the host processor to get them changed, or change them ourselves.
-;
-; Once SCSI-II tagged queueing is implemented, things will be even more
-; hairy, since contingent allegiance conditions exist on a per-target/lun
-; basis, and issuing a new command with a different tag would clear it.
-; In these cases, we must interrupt the host processor to get a request 
-; added to the HEAD of the queue with the request sense command, or we
-; must automatically issue the request sense command.
-
-#if 0
-    MOVE SCRATCH0 TO SFBR			
-    JUMP command_failed, IF 0x02
-#endif
-#if (CHIP == 710)
-#if defined(MVME16x_INTFLY)
-; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
-; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
-; schedule, which corrupts it anyway.  Will probably remove this later,
-; but want to check performance effects first.
-
-#define INTFLY_ADDR     0xfff40070
-
-    MOVE 0 TO SCRATCH0
-    MOVE 0x80 TO SCRATCH1
-    MOVE 0 TO SCRATCH2
-    MOVE 0 TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, INTFLY_ADDR
-#else
-    INT int_norm_emulateintfly
-#endif
-#else
-    INTFLY
-#endif
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-#ifdef EVENTS
-    INT int_EVENT_COMPLETE
-#endif
-#if (CHIP != 700) && (CHIP != 70066)
-    JUMP schedule
-command_failed:
-    INT int_err_check_condition
-#else
-    INT int_norm_command_complete
-#endif
-
-;
-; wait_reselect
-;
-; PURPOSE : This is essentially the idle routine, where control lands
-;	when there are no new processes to schedule.  wait_reselect
-;	waits for reselection, selection, and new commands.
-;
-;	When a successful reselection occurs, with the aid 
-;	of fixed up code in each DSA, wait_reselect walks the 
-;	reconnect_dsa_queue, asking each dsa if the target ID
-;	and LUN match its.
-;
-;	If a match is found, a call is made back to reselected_ok,
-;	which through the miracles of self modifying code, extracts
-;	the found DSA from the reconnect_dsa_queue and then 
-;	returns control to the DSAs thread of execution.
-;
-; INPUTS : NONE
-;
-; CALLS : OK
-;
-; MODIFIES : DSA,
-;
-; EXITS : On successful reselection, control is returned to the 
-;	DSA which called reselected_ok.  If the WAIT RESELECT
-;	was interrupted by a new commands arrival signaled by 
-;	SIG_P, control is passed to schedule.  If the NCR is 
-;	selected, the host system is interrupted with an 
-;	int_err_selected which is usually responded to by
-;	setting DSP to the target_abort address.
-
-ENTRY wait_reselect
-wait_reselect:
-#ifdef EVENTS
-    int int_EVENT_IDLE
-#endif
-#ifdef DEBUG
-    int int_debug_idle
-#endif
-    WAIT RESELECT wait_reselect_failed
-
-reselected:
-#ifdef EVENTS
-    int int_EVENT_RESELECT
-#endif
-    CLEAR TARGET
-    DMODE_MEMORY_TO_MEMORY
-    ; Read all data needed to reestablish the nexus - 
-    MOVE 1, reselected_identify, WHEN MSG_IN
-    ; We used to CLEAR ACK here.
-#if (CHIP != 700) && (CHIP != 70066)
-#ifdef DEBUG
-    int int_debug_reselected
-#endif
-
-    ; Point DSA at the current head of the disconnected queue.
-    DMODE_MEMORY_TO_NCR
-    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
-    DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-    MOVE MEMORY 4, addr_scratch, saved_dsa
-#else
-    CALL scratch_to_dsa
-#endif
-
-    ; Fix the update-next pointer so that the reconnect_dsa_head
-    ; pointer is the one that will be updated if this DSA is a hit 
-    ; and we remove it from the queue.
-
-    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-
-ENTRY reselected_check_next
-reselected_check_next:
-#ifdef DEBUG
-    INT int_debug_reselect_check
-#endif
-    ; Check for a NULL pointer.
-    MOVE DSA0 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA1 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA2 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    MOVE DSA3 TO SFBR
-    JUMP reselected_not_end, IF NOT 0
-    INT int_err_unexpected_reselect
-
-reselected_not_end:
-    ;
-    ; XXX the ALU is only eight bits wide, and the assembler
-    ; wont do the dirt work for us.  As long as dsa_check_reselect
-    ; is negative, we need to sign extend with 1 bits to the full
-    ; 32 bit width of the address.
-    ;
-    ; A potential work around would be to have a known alignment 
-    ; of the DSA structure such that the base address plus 
-    ; dsa_check_reselect doesn't require carrying from bytes 
-    ; higher than the LSB.
-    ;
-
-    MOVE DSA0 TO SFBR
-    MOVE SFBR + dsa_check_reselect TO SCRATCH0
-    MOVE DSA1 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
-    MOVE DSA2 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
-    MOVE DSA3 TO SFBR
-    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
-
-    DMODE_NCR_TO_MEMORY
-    MOVE MEMORY 4, addr_scratch, reselected_check + 4
-    DMODE_MEMORY_TO_MEMORY
-#if (CHIP == 710)
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-#endif
-reselected_check:
-    JUMP 0
-
-
-;
-;
-#if (CHIP == 710)
-; We have problems here - the memory move corrupts TEMP and DSA.  This
-; routine is called from DSA code, and patched from many places.  Scratch
-; is probably free when it is called.
-; We have to:
-;   copy temp to scratch, one byte at a time
-;   write scratch to patch a jump in place of the return
-;   do the move memory
-;   jump to the patched in return address
-; DSA is corrupt when we get here, and can be left corrupt
-
-ENTRY reselected_ok
-reselected_ok:
-    MOVE TEMP0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE TEMP1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE TEMP2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE TEMP3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0
-reselected_ok_jump:
-    JUMP 0
-#else
-ENTRY reselected_ok
-reselected_ok:
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0				; Patched : first word
-						; 	is address of 
-						;       successful dsa_next
-						; Second word is last 
-						;	unsuccessful dsa_next,
-						;	starting with 
-						;       dsa_reconnect_head
-    ; We used to CLEAR ACK here.
-#ifdef DEBUG
-    INT int_debug_reselected_ok
-#endif
-#ifdef DEBUG
-    INT int_debug_check_dsa
-#endif
-    RETURN					; Return control to where
-#endif
-#else
-    INT int_norm_reselected
-#endif /* (CHIP != 700) && (CHIP != 70066) */
-
-selected:
-    INT int_err_selected;
-
-;
-; A select or reselect failure can be caused by one of two conditions : 
-; 1.  SIG_P was set.  This will be the case if the user has written
-;	a new value to a previously NULL head of the issue queue.
-;
-; 2.  The NCR53c810 was selected or reselected by another device.
-;
-; 3.  The bus was already busy since we were selected or reselected
-;	before starting the command.
-
-wait_reselect_failed:
-#ifdef EVENTS 
-	INT int_EVENT_RESELECT_FAILED
-#endif
-; Check selected bit.  
-#if (CHIP == 710)
-    ; Must work out how to tell if we are selected....
-#else
-    MOVE SIST0 & 0x20 TO SFBR
-    JUMP selected, IF 0x20
-#endif
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-    JUMP schedule, IF 0x40
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-    MOVE ISTAT & 0x08 TO SFBR
-    JUMP reselected, IF 0x08
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-#if 0
-    JUMP schedule
-#else
-    INT int_debug_panic
-#endif
-
-
-select_failed:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-#ifdef EVENTS
-  int int_EVENT_SELECT_FAILED
-#endif
-; Otherwise, mask the selected and reselected bits off SIST0
-#if (CHIP ==710)
-    ; Let's assume we don't get selected for now
-    MOVE SSTAT0 & 0x10 TO SFBR
-#else
-    MOVE SIST0 & 0x30 TO SFBR
-    JUMP selected, IF 0x20
-#endif
-    JUMP reselected, IF 0x10 
-; If SIGP is set, the user just gave us another command, and
-; we should restart or return to the scheduler.
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-    JUMP select, IF 0x40
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-; FIXME: is this really necessary? 
-    MOVE ISTAT & 0x08 TO SFBR
-    JUMP reselected, IF 0x08
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-#if 0
-    JUMP schedule
-#else
-    INT int_debug_panic
-#endif
-
-;
-; test_1
-; test_2
-;
-; PURPOSE : run some verification tests on the NCR.  test_1
-;	copies test_src to test_dest and interrupts the host
-;	processor, testing for cache coherency and interrupt
-; 	problems in the processes.
-;
-;	test_2 runs a command with offsets relative to the 
-;	DSA on entry, and is useful for miscellaneous experimentation.
-;
-
-; Verify that interrupts are working correctly and that we don't 
-; have a cache invalidation problem.
-
-ABSOLUTE test_src = 0, test_dest = 0
-ENTRY test_1
-test_1:
-    MOVE MEMORY 4, test_src, test_dest
-    INT int_test_1
-
-;
-; Run arbitrary commands, with test code establishing a DSA
-;
- 
-ENTRY test_2
-test_2:
-    CLEAR TARGET
-#if (CHIP == 710)
-    ; Enable selection timer
-#ifdef NO_SELECTION_TIMEOUT
-    MOVE CTEST7 & 0xff TO CTEST7
-#else
-    MOVE CTEST7 & 0xef TO CTEST7
-#endif
-#endif
-    SELECT ATN FROM 0, test_2_fail
-    JUMP test_2_msgout, WHEN MSG_OUT
-ENTRY test_2_msgout
-test_2_msgout:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    MOVE FROM 8, WHEN MSG_OUT
-    MOVE FROM 16, WHEN CMD 
-    MOVE FROM 24, WHEN DATA_IN
-    MOVE FROM 32, WHEN STATUS
-    MOVE FROM 40, WHEN MSG_IN
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    CLEAR ACK
-    WAIT DISCONNECT
-test_2_fail:
-#if (CHIP == 710)
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-#endif
-    INT int_test_2
-
-ENTRY debug_break
-debug_break:
-    INT int_debug_break
-
-;
-; initiator_abort
-; target_abort
-;
-; PURPOSE : Abort the currently established nexus from with initiator
-;	or target mode.
-;
-;  
-
-ENTRY target_abort
-target_abort:
-    SET TARGET
-    DISCONNECT
-    CLEAR TARGET
-    JUMP schedule
-    
-ENTRY initiator_abort
-initiator_abort:
-    SET ATN
-;
-; The SCSI-I specification says that targets may go into MSG out at 
-; their leisure upon receipt of the ATN single.  On all versions of the 
-; specification, we can't change phases until REQ transitions true->false, 
-; so we need to sink/source one byte of data to allow the transition.
-;
-; For the sake of safety, we'll only source one byte of data in all 
-; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
-; arbitrary number of bytes.
-    JUMP spew_cmd, WHEN CMD
-    JUMP eat_msgin, WHEN MSG_IN
-    JUMP eat_datain, WHEN DATA_IN
-    JUMP eat_status, WHEN STATUS
-    JUMP spew_dataout, WHEN DATA_OUT
-    JUMP sated
-spew_cmd:
-    MOVE 1, NCR53c7xx_zero, WHEN CMD
-    JUMP sated
-eat_msgin:
-    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
-    JUMP eat_msgin, WHEN MSG_IN
-    JUMP sated
-eat_status:
-    MOVE 1, NCR53c7xx_sink, WHEN STATUS
-    JUMP eat_status, WHEN STATUS
-    JUMP sated
-eat_datain:
-    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
-    JUMP eat_datain, WHEN DATA_IN
-    JUMP sated
-spew_dataout:
-    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
-sated:
-#if (CHIP != 710)
-    MOVE SCNTL2 & 0x7f TO SCNTL2
-#endif
-    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
-    WAIT DISCONNECT
-    INT int_norm_aborted
-
-#if (CHIP != 710)
-;
-; dsa_to_scratch
-; scratch_to_dsa
-;
-; PURPOSE :
-; 	The NCR chips cannot do a move memory instruction with the DSA register 
-; 	as the source or destination.  So, we provide a couple of subroutines
-; 	that let us switch between the DSA register and scratch register.
-;
-; 	Memory moves to/from the DSPS  register also don't work, but we 
-; 	don't use them.
-;
-;
-
- 
-dsa_to_scratch:
-    MOVE DSA0 TO SFBR
-    MOVE SFBR TO SCRATCH0
-    MOVE DSA1 TO SFBR
-    MOVE SFBR TO SCRATCH1
-    MOVE DSA2 TO SFBR
-    MOVE SFBR TO SCRATCH2
-    MOVE DSA3 TO SFBR
-    MOVE SFBR TO SCRATCH3
-    RETURN
-
-scratch_to_dsa:
-    MOVE SCRATCH0 TO SFBR
-    MOVE SFBR TO DSA0
-    MOVE SCRATCH1 TO SFBR
-    MOVE SFBR TO DSA1
-    MOVE SCRATCH2 TO SFBR
-    MOVE SFBR TO DSA2
-    MOVE SCRATCH3 TO SFBR
-    MOVE SFBR TO DSA3
-    RETURN
-#endif
- 
-#if (CHIP == 710)
-; Little patched jump, used to overcome problems with TEMP getting
-; corrupted on memory moves.
-
-jump_temp:
-    JUMP 0
-#endif
diff --git a/drivers/scsi/53c7xx_d.h_shipped b/drivers/scsi/53c7xx_d.h_shipped
deleted file mode 100644
index 21d31b0..0000000
--- a/drivers/scsi/53c7xx_d.h_shipped
+++ /dev/null
@@ -1,2874 +0,0 @@
-/* DO NOT EDIT - Generated automatically by script_asm.pl */
-static u32 SCRIPT[] = {
-/*
-
-
-
-
-
-; 53c710 driver.  Modified from Drew Eckhardts driver
-; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-;
-; I have left the script for the 53c8xx family in here, as it is likely
-; to be useful to see what I changed when bug hunting.
-
-; NCR 53c810 driver, main script
-; Sponsored by 
-;	iX Multiuser Multitasking Magazine
-;	hm@ix.de
-;
-; Copyright 1993, 1994, 1995 Drew Eckhardt
-;      Visionary Computing 
-;      (Unix and Linux consulting and custom programming)
-;      drew@PoohSticks.ORG
-;      +1 (303) 786-7975
-;
-; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-;
-; PRE-ALPHA
-;
-; For more information, please consult 
-;
-; NCR 53C810
-; PCI-SCSI I/O Processor
-; Data Manual
-;
-; NCR 53C710 
-; SCSI I/O Processor
-; Programmers Guide
-;
-; NCR Microelectronics
-; 1635 Aeroplaza Drive
-; Colorado Springs, CO 80916
-; 1+ (719) 578-3400
-;
-; Toll free literature number
-; +1 (800) 334-5454
-;
-; IMPORTANT : This code is self modifying due to the limitations of 
-;	the NCR53c7,8xx series chips.  Persons debugging this code with
-;	the remote debugger should take this into account, and NOT set
-;	breakpoints in modified instructions.
-;
-; Design:
-; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
-; microcontroller using a simple instruction set.   
-;
-; So, to minimize the effects of interrupt latency, and to maximize 
-; throughput, this driver offloads the practical maximum amount 
-; of processing to the SCSI chip while still maintaining a common
-; structure.
-;
-; Where tradeoffs were needed between efficiency on the older
-; chips and the newer NCR53c800 series, the NCR53c800 series 
-; was chosen.
-;
-; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
-; automate SCSI transfers without host processor intervention, this 
-; isn't the case with the NCR53c710 and newer chips which allow 
-;
-; - reads and writes to the internal registers from within the SCSI
-; 	scripts, allowing the SCSI SCRIPTS(tm) code to save processor
-; 	state so that multiple threads of execution are possible, and also
-; 	provide an ALU for loop control, etc.
-; 
-; - table indirect addressing for some instructions. This allows 
-;	pointers to be located relative to the DSA ((Data Structure
-;	Address) register.
-;
-; These features make it possible to implement a mailbox style interface,
-; where the same piece of code is run to handle I/O for multiple threads
-; at once minimizing our need to relocate code.  Since the NCR53c700/
-; NCR53c800 series have a unique combination of features, making a 
-; a standard ingoing/outgoing mailbox system, costly, I've modified it.
-;
-; - Mailboxes are a mixture of code and data.  This lets us greatly
-; 	simplify the NCR53c810 code and do things that would otherwise
-;	not be possible.
-;
-; The saved data pointer is now implemented as follows :
-;
-; 	Control flow has been architected such that if control reaches
-;	munge_save_data_pointer, on a restore pointers message or 
-;	reconnection, a jump to the address formerly in the TEMP register
-;	will allow the SCSI command to resume execution.
-;
-
-;
-; Note : the DSA structures must be aligned on 32 bit boundaries,
-; since the source and destination of MOVE MEMORY instructions 
-; must share the same alignment and this is the alignment of the
-; NCR registers.
-;
-
-; For some systems (MVME166, for example) dmode is always the same, so don't
-; waste time writing it
-
-
-
-
-
-
-
-
-
-
-
-ABSOLUTE dsa_temp_lun = 0		; Patch to lun for current dsa
-ABSOLUTE dsa_temp_next = 0		; Patch to dsa next for current dsa
-ABSOLUTE dsa_temp_addr_next = 0		; Patch to address of dsa next address 
-					; 	for current dsa
-ABSOLUTE dsa_temp_sync = 0		; Patch to address of per-target
-					;	sync routine
-ABSOLUTE dsa_sscf_710 = 0		; Patch to address of per-target
-					;	sscf value (53c710)
-ABSOLUTE dsa_temp_target = 0		; Patch to id for current dsa
-ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
-					; 	saved data pointer
-ABSOLUTE dsa_temp_addr_residual = 0	; Patch to address of per-command
-					;	current residual code
-ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
-					; saved residual code
-ABSOLUTE dsa_temp_addr_new_value = 0	; Address of value for JUMP operand
-ABSOLUTE dsa_temp_addr_array_value = 0 	; Address to copy to
-ABSOLUTE dsa_temp_addr_dsa_value = 0	; Address of this DSA value
-
-;
-; Once a device has initiated reselection, we need to compare it 
-; against the singly linked list of commands which have disconnected
-; and are pending reselection.  These commands are maintained in 
-; an unordered singly linked list of DSA structures, through the
-; DSA pointers at their 'centers' headed by the reconnect_dsa_head
-; pointer.
-; 
-; To avoid complications in removing commands from the list,
-; I minimize the amount of expensive (at eight operations per
-; addition @ 500-600ns each) pointer operations which must
-; be done in the NCR driver by precomputing them on the 
-; host processor during dsa structure generation.
-;
-; The fixed-up per DSA code knows how to recognize the nexus
-; associated with the corresponding SCSI command, and modifies
-; the source and destination pointers for the MOVE MEMORY 
-; instruction which is executed when reselected_ok is called
-; to remove the command from the list.  Similarly, DSA is 
-; loaded with the address of the next DSA structure and
-; reselected_check_next is called if a failure occurs.
-;
-; Perhaps more concisely, the net effect of the mess is 
-;
-; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
-;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
-; 	src = &dsa->next;
-; 	if (target_id == dsa->id && target_lun == dsa->lun) {
-; 		*dest = *src;
-; 		break;
-;         }	
-; }
-;
-; if (!dsa)
-;           error (int_err_unexpected_reselect);
-; else  
-;     longjmp (dsa->jump_resume, 0);
-;
-; 	
-
-
-; Define DSA structure used for mailboxes
-ENTRY dsa_code_template
-dsa_code_template:
-ENTRY dsa_code_begin
-dsa_code_begin:
-; RGH: Don't care about TEMP and DSA here
-	
-	MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
-
-at 0x00000000 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	
-
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x00000003 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	; We are about to go and select the device, so must set SSCF bits
-	MOVE MEMORY 4, dsa_sscf_710, addr_scratch
-
-at 0x00000006 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-	MOVE SCRATCH3 TO SFBR
-
-at 0x00000009 : */	0x72370000,0x00000000,
-/*
-
-
-
-	MOVE SFBR TO SBCL
-
-at 0x0000000b : */	0x6a0b0000,0x00000000,
-/*
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000000d : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	CALL select
-
-at 0x00000010 : */	0x88080000,0x000001f8,
-/*
-; Handle the phase mismatch which may have resulted from the 
-; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
-; may or may not be necessary, and we should update script_asm.pl
-; to handle multiple pieces.
-    CLEAR ATN
-
-at 0x00000012 : */	0x60000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000014 : */	0x60000040,0x00000000,
-/*
-
-; Replace second operand with address of JUMP instruction dest operand
-; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
-ENTRY dsa_code_fix_jump
-dsa_code_fix_jump:
-	MOVE MEMORY 4, NOP_insn, 0
-
-at 0x00000016 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	JUMP select_done
-
-at 0x00000019 : */	0x80080000,0x00000230,
-/*
-
-; wrong_dsa loads the DSA register with the value of the dsa_next
-; field.
-;
-wrong_dsa:
-
-;                NOTE DSA is corrupt when we arrive here!
-
-;		Patch the MOVE MEMORY INSTRUCTION such that 
-;		the destination address is the address of the OLD 
-;		next pointer.
-;
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
-
-at 0x0000001b : */	0xc0000004,0x00000000,0x000007ec,
-/*
-	
-;
-; 	Move the _contents_ of the next pointer into the DSA register as 
-;	the next I_T_L or I_T_L_Q tupple to check against the established
-;	nexus.
-;
-	MOVE MEMORY 4, dsa_temp_next, addr_scratch
-
-at 0x0000001e : */	0xc0000004,0x00000000,0x00000000,
-/*
-	
-
-	MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x00000021 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000024 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	JUMP reselected_check_next
-
-at 0x00000027 : */	0x80080000,0x000006f0,
-/*
-
-ABSOLUTE dsa_save_data_pointer = 0
-ENTRY dsa_code_save_data_pointer
-dsa_code_save_data_pointer:
-
-	; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
-	; We MUST return with DSA correct
-    	MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
-
-at 0x00000029 : */	0xc0000004,0x000009c8,0x00000000,
-/*
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
-
-at 0x0000002c : */	0xc0000018,0x00000000,0x00000000,
-/*
-        CLEAR ACK
-
-at 0x0000002f : */	0x60000040,0x00000000,
-/*
-
-
-
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000031 : */	0xc0000004,0x00000000,0x00000000,
-/*
-	JUMP jump_temp
-
-at 0x00000034 : */	0x80080000,0x000009c4,
-/*
-
-ABSOLUTE dsa_restore_pointers = 0
-ENTRY dsa_code_restore_pointers
-dsa_code_restore_pointers:
-
-	; TEMP and DSA are corrupt when we get here, but who cares!
-    	MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
-
-at 0x00000036 : */	0xc0000004,0x00000000,0x000009c8,
-/*
-; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
-    	MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
-
-at 0x00000039 : */	0xc0000018,0x00000000,0x00000000,
-/*
-        CLEAR ACK
-
-at 0x0000003c : */	0x60000040,0x00000000,
-/*
-	; Restore DSA, note we don't care about TEMP
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000003e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-	JUMP jump_temp
-
-at 0x00000041 : */	0x80080000,0x000009c4,
-/*
-
-
-ABSOLUTE dsa_check_reselect = 0
-; dsa_check_reselect determines whether or not the current target and
-; lun match the current DSA
-ENTRY dsa_code_check_reselect
-dsa_code_check_reselect:
-
-	
-	
-	MOVE LCRC TO SFBR		; LCRC has our ID and his ID bits set
-
-at 0x00000043 : */	0x72230000,0x00000000,
-/*
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
-
-at 0x00000045 : */	0x80848000,0x00ffff50,
-/*
-
-
-
-
-
-;
-; Hack - move to scratch first, since SFBR is not writeable
-; 	via the CPU and hence a MOVE MEMORY instruction.
-;
-	
-	MOVE MEMORY 1, reselected_identify, addr_scratch
-
-at 0x00000047 : */	0xc0000001,0x00000000,0x00000000,
-/*
-	
-
-	; BIG ENDIAN ON MVME16x
-	MOVE SCRATCH3 TO SFBR
-
-at 0x0000004a : */	0x72370000,0x00000000,
-/*
-
-
-
-; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
-; Are you sure about that?  richard@sleepie.demon.co.uk
-	JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
-
-at 0x0000004c : */	0x8084f800,0x00ffff34,
-/*
-;		Patch the MOVE MEMORY INSTRUCTION such that
-;		the source address is the address of this dsa's
-;		next pointer.
-	MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
-
-at 0x0000004e : */	0xc0000004,0x00000000,0x000007e8,
-/*
-	CALL reselected_ok
-
-at 0x00000051 : */	0x88080000,0x00000798,
-/*
-
-;	Restore DSA following memory moves in reselected_ok
-;	dsa_temp_sync doesn't really care about DSA, but it has an
-;	optional debug INT so a valid DSA is a good idea.
-	MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000053 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-	CALL dsa_temp_sync	
-
-at 0x00000056 : */	0x88080000,0x00000000,
-/*
-; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
-; transfer parameters! 
-	CLEAR ACK
-
-at 0x00000058 : */	0x60000040,0x00000000,
-/*
-; Implicitly restore pointers on reselection, so a RETURN
-; will transfer control back to the right spot.
-    	CALL REL (dsa_code_restore_pointers)
-
-at 0x0000005a : */	0x88880000,0x00ffff68,
-/*
-    	RETURN
-
-at 0x0000005c : */	0x90080000,0x00000000,
-/*
-ENTRY dsa_zero
-dsa_zero:
-ENTRY dsa_code_template_end
-dsa_code_template_end:
-
-; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
-; dsa_zero, puke.
-
-ABSOLUTE dsa_fields_start =  0	; Sanity marker
-				; 	pad 48 bytes (fix this RSN)
-ABSOLUTE dsa_next = 48		; len 4 Next DSA
- 				; del 4 Previous DSA address
-ABSOLUTE dsa_cmnd = 56		; len 4 Scsi_Cmnd * for this thread.
-ABSOLUTE dsa_select = 60	; len 4 Device ID, Period, Offset for 
-			 	;	table indirect select
-ABSOLUTE dsa_msgout = 64	; len 8 table indirect move parameter for 
-				;       select message
-ABSOLUTE dsa_cmdout = 72	; len 8 table indirect move parameter for 
-				;	command
-ABSOLUTE dsa_dataout = 80	; len 4 code pointer for dataout
-ABSOLUTE dsa_datain = 84	; len 4 code pointer for datain
-ABSOLUTE dsa_msgin = 88		; len 8 table indirect move for msgin
-ABSOLUTE dsa_status = 96 	; len 8 table indirect move for status byte
-ABSOLUTE dsa_msgout_other = 104	; len 8 table indirect for normal message out
-				; (Synchronous transfer negotiation, etc).
-ABSOLUTE dsa_end = 112
-
-ABSOLUTE schedule = 0 		; Array of JUMP dsa_begin or JUMP (next),
-				; terminated by a call to JUMP wait_reselect
-
-; Linked lists of DSA structures
-ABSOLUTE reconnect_dsa_head = 0	; Link list of DSAs which can reconnect
-ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
-				; address of reconnect_dsa_head
-
-; These select the source and destination of a MOVE MEMORY instruction
-ABSOLUTE dmode_memory_to_memory = 0x0
-ABSOLUTE dmode_memory_to_ncr = 0x0
-ABSOLUTE dmode_ncr_to_memory = 0x0
-
-ABSOLUTE addr_scratch = 0x0
-ABSOLUTE addr_temp = 0x0
-
-ABSOLUTE saved_dsa = 0x0
-ABSOLUTE emulfly = 0x0
-ABSOLUTE addr_dsa = 0x0
-
-
-
-; Interrupts - 
-; MSB indicates type
-; 0	handle error condition
-; 1 	handle message 
-; 2 	handle normal condition
-; 3	debugging interrupt
-; 4 	testing interrupt 
-; Next byte indicates specific error
-
-; XXX not yet implemented, I'm not sure if I want to - 
-; Next byte indicates the routine the error occurred in
-; The LSB indicates the specific place the error occurred
- 
-ABSOLUTE int_err_unexpected_phase = 0x00000000	; Unexpected phase encountered
-ABSOLUTE int_err_selected = 0x00010000		; SELECTED (nee RESELECTED)
-ABSOLUTE int_err_unexpected_reselect = 0x00020000 
-ABSOLUTE int_err_check_condition = 0x00030000	
-ABSOLUTE int_err_no_phase = 0x00040000
-ABSOLUTE int_msg_wdtr = 0x01000000		; WDTR message received
-ABSOLUTE int_msg_sdtr = 0x01010000		; SDTR received
-ABSOLUTE int_msg_1 = 0x01020000			; single byte special message
-						; received
-
-ABSOLUTE int_norm_select_complete = 0x02000000	; Select complete, reprogram
-						; registers.
-ABSOLUTE int_norm_reselect_complete = 0x02010000	; Nexus established
-ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
-ABSOLUTE int_norm_disconnected = 0x02030000	; Disconnected 
-ABSOLUTE int_norm_aborted =0x02040000		; Aborted *dsa
-ABSOLUTE int_norm_reset = 0x02050000		; Generated BUS reset.
-ABSOLUTE int_norm_emulateintfly = 0x02060000	; 53C710 Emulated intfly
-ABSOLUTE int_debug_break = 0x03000000		; Break point
-
-ABSOLUTE int_debug_panic = 0x030b0000		; Panic driver
-
-
-ABSOLUTE int_test_1 = 0x04000000		; Test 1 complete
-ABSOLUTE int_test_2 = 0x04010000		; Test 2 complete
-ABSOLUTE int_test_3 = 0x04020000		; Test 3 complete
-
-
-; These should start with 0x05000000, with low bits incrementing for 
-; each one.
-
-
-						
-ABSOLUTE NCR53c7xx_msg_abort = 0	; Pointer to abort message
-ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
-ABSOLUTE NCR53c7xx_zero	= 0		; long with zero in it, use for source
-ABSOLUTE NCR53c7xx_sink = 0		; long to dump worthless data in
-ABSOLUTE NOP_insn = 0			; NOP instruction
-
-; Pointer to message, potentially multi-byte
-ABSOLUTE msg_buf = 0
-
-; Pointer to holding area for reselection information
-ABSOLUTE reselected_identify = 0
-ABSOLUTE reselected_tag = 0
-
-; Request sense command pointer, it's a 6 byte command, should
-; be constant for all commands since we always want 16 bytes of 
-; sense and we don't need to change any fields as we did under 
-; SCSI-I when we actually cared about the LUN field.
-;EXTERNAL NCR53c7xx_sense		; Request sense command
-
-
-; dsa_schedule  
-; PURPOSE : after a DISCONNECT message has been received, and pointers
-;	saved, insert the current DSA structure at the head of the 
-; 	disconnected queue and fall through to the scheduler.
-;
-; CALLS : OK
-;
-; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
-;	of disconnected commands
-;
-; MODIFIES : SCRATCH, reconnect_dsa_head
-; 
-; EXITS : always passes control to schedule
-
-ENTRY dsa_schedule
-dsa_schedule:
-
-
-
-
-;
-; Calculate the address of the next pointer within the DSA 
-; structure of the command that is currently disconnecting
-;
-
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x0000005e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_next TO SCRATCH0
-
-at 0x00000061 : */	0x7e343000,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
-
-at 0x00000063 : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
-
-at 0x00000065 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
-
-at 0x00000067 : */	0x7f370000,0x00000000,
-/*
-
-; Point the next field of this DSA structure at the current disconnected 
-; list
-    
-    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
-
-at 0x00000069 : */	0xc0000004,0x00000000,0x000001b8,
-/*
-    
-dsa_schedule_insert:
-    MOVE MEMORY 4, reconnect_dsa_head, 0 
-
-at 0x0000006c : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-; And update the head pointer.
-
-    ; Read what should be the current DSA from memory - actual DSA
-    ; register is probably corrupt
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x0000006f : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    
-    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
-
-at 0x00000072 : */	0xc0000004,0x00000000,0x00000000,
-/*
-    
-
-
-
-
-
-    CLEAR ACK
-
-at 0x00000075 : */	0x60000040,0x00000000,
-/*
-
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x00000077 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-    WAIT DISCONNECT
-
-at 0x0000007a : */	0x48000000,0x00000000,
-/*
-
-
-
-
-
-
-    JUMP schedule
-
-at 0x0000007c : */	0x80080000,0x00000000,
-/*
-
-
-;
-; select
-;
-; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
-;	On success, the current DSA structure is removed from the issue 
-;	queue.  Usually, this is entered as a fall-through from schedule,
-;	although the contingent allegiance handling code will write
-;	the select entry address to the DSP to restart a command as a 
-;	REQUEST SENSE.  A message is sent (usually IDENTIFY, although
-;	additional SDTR or WDTR messages may be sent).  COMMAND OUT
-;	is handled.
-;
-; INPUTS : DSA - SCSI command, issue_dsa_head
-;
-; CALLS : NOT OK
-;
-; MODIFIES : SCRATCH, issue_dsa_head
-;
-; EXITS : on reselection or selection, go to select_failed
-;	otherwise, RETURN so control is passed back to 
-;	dsa_begin.
-;
-
-ENTRY select
-select:
-
-
-
-
-
-
-
-
-    CLEAR TARGET
-
-at 0x0000007e : */	0x60000200,0x00000000,
-/*
-
-; XXX
-;
-; In effect, SELECTION operations are backgrounded, with execution
-; continuing until code which waits for REQ or a fatal interrupt is 
-; encountered.
-;
-; So, for more performance, we could overlap the code which removes 
-; the command from the NCRs issue queue with the selection, but 
-; at this point I don't want to deal with the error recovery.
-;
-
-
-
-    ; Enable selection timer
-
-
-
-    MOVE CTEST7 & 0xef TO CTEST7
-
-at 0x00000080 : */	0x7c1bef00,0x00000000,
-/*
-
-
-    SELECT ATN FROM dsa_select, select_failed
-
-at 0x00000082 : */	0x4300003c,0x00000828,
-/*
-    JUMP select_msgout, WHEN MSG_OUT
-
-at 0x00000084 : */	0x860b0000,0x00000218,
-/*
-ENTRY select_msgout
-select_msgout:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000086 : */	0x7a1b1000,0x00000000,
-/*
-
-    MOVE FROM dsa_msgout, WHEN MSG_OUT
-
-at 0x00000088 : */	0x1e000000,0x00000040,
-/*
-
-
-
-
-
-
-
-
-
-
-   RETURN
-
-at 0x0000008a : */	0x90080000,0x00000000,
-/*
-
-; 
-; select_done
-; 
-; PURPOSE: continue on to normal data transfer; called as the exit 
-;	point from dsa_begin.
-;
-; INPUTS: dsa
-;
-; CALLS: OK
-;
-;
-
-select_done:
-
-; NOTE DSA is corrupt when we arrive here!
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000008c : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-
-
-
-
-; After a successful selection, we should get either a CMD phase or 
-; some transfer request negotiation message.
-
-    JUMP cmdout, WHEN CMD
-
-at 0x0000008f : */	0x820b0000,0x0000025c,
-/*
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
-
-at 0x00000091 : */	0x9f030000,0x00000000,
-/*
-
-select_msg_in:
-    CALL msg_in, WHEN MSG_IN
-
-at 0x00000093 : */	0x8f0b0000,0x0000041c,
-/*
-    JUMP select_msg_in, WHEN MSG_IN
-
-at 0x00000095 : */	0x870b0000,0x0000024c,
-/*
-
-cmdout:
-    INT int_err_unexpected_phase, WHEN NOT CMD
-
-at 0x00000097 : */	0x9a030000,0x00000000,
-/*
-
-
-
-ENTRY cmdout_cmdout
-cmdout_cmdout:
-
-    MOVE FROM dsa_cmdout, WHEN CMD
-
-at 0x00000099 : */	0x1a000000,0x00000048,
-/*
-
-
-
-
-;
-; data_transfer  
-; other_out
-; other_in
-; other_transfer
-;
-; PURPOSE : handle the main data transfer for a SCSI command in 
-;	several parts.  In the first part, data_transfer, DATA_IN
-;	and DATA_OUT phases are allowed, with the user provided
-;	code (usually dynamically generated based on the scatter/gather
-;	list associated with a SCSI command) called to handle these 
-;	phases.
-;
-;	After control has passed to one of the user provided 
-;	DATA_IN or DATA_OUT routines, back calls are made to 
-;	other_transfer_in or other_transfer_out to handle non-DATA IN
-;	and DATA OUT phases respectively, with the state of the active
-;	data pointer being preserved in TEMP.
-;
-;	On completion, the user code passes control to other_transfer
-;	which causes DATA_IN and DATA_OUT to result in unexpected_phase
-;	interrupts so that data overruns may be trapped.
-;
-; INPUTS : DSA - SCSI command
-;
-; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
-;	other_transfer
-;
-; MODIFIES : SCRATCH
-;
-; EXITS : if STATUS IN is detected, signifying command completion,
-;	the NCR jumps to command_complete.  If MSG IN occurs, a 
-;	CALL is made to msg_in.  Otherwise, other_transfer runs in 
-;	an infinite loop.
-;	
-
-ENTRY data_transfer
-data_transfer:
-    JUMP cmdout_cmdout, WHEN CMD
-
-at 0x0000009b : */	0x820b0000,0x00000264,
-/*
-    CALL msg_in, WHEN MSG_IN
-
-at 0x0000009d : */	0x8f0b0000,0x0000041c,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x0000009f : */	0x9e0b0000,0x00000000,
-/*
-    JUMP do_dataout, WHEN DATA_OUT
-
-at 0x000000a1 : */	0x800b0000,0x000002a4,
-/*
-    JUMP do_datain, WHEN DATA_IN
-
-at 0x000000a3 : */	0x810b0000,0x000002fc,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000a5 : */	0x830b0000,0x0000065c,
-/*
-    JUMP data_transfer
-
-at 0x000000a7 : */	0x80080000,0x0000026c,
-/*
-ENTRY end_data_transfer
-end_data_transfer:
-
-;
-; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
-; should be fixed up whenever the nexus changes so it can point to the 
-; correct routine for that command.
-;
-
-
-; Nasty jump to dsa->dataout
-do_dataout:
-
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x000000a9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0	
-
-at 0x000000ac : */	0x7e345000,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-
-at 0x000000ae : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-
-at 0x000000b0 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-
-at 0x000000b2 : */	0x7f370000,0x00000000,
-/*
-    
-    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
-
-at 0x000000b4 : */	0xc0000004,0x00000000,0x000002e0,
-/*
-    
-dataout_to_jump:
-    MOVE MEMORY 4, 0, dataout_jump + 4 
-
-at 0x000000b7 : */	0xc0000004,0x00000000,0x000002f8,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000000ba : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-dataout_jump:
-    JUMP 0
-
-at 0x000000bd : */	0x80080000,0x00000000,
-/*
-
-; Nasty jump to dsa->dsain
-do_datain:
-
-    MOVE MEMORY 4, saved_dsa, addr_scratch
-
-at 0x000000bf : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-    MOVE SCRATCH0 + dsa_datain TO SCRATCH0	
-
-at 0x000000c2 : */	0x7e345400,0x00000000,
-/*
-    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
-
-at 0x000000c4 : */	0x7f350000,0x00000000,
-/*
-    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
-
-at 0x000000c6 : */	0x7f360000,0x00000000,
-/*
-    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
-
-at 0x000000c8 : */	0x7f370000,0x00000000,
-/*
-    
-    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
-
-at 0x000000ca : */	0xc0000004,0x00000000,0x00000338,
-/*
-    
-ENTRY datain_to_jump
-datain_to_jump:
-    MOVE MEMORY 4, 0, datain_jump + 4
-
-at 0x000000cd : */	0xc0000004,0x00000000,0x00000350,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000000d0 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-datain_jump:
-    JUMP 0
-
-at 0x000000d3 : */	0x80080000,0x00000000,
-/*
-
-
-
-; Note that other_out and other_in loop until a non-data phase
-; is discovered, so we only execute return statements when we
-; can go on to the next data phase block move statement.
-
-ENTRY other_out
-other_out:
-
-
-
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000d5 : */	0x9a0b0000,0x00000000,
-/*
-    JUMP msg_in_restart, WHEN MSG_IN 
-
-at 0x000000d7 : */	0x870b0000,0x000003fc,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000d9 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_IN
-
-at 0x000000db : */	0x990b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000dd : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_out, WHEN NOT DATA_OUT
-
-at 0x000000df : */	0x80030000,0x00000354,
-/*
-
-; TEMP should be OK, as we got here from a call in the user dataout code.
-
-    RETURN
-
-at 0x000000e1 : */	0x90080000,0x00000000,
-/*
-
-ENTRY other_in
-other_in:
-
-
-
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000e3 : */	0x9a0b0000,0x00000000,
-/*
-    JUMP msg_in_restart, WHEN MSG_IN 
-
-at 0x000000e5 : */	0x870b0000,0x000003fc,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000e7 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-
-at 0x000000e9 : */	0x980b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000eb : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_in, WHEN NOT DATA_IN
-
-at 0x000000ed : */	0x81030000,0x0000038c,
-/*
-
-; TEMP should be OK, as we got here from a call in the user datain code.
-
-    RETURN
-
-at 0x000000ef : */	0x90080000,0x00000000,
-/*
-
-
-ENTRY other_transfer
-other_transfer:
-    INT int_err_unexpected_phase, WHEN CMD
-
-at 0x000000f1 : */	0x9a0b0000,0x00000000,
-/*
-    CALL msg_in, WHEN MSG_IN
-
-at 0x000000f3 : */	0x8f0b0000,0x0000041c,
-/*
-    INT int_err_unexpected_phase, WHEN MSG_OUT
-
-at 0x000000f5 : */	0x9e0b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_OUT
-
-at 0x000000f7 : */	0x980b0000,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN DATA_IN
-
-at 0x000000f9 : */	0x990b0000,0x00000000,
-/*
-    JUMP command_complete, WHEN STATUS
-
-at 0x000000fb : */	0x830b0000,0x0000065c,
-/*
-    JUMP other_transfer
-
-at 0x000000fd : */	0x80080000,0x000003c4,
-/*
-
-;
-; msg_in_restart
-; msg_in
-; munge_msg
-;
-; PURPOSE : process messages from a target.  msg_in is called when the 
-;	caller hasn't read the first byte of the message.  munge_message
-;	is called when the caller has read the first byte of the message,
-;	and left it in SFBR.  msg_in_restart is called when the caller 
-;	hasn't read the first byte of the message, and wishes RETURN
-;	to transfer control back to the address of the conditional
-;	CALL instruction rather than to the instruction after it.
-;
-;	Various int_* interrupts are generated when the host system
-;	needs to intervene, as is the case with SDTR, WDTR, and
-;	INITIATE RECOVERY messages.
-;
-;	When the host system handles one of these interrupts,
-;	it can respond by reentering at reject_message, 
-;	which rejects the message and returns control to
-;	the caller of msg_in or munge_msg, accept_message
-;	which clears ACK and returns control, or reply_message
-;	which sends the message pointed to by the DSA 
-;	msgout_other table indirect field.
-;
-;	DISCONNECT messages are handled by moving the command
-;	to the reconnect_dsa_queue.
-
-; NOTE: DSA should be valid when we get here - we cannot save both it
-;	and TEMP in this routine.
-
-;
-; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
-;	only)
-;
-; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
-;
-; MODIFIES : SCRATCH, DSA on DISCONNECT
-;
-; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
-;	and normal return from message handlers running under
-;	Linux, control is returned to the caller.  Receipt
-;	of DISCONNECT messages pass control to dsa_schedule.
-;
-ENTRY msg_in_restart
-msg_in_restart:
-; XXX - hackish
-;
-; Since it's easier to debug changes to the statically 
-; compiled code, rather than the dynamically generated 
-; stuff, such as
-;
-; 	MOVE x, y, WHEN data_phase
-; 	CALL other_z, WHEN NOT data_phase
-; 	MOVE x, y, WHEN data_phase
-;
-; I'd like to have certain routines (notably the message handler)
-; restart on the conditional call rather than the next instruction.
-;
-; So, subtract 8 from the return address
-
-    MOVE TEMP0 + 0xf8 TO TEMP0
-
-at 0x000000ff : */	0x7e1cf800,0x00000000,
-/*
-    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
-
-at 0x00000101 : */	0x7f1dff00,0x00000000,
-/*
-    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
-
-at 0x00000103 : */	0x7f1eff00,0x00000000,
-/*
-    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
-
-at 0x00000105 : */	0x7f1fff00,0x00000000,
-/*
-
-ENTRY msg_in
-msg_in:
-    MOVE 1, msg_buf, WHEN MSG_IN
-
-at 0x00000107 : */	0x0f000001,0x00000000,
-/*
-
-munge_msg:
-    JUMP munge_extended, IF 0x01		; EXTENDED MESSAGE
-
-at 0x00000109 : */	0x800c0001,0x00000574,
-/*
-    JUMP munge_2, IF 0x20, AND MASK 0xdf	; two byte message
-
-at 0x0000010b : */	0x800cdf20,0x00000464,
-/*
-;
-; XXX - I've seen a handful of broken SCSI devices which fail to issue
-; 	a SAVE POINTERS message before disconnecting in the middle of 
-; 	a transfer, assuming that the DATA POINTER will be implicitly 
-; 	restored.  
-;
-; Historically, I've often done an implicit save when the DISCONNECT
-; message is processed.  We may want to consider having the option of 
-; doing that here. 
-;
-    JUMP munge_save_data_pointer, IF 0x02	; SAVE DATA POINTER
-
-at 0x0000010d : */	0x800c0002,0x0000046c,
-/*
-    JUMP munge_restore_pointers, IF 0x03	; RESTORE POINTERS 
-
-at 0x0000010f : */	0x800c0003,0x00000518,
-/*
-    JUMP munge_disconnect, IF 0x04		; DISCONNECT
-
-at 0x00000111 : */	0x800c0004,0x0000056c,
-/*
-    INT int_msg_1, IF 0x07			; MESSAGE REJECT
-
-at 0x00000113 : */	0x980c0007,0x01020000,
-/*
-    INT int_msg_1, IF 0x0f			; INITIATE RECOVERY
-
-at 0x00000115 : */	0x980c000f,0x01020000,
-/*
-
-
-
-    JUMP reject_message
-
-at 0x00000117 : */	0x80080000,0x00000604,
-/*
-
-munge_2:
-    JUMP reject_message
-
-at 0x00000119 : */	0x80080000,0x00000604,
-/*
-;
-; The SCSI standard allows targets to recover from transient 
-; error conditions by backing up the data pointer with a 
-; RESTORE POINTERS message.  
-;	
-; So, we must save and restore the _residual_ code as well as 
-; the current instruction pointer.  Because of this messiness,
-; it is simpler to put dynamic code in the dsa for this and to
-; just do a simple jump down there. 
-;
-
-munge_save_data_pointer:
-
-    ; We have something in TEMP here, so first we must save that
-    MOVE TEMP0 TO SFBR
-
-at 0x0000011b : */	0x721c0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x0000011d : */	0x6a340000,0x00000000,
-/*
-    MOVE TEMP1 TO SFBR
-
-at 0x0000011f : */	0x721d0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x00000121 : */	0x6a350000,0x00000000,
-/*
-    MOVE TEMP2 TO SFBR
-
-at 0x00000123 : */	0x721e0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x00000125 : */	0x6a360000,0x00000000,
-/*
-    MOVE TEMP3 TO SFBR
-
-at 0x00000127 : */	0x721f0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x00000129 : */	0x6a370000,0x00000000,
-/*
-    MOVE MEMORY 4, addr_scratch, jump_temp + 4
-
-at 0x0000012b : */	0xc0000004,0x00000000,0x000009c8,
-/*
-    ; Now restore DSA
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x0000012e : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-    MOVE DSA0 + dsa_save_data_pointer TO SFBR
-
-at 0x00000131 : */	0x76100000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x00000133 : */	0x6a340000,0x00000000,
-/*
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-
-at 0x00000135 : */	0x7711ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x00000137 : */	0x6a350000,0x00000000,
-/*
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
-
-at 0x00000139 : */	0x7712ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x0000013b : */	0x6a360000,0x00000000,
-/*
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-
-at 0x0000013d : */	0x7713ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x0000013f : */	0x6a370000,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
-
-at 0x00000141 : */	0xc0000004,0x00000000,0x00000514,
-/*
-    
-jump_dsa_save:
-    JUMP 0
-
-at 0x00000144 : */	0x80080000,0x00000000,
-/*
-
-munge_restore_pointers:
-
-    ; The code at dsa_restore_pointers will RETURN, but we don't care
-    ; about TEMP here, as it will overwrite it anyway.
-
-    MOVE DSA0 + dsa_restore_pointers TO SFBR
-
-at 0x00000146 : */	0x76100000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x00000148 : */	0x6a340000,0x00000000,
-/*
-    MOVE DSA1 + 0xff TO SFBR WITH CARRY
-
-at 0x0000014a : */	0x7711ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x0000014c : */	0x6a350000,0x00000000,
-/*
-    MOVE DSA2 + 0xff TO SFBR WITH CARRY
-
-at 0x0000014e : */	0x7712ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x00000150 : */	0x6a360000,0x00000000,
-/*
-    MOVE DSA3 + 0xff TO SFBR WITH CARRY
-
-at 0x00000152 : */	0x7713ff00,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x00000154 : */	0x6a370000,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
-
-at 0x00000156 : */	0xc0000004,0x00000000,0x00000568,
-/*
-    
-jump_dsa_restore:
-    JUMP 0
-
-at 0x00000159 : */	0x80080000,0x00000000,
-/*
-
-
-munge_disconnect:
-
-
-
-
-
-
-
-
-
- 
-
-
-
-
-
-
-
-
-
-
-    JUMP dsa_schedule
-
-at 0x0000015b : */	0x80080000,0x00000178,
-/*
-
-
-
-
-
-munge_extended:
-    CLEAR ACK
-
-at 0x0000015d : */	0x60000040,0x00000000,
-/*
-    INT int_err_unexpected_phase, WHEN NOT MSG_IN
-
-at 0x0000015f : */	0x9f030000,0x00000000,
-/*
-    MOVE 1, msg_buf + 1, WHEN MSG_IN
-
-at 0x00000161 : */	0x0f000001,0x00000001,
-/*
-    JUMP munge_extended_2, IF 0x02
-
-at 0x00000163 : */	0x800c0002,0x000005a4,
-/*
-    JUMP munge_extended_3, IF 0x03 
-
-at 0x00000165 : */	0x800c0003,0x000005d4,
-/*
-    JUMP reject_message
-
-at 0x00000167 : */	0x80080000,0x00000604,
-/*
-
-munge_extended_2:
-    CLEAR ACK
-
-at 0x00000169 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-
-at 0x0000016b : */	0x0f000001,0x00000002,
-/*
-    JUMP reject_message, IF NOT 0x02	; Must be WDTR
-
-at 0x0000016d : */	0x80040002,0x00000604,
-/*
-    CLEAR ACK
-
-at 0x0000016f : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 3, WHEN MSG_IN
-
-at 0x00000171 : */	0x0f000001,0x00000003,
-/*
-    INT int_msg_wdtr
-
-at 0x00000173 : */	0x98080000,0x01000000,
-/*
-
-munge_extended_3:
-    CLEAR ACK
-
-at 0x00000175 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, msg_buf + 2, WHEN MSG_IN
-
-at 0x00000177 : */	0x0f000001,0x00000002,
-/*
-    JUMP reject_message, IF NOT 0x01	; Must be SDTR
-
-at 0x00000179 : */	0x80040001,0x00000604,
-/*
-    CLEAR ACK
-
-at 0x0000017b : */	0x60000040,0x00000000,
-/*
-    MOVE 2, msg_buf + 3, WHEN MSG_IN
-
-at 0x0000017d : */	0x0f000002,0x00000003,
-/*
-    INT int_msg_sdtr
-
-at 0x0000017f : */	0x98080000,0x01010000,
-/*
-
-ENTRY reject_message
-reject_message:
-    SET ATN
-
-at 0x00000181 : */	0x58000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000183 : */	0x60000040,0x00000000,
-/*
-    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
-
-at 0x00000185 : */	0x0e000001,0x00000000,
-/*
-    RETURN
-
-at 0x00000187 : */	0x90080000,0x00000000,
-/*
-
-ENTRY accept_message
-accept_message:
-    CLEAR ATN
-
-at 0x00000189 : */	0x60000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x0000018b : */	0x60000040,0x00000000,
-/*
-    RETURN
-
-at 0x0000018d : */	0x90080000,0x00000000,
-/*
-
-ENTRY respond_message
-respond_message:
-    SET ATN
-
-at 0x0000018f : */	0x58000008,0x00000000,
-/*
-    CLEAR ACK
-
-at 0x00000191 : */	0x60000040,0x00000000,
-/*
-    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
-
-at 0x00000193 : */	0x1e000000,0x00000068,
-/*
-    RETURN
-
-at 0x00000195 : */	0x90080000,0x00000000,
-/*
-
-;
-; command_complete
-;
-; PURPOSE : handle command termination when STATUS IN is detected by reading
-;	a status byte followed by a command termination message. 
-;
-;	Normal termination results in an INTFLY instruction, and 
-;	the host system can pick out which command terminated by 
-;	examining the MESSAGE and STATUS buffers of all currently 
-;	executing commands;
-;
-;	Abnormal (CHECK_CONDITION) termination results in an
-;	int_err_check_condition interrupt so that a REQUEST SENSE
-;	command can be issued out-of-order so that no other command
-;	clears the contingent allegiance condition.
-;	
-;
-; INPUTS : DSA - command	
-;
-; CALLS : OK
-;
-; EXITS : On successful termination, control is passed to schedule.
-;	On abnormal termination, the user will usually modify the 
-;	DSA fields and corresponding buffers and return control
-;	to select.
-;
-
-ENTRY command_complete
-command_complete:
-    MOVE FROM dsa_status, WHEN STATUS
-
-at 0x00000197 : */	0x1b000000,0x00000060,
-/*
-
-    MOVE SFBR TO SCRATCH0		; Save status
-
-at 0x00000199 : */	0x6a340000,0x00000000,
-/*
-
-ENTRY command_complete_msgin
-command_complete_msgin:
-    MOVE FROM dsa_msgin, WHEN MSG_IN
-
-at 0x0000019b : */	0x1f000000,0x00000058,
-/*
-; Indicate that we should be expecting a disconnect
-
-
-
-    ; Above code cleared the Unexpected Disconnect bit, what do we do?
-
-    CLEAR ACK
-
-at 0x0000019d : */	0x60000040,0x00000000,
-/*
-
-    WAIT DISCONNECT
-
-at 0x0000019f : */	0x48000000,0x00000000,
-/*
-
-;
-; The SCSI specification states that when a UNIT ATTENTION condition
-; is pending, as indicated by a CHECK CONDITION status message,
-; the target shall revert to asynchronous transfers.  Since
-; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
-; basis, and returning control to our scheduler could work on a command
-; running on another lun on that target using the old parameters, we must
-; interrupt the host processor to get them changed, or change them ourselves.
-;
-; Once SCSI-II tagged queueing is implemented, things will be even more
-; hairy, since contingent allegiance conditions exist on a per-target/lun
-; basis, and issuing a new command with a different tag would clear it.
-; In these cases, we must interrupt the host processor to get a request 
-; added to the HEAD of the queue with the request sense command, or we
-; must automatically issue the request sense command.
-
-
-
-
-
-
-
-    INT int_norm_emulateintfly
-
-at 0x000001a1 : */	0x98080000,0x02060000,
-/*
-
-
-
-
-
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001a3 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-
-    JUMP schedule
-
-at 0x000001a6 : */	0x80080000,0x00000000,
-/*
-command_failed:
-    INT int_err_check_condition
-
-at 0x000001a8 : */	0x98080000,0x00030000,
-/*
-
-
-
-
-;
-; wait_reselect
-;
-; PURPOSE : This is essentially the idle routine, where control lands
-;	when there are no new processes to schedule.  wait_reselect
-;	waits for reselection, selection, and new commands.
-;
-;	When a successful reselection occurs, with the aid 
-;	of fixed up code in each DSA, wait_reselect walks the 
-;	reconnect_dsa_queue, asking each dsa if the target ID
-;	and LUN match its.
-;
-;	If a match is found, a call is made back to reselected_ok,
-;	which through the miracles of self modifying code, extracts
-;	the found DSA from the reconnect_dsa_queue and then 
-;	returns control to the DSAs thread of execution.
-;
-; INPUTS : NONE
-;
-; CALLS : OK
-;
-; MODIFIES : DSA,
-;
-; EXITS : On successful reselection, control is returned to the 
-;	DSA which called reselected_ok.  If the WAIT RESELECT
-;	was interrupted by a new commands arrival signaled by 
-;	SIG_P, control is passed to schedule.  If the NCR is 
-;	selected, the host system is interrupted with an 
-;	int_err_selected which is usually responded to by
-;	setting DSP to the target_abort address.
-
-ENTRY wait_reselect
-wait_reselect:
-
-
-
-
-
-
-    WAIT RESELECT wait_reselect_failed
-
-at 0x000001aa : */	0x50000000,0x00000800,
-/*
-
-reselected:
-
-
-
-    CLEAR TARGET
-
-at 0x000001ac : */	0x60000200,0x00000000,
-/*
-    
-    ; Read all data needed to reestablish the nexus - 
-    MOVE 1, reselected_identify, WHEN MSG_IN
-
-at 0x000001ae : */	0x0f000001,0x00000000,
-/*
-    ; We used to CLEAR ACK here.
-
-
-
-
-
-    ; Point DSA at the current head of the disconnected queue.
-    
-    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
-
-at 0x000001b0 : */	0xc0000004,0x00000000,0x00000000,
-/*
-    
-
-    MOVE MEMORY 4, addr_scratch, saved_dsa
-
-at 0x000001b3 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-
-
-    ; Fix the update-next pointer so that the reconnect_dsa_head
-    ; pointer is the one that will be updated if this DSA is a hit 
-    ; and we remove it from the queue.
-
-    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
-
-at 0x000001b6 : */	0xc0000004,0x00000000,0x000007ec,
-/*
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001b9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-
-ENTRY reselected_check_next
-reselected_check_next:
-
-
-
-    ; Check for a NULL pointer.
-    MOVE DSA0 TO SFBR
-
-at 0x000001bc : */	0x72100000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001be : */	0x80040000,0x00000738,
-/*
-    MOVE DSA1 TO SFBR
-
-at 0x000001c0 : */	0x72110000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001c2 : */	0x80040000,0x00000738,
-/*
-    MOVE DSA2 TO SFBR
-
-at 0x000001c4 : */	0x72120000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001c6 : */	0x80040000,0x00000738,
-/*
-    MOVE DSA3 TO SFBR
-
-at 0x000001c8 : */	0x72130000,0x00000000,
-/*
-    JUMP reselected_not_end, IF NOT 0
-
-at 0x000001ca : */	0x80040000,0x00000738,
-/*
-    INT int_err_unexpected_reselect
-
-at 0x000001cc : */	0x98080000,0x00020000,
-/*
-
-reselected_not_end:
-    ;
-    ; XXX the ALU is only eight bits wide, and the assembler
-    ; wont do the dirt work for us.  As long as dsa_check_reselect
-    ; is negative, we need to sign extend with 1 bits to the full
-    ; 32 bit width of the address.
-    ;
-    ; A potential work around would be to have a known alignment 
-    ; of the DSA structure such that the base address plus 
-    ; dsa_check_reselect doesn't require carrying from bytes 
-    ; higher than the LSB.
-    ;
-
-    MOVE DSA0 TO SFBR
-
-at 0x000001ce : */	0x72100000,0x00000000,
-/*
-    MOVE SFBR + dsa_check_reselect TO SCRATCH0
-
-at 0x000001d0 : */	0x6e340000,0x00000000,
-/*
-    MOVE DSA1 TO SFBR
-
-at 0x000001d2 : */	0x72110000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
-
-at 0x000001d4 : */	0x6f35ff00,0x00000000,
-/*
-    MOVE DSA2 TO SFBR
-
-at 0x000001d6 : */	0x72120000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
-
-at 0x000001d8 : */	0x6f36ff00,0x00000000,
-/*
-    MOVE DSA3 TO SFBR
-
-at 0x000001da : */	0x72130000,0x00000000,
-/*
-    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
-
-at 0x000001dc : */	0x6f37ff00,0x00000000,
-/*
-
-    
-    MOVE MEMORY 4, addr_scratch, reselected_check + 4
-
-at 0x000001de : */	0xc0000004,0x00000000,0x00000794,
-/*
-    
-
-    ; Time to correct DSA following memory move
-    MOVE MEMORY 4, saved_dsa, addr_dsa
-
-at 0x000001e1 : */	0xc0000004,0x00000000,0x00000000,
-/*
-
-reselected_check:
-    JUMP 0
-
-at 0x000001e4 : */	0x80080000,0x00000000,
-/*
-
-
-;
-;
-
-; We have problems here - the memory move corrupts TEMP and DSA.  This
-; routine is called from DSA code, and patched from many places.  Scratch
-; is probably free when it is called.
-; We have to:
-;   copy temp to scratch, one byte at a time
-;   write scratch to patch a jump in place of the return
-;   do the move memory
-;   jump to the patched in return address
-; DSA is corrupt when we get here, and can be left corrupt
-
-ENTRY reselected_ok
-reselected_ok:
-    MOVE TEMP0 TO SFBR
-
-at 0x000001e6 : */	0x721c0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH0
-
-at 0x000001e8 : */	0x6a340000,0x00000000,
-/*
-    MOVE TEMP1 TO SFBR
-
-at 0x000001ea : */	0x721d0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH1
-
-at 0x000001ec : */	0x6a350000,0x00000000,
-/*
-    MOVE TEMP2 TO SFBR
-
-at 0x000001ee : */	0x721e0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH2
-
-at 0x000001f0 : */	0x6a360000,0x00000000,
-/*
-    MOVE TEMP3 TO SFBR
-
-at 0x000001f2 : */	0x721f0000,0x00000000,
-/*
-    MOVE SFBR TO SCRATCH3
-
-at 0x000001f4 : */	0x6a370000,0x00000000,
-/*
-    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
-
-at 0x000001f6 : */	0xc0000004,0x00000000,0x000007f4,
-/*
-reselected_ok_patch:
-    MOVE MEMORY 4, 0, 0
-
-at 0x000001f9 : */	0xc0000004,0x00000000,0x00000000,
-/*
-reselected_ok_jump:
-    JUMP 0
-
-at 0x000001fc : */	0x80080000,0x00000000,
-/*
-
-
-
-
-
-selected:
-    INT int_err_selected;
-
-at 0x000001fe : */	0x98080000,0x00010000,
-/*
-
-;
-; A select or reselect failure can be caused by one of two conditions : 
-; 1.  SIG_P was set.  This will be the case if the user has written
-;	a new value to a previously NULL head of the issue queue.
-;
-; 2.  The NCR53c810 was selected or reselected by another device.
-;
-; 3.  The bus was already busy since we were selected or reselected
-;	before starting the command.
-
-wait_reselect_failed:
-
-
-
-; Check selected bit.  
-
-    ; Must work out how to tell if we are selected....
-
-
-
-
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-
-at 0x00000200 : */	0x74164000,0x00000000,
-/*
-    JUMP schedule, IF 0x40
-
-at 0x00000202 : */	0x800c0040,0x00000000,
-/*
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-    MOVE ISTAT & 0x08 TO SFBR
-
-at 0x00000204 : */	0x74210800,0x00000000,
-/*
-    JUMP reselected, IF 0x08
-
-at 0x00000206 : */	0x800c0008,0x000006b0,
-/*
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-
-
-
-    INT int_debug_panic
-
-at 0x00000208 : */	0x98080000,0x030b0000,
-/*
-
-
-
-select_failed:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x0000020a : */	0x7a1b1000,0x00000000,
-/*
-
-
-
-
-; Otherwise, mask the selected and reselected bits off SIST0
-
-    ; Let's assume we don't get selected for now
-    MOVE SSTAT0 & 0x10 TO SFBR
-
-at 0x0000020c : */	0x740d1000,0x00000000,
-/*
-
-
-
-
-    JUMP reselected, IF 0x10 
-
-at 0x0000020e : */	0x800c0010,0x000006b0,
-/*
-; If SIGP is set, the user just gave us another command, and
-; we should restart or return to the scheduler.
-; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
-    MOVE CTEST2 & 0x40 TO SFBR	
-
-at 0x00000210 : */	0x74164000,0x00000000,
-/*
-    JUMP select, IF 0x40
-
-at 0x00000212 : */	0x800c0040,0x000001f8,
-/*
-; Check connected bit.  
-; FIXME: this needs to change if we support target mode
-; FIXME: is this really necessary? 
-    MOVE ISTAT & 0x08 TO SFBR
-
-at 0x00000214 : */	0x74210800,0x00000000,
-/*
-    JUMP reselected, IF 0x08
-
-at 0x00000216 : */	0x800c0008,0x000006b0,
-/*
-; FIXME : Something bogus happened, and we shouldn't fail silently.
-
-
-
-    INT int_debug_panic
-
-at 0x00000218 : */	0x98080000,0x030b0000,
-/*
-
-
-;
-; test_1
-; test_2
-;
-; PURPOSE : run some verification tests on the NCR.  test_1
-;	copies test_src to test_dest and interrupts the host
-;	processor, testing for cache coherency and interrupt
-; 	problems in the processes.
-;
-;	test_2 runs a command with offsets relative to the 
-;	DSA on entry, and is useful for miscellaneous experimentation.
-;
-
-; Verify that interrupts are working correctly and that we don't 
-; have a cache invalidation problem.
-
-ABSOLUTE test_src = 0, test_dest = 0
-ENTRY test_1
-test_1:
-    MOVE MEMORY 4, test_src, test_dest
-
-at 0x0000021a : */	0xc0000004,0x00000000,0x00000000,
-/*
-    INT int_test_1
-
-at 0x0000021d : */	0x98080000,0x04000000,
-/*
-
-;
-; Run arbitrary commands, with test code establishing a DSA
-;
- 
-ENTRY test_2
-test_2:
-    CLEAR TARGET
-
-at 0x0000021f : */	0x60000200,0x00000000,
-/*
-
-    ; Enable selection timer
-
-
-
-    MOVE CTEST7 & 0xef TO CTEST7
-
-at 0x00000221 : */	0x7c1bef00,0x00000000,
-/*
-
-
-    SELECT ATN FROM 0, test_2_fail
-
-at 0x00000223 : */	0x43000000,0x000008dc,
-/*
-    JUMP test_2_msgout, WHEN MSG_OUT
-
-at 0x00000225 : */	0x860b0000,0x0000089c,
-/*
-ENTRY test_2_msgout
-test_2_msgout:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000227 : */	0x7a1b1000,0x00000000,
-/*
-
-    MOVE FROM 8, WHEN MSG_OUT
-
-at 0x00000229 : */	0x1e000000,0x00000008,
-/*
-    MOVE FROM 16, WHEN CMD 
-
-at 0x0000022b : */	0x1a000000,0x00000010,
-/*
-    MOVE FROM 24, WHEN DATA_IN
-
-at 0x0000022d : */	0x19000000,0x00000018,
-/*
-    MOVE FROM 32, WHEN STATUS
-
-at 0x0000022f : */	0x1b000000,0x00000020,
-/*
-    MOVE FROM 40, WHEN MSG_IN
-
-at 0x00000231 : */	0x1f000000,0x00000028,
-/*
-
-
-
-    CLEAR ACK
-
-at 0x00000233 : */	0x60000040,0x00000000,
-/*
-    WAIT DISCONNECT
-
-at 0x00000235 : */	0x48000000,0x00000000,
-/*
-test_2_fail:
-
-    ; Disable selection timer
-    MOVE CTEST7 | 0x10 TO CTEST7
-
-at 0x00000237 : */	0x7a1b1000,0x00000000,
-/*
-
-    INT int_test_2
-
-at 0x00000239 : */	0x98080000,0x04010000,
-/*
-
-ENTRY debug_break
-debug_break:
-    INT int_debug_break
-
-at 0x0000023b : */	0x98080000,0x03000000,
-/*
-
-;
-; initiator_abort
-; target_abort
-;
-; PURPOSE : Abort the currently established nexus from with initiator
-;	or target mode.
-;
-;  
-
-ENTRY target_abort
-target_abort:
-    SET TARGET
-
-at 0x0000023d : */	0x58000200,0x00000000,
-/*
-    DISCONNECT
-
-at 0x0000023f : */	0x48000000,0x00000000,
-/*
-    CLEAR TARGET
-
-at 0x00000241 : */	0x60000200,0x00000000,
-/*
-    JUMP schedule
-
-at 0x00000243 : */	0x80080000,0x00000000,
-/*
-    
-ENTRY initiator_abort
-initiator_abort:
-    SET ATN
-
-at 0x00000245 : */	0x58000008,0x00000000,
-/*
-;
-; The SCSI-I specification says that targets may go into MSG out at 
-; their leisure upon receipt of the ATN single.  On all versions of the 
-; specification, we can't change phases until REQ transitions true->false, 
-; so we need to sink/source one byte of data to allow the transition.
-;
-; For the sake of safety, we'll only source one byte of data in all 
-; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
-; arbitrary number of bytes.
-    JUMP spew_cmd, WHEN CMD
-
-at 0x00000247 : */	0x820b0000,0x0000094c,
-/*
-    JUMP eat_msgin, WHEN MSG_IN
-
-at 0x00000249 : */	0x870b0000,0x0000095c,
-/*
-    JUMP eat_datain, WHEN DATA_IN
-
-at 0x0000024b : */	0x810b0000,0x0000098c,
-/*
-    JUMP eat_status, WHEN STATUS
-
-at 0x0000024d : */	0x830b0000,0x00000974,
-/*
-    JUMP spew_dataout, WHEN DATA_OUT
-
-at 0x0000024f : */	0x800b0000,0x000009a4,
-/*
-    JUMP sated
-
-at 0x00000251 : */	0x80080000,0x000009ac,
-/*
-spew_cmd:
-    MOVE 1, NCR53c7xx_zero, WHEN CMD
-
-at 0x00000253 : */	0x0a000001,0x00000000,
-/*
-    JUMP sated
-
-at 0x00000255 : */	0x80080000,0x000009ac,
-/*
-eat_msgin:
-    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
-
-at 0x00000257 : */	0x0f000001,0x00000000,
-/*
-    JUMP eat_msgin, WHEN MSG_IN
-
-at 0x00000259 : */	0x870b0000,0x0000095c,
-/*
-    JUMP sated
-
-at 0x0000025b : */	0x80080000,0x000009ac,
-/*
-eat_status:
-    MOVE 1, NCR53c7xx_sink, WHEN STATUS
-
-at 0x0000025d : */	0x0b000001,0x00000000,
-/*
-    JUMP eat_status, WHEN STATUS
-
-at 0x0000025f : */	0x830b0000,0x00000974,
-/*
-    JUMP sated
-
-at 0x00000261 : */	0x80080000,0x000009ac,
-/*
-eat_datain:
-    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
-
-at 0x00000263 : */	0x09000001,0x00000000,
-/*
-    JUMP eat_datain, WHEN DATA_IN
-
-at 0x00000265 : */	0x810b0000,0x0000098c,
-/*
-    JUMP sated
-
-at 0x00000267 : */	0x80080000,0x000009ac,
-/*
-spew_dataout:
-    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
-
-at 0x00000269 : */	0x08000001,0x00000000,
-/*
-sated:
-
-
-
-    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
-
-at 0x0000026b : */	0x0e000001,0x00000000,
-/*
-    WAIT DISCONNECT
-
-at 0x0000026d : */	0x48000000,0x00000000,
-/*
-    INT int_norm_aborted
-
-at 0x0000026f : */	0x98080000,0x02040000,
-/*
-
-
- 
-
-; Little patched jump, used to overcome problems with TEMP getting
-; corrupted on memory moves.
-
-jump_temp:
-    JUMP 0
-
-at 0x00000271 : */	0x80080000,0x00000000,
-};
-
-#define A_NCR53c7xx_msg_abort	0x00000000
-static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
-	0x0000026c,
-};
-
-#define A_NCR53c7xx_msg_reject	0x00000000
-static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
-	0x00000186,
-};
-
-#define A_NCR53c7xx_sink	0x00000000
-static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
-	0x00000258,
-	0x0000025e,
-	0x00000264,
-};
-
-#define A_NCR53c7xx_zero	0x00000000
-static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
-	0x00000254,
-	0x0000026a,
-};
-
-#define A_NOP_insn	0x00000000
-static u32 A_NOP_insn_used[] __attribute((unused)) = {
-	0x00000017,
-};
-
-#define A_addr_dsa	0x00000000
-static u32 A_addr_dsa_used[] __attribute((unused)) = {
-	0x0000000f,
-	0x00000026,
-	0x00000033,
-	0x00000040,
-	0x00000055,
-	0x00000079,
-	0x0000008e,
-	0x000000bc,
-	0x000000d2,
-	0x00000130,
-	0x000001a5,
-	0x000001bb,
-	0x000001e3,
-};
-
-#define A_addr_reconnect_dsa_head	0x00000000
-static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
-	0x000001b7,
-};
-
-#define A_addr_scratch	0x00000000
-static u32 A_addr_scratch_used[] __attribute((unused)) = {
-	0x00000002,
-	0x00000004,
-	0x00000008,
-	0x00000020,
-	0x00000022,
-	0x00000049,
-	0x00000060,
-	0x0000006a,
-	0x00000071,
-	0x00000073,
-	0x000000ab,
-	0x000000b5,
-	0x000000c1,
-	0x000000cb,
-	0x0000012c,
-	0x00000142,
-	0x00000157,
-	0x000001b2,
-	0x000001b4,
-	0x000001df,
-	0x000001f7,
-};
-
-#define A_addr_temp	0x00000000
-static u32 A_addr_temp_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_memory_to_memory	0x00000000
-static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_memory_to_ncr	0x00000000
-static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
-};
-
-#define A_dmode_ncr_to_memory	0x00000000
-static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_check_reselect	0x00000000
-static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
-	0x000001d0,
-};
-
-#define A_dsa_cmdout	0x00000048
-static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
-	0x0000009a,
-};
-
-#define A_dsa_cmnd	0x00000038
-static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_datain	0x00000054
-static u32 A_dsa_datain_used[] __attribute((unused)) = {
-	0x000000c2,
-};
-
-#define A_dsa_dataout	0x00000050
-static u32 A_dsa_dataout_used[] __attribute((unused)) = {
-	0x000000ac,
-};
-
-#define A_dsa_end	0x00000070
-static u32 A_dsa_end_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_fields_start	0x00000000
-static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_msgin	0x00000058
-static u32 A_dsa_msgin_used[] __attribute((unused)) = {
-	0x0000019c,
-};
-
-#define A_dsa_msgout	0x00000040
-static u32 A_dsa_msgout_used[] __attribute((unused)) = {
-	0x00000089,
-};
-
-#define A_dsa_msgout_other	0x00000068
-static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
-	0x00000194,
-};
-
-#define A_dsa_next	0x00000030
-static u32 A_dsa_next_used[] __attribute((unused)) = {
-	0x00000061,
-};
-
-#define A_dsa_restore_pointers	0x00000000
-static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
-	0x00000146,
-};
-
-#define A_dsa_save_data_pointer	0x00000000
-static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
-	0x00000131,
-};
-
-#define A_dsa_select	0x0000003c
-static u32 A_dsa_select_used[] __attribute((unused)) = {
-	0x00000082,
-};
-
-#define A_dsa_sscf_710	0x00000000
-static u32 A_dsa_sscf_710_used[] __attribute((unused)) = {
-	0x00000007,
-};
-
-#define A_dsa_status	0x00000060
-static u32 A_dsa_status_used[] __attribute((unused)) = {
-	0x00000198,
-};
-
-#define A_dsa_temp_addr_array_value	0x00000000
-static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_temp_addr_dsa_value	0x00000000
-static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
-	0x00000001,
-};
-
-#define A_dsa_temp_addr_new_value	0x00000000
-static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
-};
-
-#define A_dsa_temp_addr_next	0x00000000
-static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
-	0x0000001c,
-	0x0000004f,
-};
-
-#define A_dsa_temp_addr_residual	0x00000000
-static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
-	0x0000002d,
-	0x0000003b,
-};
-
-#define A_dsa_temp_addr_saved_pointer	0x00000000
-static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
-	0x0000002b,
-	0x00000037,
-};
-
-#define A_dsa_temp_addr_saved_residual	0x00000000
-static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
-	0x0000002e,
-	0x0000003a,
-};
-
-#define A_dsa_temp_lun	0x00000000
-static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
-	0x0000004c,
-};
-
-#define A_dsa_temp_next	0x00000000
-static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
-	0x0000001f,
-};
-
-#define A_dsa_temp_sync	0x00000000
-static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
-	0x00000057,
-};
-
-#define A_dsa_temp_target	0x00000000
-static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
-	0x00000045,
-};
-
-#define A_emulfly	0x00000000
-static u32 A_emulfly_used[] __attribute((unused)) = {
-};
-
-#define A_int_debug_break	0x03000000
-static u32 A_int_debug_break_used[] __attribute((unused)) = {
-	0x0000023c,
-};
-
-#define A_int_debug_panic	0x030b0000
-static u32 A_int_debug_panic_used[] __attribute((unused)) = {
-	0x00000209,
-	0x00000219,
-};
-
-#define A_int_err_check_condition	0x00030000
-static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
-	0x000001a9,
-};
-
-#define A_int_err_no_phase	0x00040000
-static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
-};
-
-#define A_int_err_selected	0x00010000
-static u32 A_int_err_selected_used[] __attribute((unused)) = {
-	0x000001ff,
-};
-
-#define A_int_err_unexpected_phase	0x00000000
-static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
-	0x00000092,
-	0x00000098,
-	0x000000a0,
-	0x000000d6,
-	0x000000da,
-	0x000000dc,
-	0x000000e4,
-	0x000000e8,
-	0x000000ea,
-	0x000000f2,
-	0x000000f6,
-	0x000000f8,
-	0x000000fa,
-	0x00000160,
-};
-
-#define A_int_err_unexpected_reselect	0x00020000
-static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
-	0x000001cd,
-};
-
-#define A_int_msg_1	0x01020000
-static u32 A_int_msg_1_used[] __attribute((unused)) = {
-	0x00000114,
-	0x00000116,
-};
-
-#define A_int_msg_sdtr	0x01010000
-static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
-	0x00000180,
-};
-
-#define A_int_msg_wdtr	0x01000000
-static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
-	0x00000174,
-};
-
-#define A_int_norm_aborted	0x02040000
-static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
-	0x00000270,
-};
-
-#define A_int_norm_command_complete	0x02020000
-static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_disconnected	0x02030000
-static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_emulateintfly	0x02060000
-static u32 A_int_norm_emulateintfly_used[] __attribute((unused)) = {
-	0x000001a2,
-};
-
-#define A_int_norm_reselect_complete	0x02010000
-static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_reset	0x02050000
-static u32 A_int_norm_reset_used[] __attribute((unused)) = {
-};
-
-#define A_int_norm_select_complete	0x02000000
-static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
-};
-
-#define A_int_test_1	0x04000000
-static u32 A_int_test_1_used[] __attribute((unused)) = {
-	0x0000021e,
-};
-
-#define A_int_test_2	0x04010000
-static u32 A_int_test_2_used[] __attribute((unused)) = {
-	0x0000023a,
-};
-
-#define A_int_test_3	0x04020000
-static u32 A_int_test_3_used[] __attribute((unused)) = {
-};
-
-#define A_msg_buf	0x00000000
-static u32 A_msg_buf_used[] __attribute((unused)) = {
-	0x00000108,
-	0x00000162,
-	0x0000016c,
-	0x00000172,
-	0x00000178,
-	0x0000017e,
-};
-
-#define A_reconnect_dsa_head	0x00000000
-static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
-	0x0000006d,
-	0x00000074,
-	0x000001b1,
-};
-
-#define A_reselected_identify	0x00000000
-static u32 A_reselected_identify_used[] __attribute((unused)) = {
-	0x00000048,
-	0x000001af,
-};
-
-#define A_reselected_tag	0x00000000
-static u32 A_reselected_tag_used[] __attribute((unused)) = {
-};
-
-#define A_saved_dsa	0x00000000
-static u32 A_saved_dsa_used[] __attribute((unused)) = {
-	0x00000005,
-	0x0000000e,
-	0x00000023,
-	0x00000025,
-	0x00000032,
-	0x0000003f,
-	0x00000054,
-	0x0000005f,
-	0x00000070,
-	0x00000078,
-	0x0000008d,
-	0x000000aa,
-	0x000000bb,
-	0x000000c0,
-	0x000000d1,
-	0x0000012f,
-	0x000001a4,
-	0x000001b5,
-	0x000001ba,
-	0x000001e2,
-};
-
-#define A_schedule	0x00000000
-static u32 A_schedule_used[] __attribute((unused)) = {
-	0x0000007d,
-	0x000001a7,
-	0x00000203,
-	0x00000244,
-};
-
-#define A_test_dest	0x00000000
-static u32 A_test_dest_used[] __attribute((unused)) = {
-	0x0000021c,
-};
-
-#define A_test_src	0x00000000
-static u32 A_test_src_used[] __attribute((unused)) = {
-	0x0000021b,
-};
-
-#define Ent_accept_message	0x00000624
-#define Ent_cmdout_cmdout	0x00000264
-#define Ent_command_complete	0x0000065c
-#define Ent_command_complete_msgin	0x0000066c
-#define Ent_data_transfer	0x0000026c
-#define Ent_datain_to_jump	0x00000334
-#define Ent_debug_break	0x000008ec
-#define Ent_dsa_code_begin	0x00000000
-#define Ent_dsa_code_check_reselect	0x0000010c
-#define Ent_dsa_code_fix_jump	0x00000058
-#define Ent_dsa_code_restore_pointers	0x000000d8
-#define Ent_dsa_code_save_data_pointer	0x000000a4
-#define Ent_dsa_code_template	0x00000000
-#define Ent_dsa_code_template_end	0x00000178
-#define Ent_dsa_schedule	0x00000178
-#define Ent_dsa_zero	0x00000178
-#define Ent_end_data_transfer	0x000002a4
-#define Ent_initiator_abort	0x00000914
-#define Ent_msg_in	0x0000041c
-#define Ent_msg_in_restart	0x000003fc
-#define Ent_other_in	0x0000038c
-#define Ent_other_out	0x00000354
-#define Ent_other_transfer	0x000003c4
-#define Ent_reject_message	0x00000604
-#define Ent_reselected_check_next	0x000006f0
-#define Ent_reselected_ok	0x00000798
-#define Ent_respond_message	0x0000063c
-#define Ent_select	0x000001f8
-#define Ent_select_msgout	0x00000218
-#define Ent_target_abort	0x000008f4
-#define Ent_test_1	0x00000868
-#define Ent_test_2	0x0000087c
-#define Ent_test_2_msgout	0x0000089c
-#define Ent_wait_reselect	0x000006a8
-static u32 LABELPATCHES[] __attribute((unused)) = {
-	0x00000011,
-	0x0000001a,
-	0x0000001d,
-	0x00000028,
-	0x0000002a,
-	0x00000035,
-	0x00000038,
-	0x00000042,
-	0x00000050,
-	0x00000052,
-	0x0000006b,
-	0x00000083,
-	0x00000085,
-	0x00000090,
-	0x00000094,
-	0x00000096,
-	0x0000009c,
-	0x0000009e,
-	0x000000a2,
-	0x000000a4,
-	0x000000a6,
-	0x000000a8,
-	0x000000b6,
-	0x000000b9,
-	0x000000cc,
-	0x000000cf,
-	0x000000d8,
-	0x000000de,
-	0x000000e0,
-	0x000000e6,
-	0x000000ec,
-	0x000000ee,
-	0x000000f4,
-	0x000000fc,
-	0x000000fe,
-	0x0000010a,
-	0x0000010c,
-	0x0000010e,
-	0x00000110,
-	0x00000112,
-	0x00000118,
-	0x0000011a,
-	0x0000012d,
-	0x00000143,
-	0x00000158,
-	0x0000015c,
-	0x00000164,
-	0x00000166,
-	0x00000168,
-	0x0000016e,
-	0x0000017a,
-	0x000001ab,
-	0x000001b8,
-	0x000001bf,
-	0x000001c3,
-	0x000001c7,
-	0x000001cb,
-	0x000001e0,
-	0x000001f8,
-	0x00000207,
-	0x0000020f,
-	0x00000213,
-	0x00000217,
-	0x00000224,
-	0x00000226,
-	0x00000248,
-	0x0000024a,
-	0x0000024c,
-	0x0000024e,
-	0x00000250,
-	0x00000252,
-	0x00000256,
-	0x0000025a,
-	0x0000025c,
-	0x00000260,
-	0x00000262,
-	0x00000266,
-	0x00000268,
-};
-
-static struct {
-	u32	offset;
-	void		*address;
-} EXTERNAL_PATCHES[] __attribute((unused)) = {
-};
-
-static u32 INSTRUCTIONS __attribute((unused))	= 290;
-static u32 PATCHES __attribute((unused))	= 78;
-static u32 EXTERNAL_PATCHES_LEN __attribute((unused))	= 0;
diff --git a/drivers/scsi/53c7xx_u.h_shipped b/drivers/scsi/53c7xx_u.h_shipped
deleted file mode 100644
index 7b33717..0000000
--- a/drivers/scsi/53c7xx_u.h_shipped
+++ /dev/null
@@ -1,102 +0,0 @@
-#undef A_NCR53c7xx_msg_abort
-#undef A_NCR53c7xx_msg_reject
-#undef A_NCR53c7xx_sink
-#undef A_NCR53c7xx_zero
-#undef A_NOP_insn
-#undef A_addr_dsa
-#undef A_addr_reconnect_dsa_head
-#undef A_addr_scratch
-#undef A_addr_temp
-#undef A_dmode_memory_to_memory
-#undef A_dmode_memory_to_ncr
-#undef A_dmode_ncr_to_memory
-#undef A_dsa_check_reselect
-#undef A_dsa_cmdout
-#undef A_dsa_cmnd
-#undef A_dsa_datain
-#undef A_dsa_dataout
-#undef A_dsa_end
-#undef A_dsa_fields_start
-#undef A_dsa_msgin
-#undef A_dsa_msgout
-#undef A_dsa_msgout_other
-#undef A_dsa_next
-#undef A_dsa_restore_pointers
-#undef A_dsa_save_data_pointer
-#undef A_dsa_select
-#undef A_dsa_sscf_710
-#undef A_dsa_status
-#undef A_dsa_temp_addr_array_value
-#undef A_dsa_temp_addr_dsa_value
-#undef A_dsa_temp_addr_new_value
-#undef A_dsa_temp_addr_next
-#undef A_dsa_temp_addr_residual
-#undef A_dsa_temp_addr_saved_pointer
-#undef A_dsa_temp_addr_saved_residual
-#undef A_dsa_temp_lun
-#undef A_dsa_temp_next
-#undef A_dsa_temp_sync
-#undef A_dsa_temp_target
-#undef A_emulfly
-#undef A_int_debug_break
-#undef A_int_debug_panic
-#undef A_int_err_check_condition
-#undef A_int_err_no_phase
-#undef A_int_err_selected
-#undef A_int_err_unexpected_phase
-#undef A_int_err_unexpected_reselect
-#undef A_int_msg_1
-#undef A_int_msg_sdtr
-#undef A_int_msg_wdtr
-#undef A_int_norm_aborted
-#undef A_int_norm_command_complete
-#undef A_int_norm_disconnected
-#undef A_int_norm_emulateintfly
-#undef A_int_norm_reselect_complete
-#undef A_int_norm_reset
-#undef A_int_norm_select_complete
-#undef A_int_test_1
-#undef A_int_test_2
-#undef A_int_test_3
-#undef A_msg_buf
-#undef A_reconnect_dsa_head
-#undef A_reselected_identify
-#undef A_reselected_tag
-#undef A_saved_dsa
-#undef A_schedule
-#undef A_test_dest
-#undef A_test_src
-#undef Ent_accept_message
-#undef Ent_cmdout_cmdout
-#undef Ent_command_complete
-#undef Ent_command_complete_msgin
-#undef Ent_data_transfer
-#undef Ent_datain_to_jump
-#undef Ent_debug_break
-#undef Ent_dsa_code_begin
-#undef Ent_dsa_code_check_reselect
-#undef Ent_dsa_code_fix_jump
-#undef Ent_dsa_code_restore_pointers
-#undef Ent_dsa_code_save_data_pointer
-#undef Ent_dsa_code_template
-#undef Ent_dsa_code_template_end
-#undef Ent_dsa_schedule
-#undef Ent_dsa_zero
-#undef Ent_end_data_transfer
-#undef Ent_initiator_abort
-#undef Ent_msg_in
-#undef Ent_msg_in_restart
-#undef Ent_other_in
-#undef Ent_other_out
-#undef Ent_other_transfer
-#undef Ent_reject_message
-#undef Ent_reselected_check_next
-#undef Ent_reselected_ok
-#undef Ent_respond_message
-#undef Ent_select
-#undef Ent_select_msgout
-#undef Ent_target_abort
-#undef Ent_test_1
-#undef Ent_test_2
-#undef Ent_test_2_msgout
-#undef Ent_wait_reselect
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 96f4cab0..9b20617 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -304,18 +304,10 @@
 static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
 {
 	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-	struct scsi_cmnd *cmd = CCB->Command;
 
-	if (cmd->use_sg != 0) {
-		pci_unmap_sg(HostAdapter->PCI_Device,
-				(struct scatterlist *)cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
-				CCB->DataLength, cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(CCB->Command);
 	pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-			CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+			 CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
 
 	CCB->Command = NULL;
 	CCB->Status = BusLogic_CCB_Free;
@@ -2648,7 +2640,8 @@
 			 */
 			if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
 				struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
-				struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer;
+				struct SCSI_Inquiry *InquiryResult =
+					(struct SCSI_Inquiry *) scsi_sglist(Command);
 				TargetFlags->TargetExists = true;
 				TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
 				TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
@@ -2819,9 +2812,8 @@
 	int CDB_Length = Command->cmd_len;
 	int TargetID = Command->device->id;
 	int LogicalUnit = Command->device->lun;
-	void *BufferPointer = Command->request_buffer;
-	int BufferLength = Command->request_bufflen;
-	int SegmentCount = Command->use_sg;
+	int BufferLength = scsi_bufflen(Command);
+	int Count;
 	struct BusLogic_CCB *CCB;
 	/*
 	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
@@ -2851,36 +2843,35 @@
 			return 0;
 		}
 	}
+
 	/*
 	   Initialize the fields in the BusLogic Command Control Block (CCB).
 	 */
-	if (SegmentCount == 0 && BufferLength != 0) {
-		CCB->Opcode = BusLogic_InitiatorCCB;
-		CCB->DataLength = BufferLength;
-		CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
-				BufferPointer, BufferLength,
-				Command->sc_data_direction);
-	} else if (SegmentCount != 0) {
-		struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
-		int Segment, Count;
+	Count = scsi_dma_map(Command);
+	BUG_ON(Count < 0);
+	if (Count) {
+		struct scatterlist *sg;
+		int i;
 
-		Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
-				Command->sc_data_direction);
 		CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
 		CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
 		if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
 			CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
 		else
 			CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
-		for (Segment = 0; Segment < Count; Segment++) {
-			CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment);
-			CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment);
+
+		scsi_for_each_sg(Command, sg, Count, i) {
+			CCB->ScatterGatherList[i].SegmentByteCount =
+				sg_dma_len(sg);
+			CCB->ScatterGatherList[i].SegmentDataPointer =
+				sg_dma_address(sg);
 		}
-	} else {
+	} else if (!Count) {
 		CCB->Opcode = BusLogic_InitiatorCCB;
 		CCB->DataLength = BufferLength;
 		CCB->DataPointer = 0;
 	}
+
 	switch (CDB[0]) {
 	case READ_6:
 	case READ_10:
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 572034c..aac9cd9 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -738,7 +738,7 @@
 
 config SCSI_IBMMCA
 	tristate "IBMMCA SCSI support"
-	depends on MCA_LEGACY && SCSI
+	depends on MCA && SCSI
 	---help---
 	  This is support for the IBM SCSI adapter found in many of the PS/2
 	  series computers.  These machines have an MCA bus, so you need to
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index b1b6327..cba3967 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -37,7 +37,6 @@
 
 obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
-obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
 obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
 obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
@@ -53,8 +52,6 @@
 obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
 obj-$(CONFIG_SCSI_MAC_ESP)	+= mac_esp.o	NCR53C9x.o
 obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
-obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x.o	53c7xx.o
-obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000.o	53c7xx.o
 obj-$(CONFIG_SCSI_SIM710)	+= 53c700.o	sim710.o
 obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
 obj-$(CONFIG_SCSI_PSI240I)	+= psi240i.o
@@ -168,10 +165,8 @@
 oktagon_esp_mod-objs	:= oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
-clean-files :=	53c7xx_d.h 53c700_d.h	\
-		53c7xx_u.h 53c700_u.h
+clean-files :=	53c700_d.h 53c700_u.h
 
-$(obj)/53c7xx.o:   $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
 $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
 
 # If you want to play with the firmware, uncomment
@@ -179,11 +174,6 @@
 
 ifdef GENERATE_FIRMWARE
 
-$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl
-	$(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h)
-
-$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h
-
 $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl
 	$(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $<
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index bb3cb33..37de6b3 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -347,7 +347,7 @@
 		if((r & bit) == val)
 			return 0;
 		if(!in_interrupt())
-			yield();
+			cond_resched();
 		else
 			cpu_relax();
 	}
@@ -357,7 +357,7 @@
 static struct {
 	unsigned char value;
 	const char *name;
-} phases[] = {
+} phases[] __maybe_unused = {
 	{PHASE_DATAOUT, "DATAOUT"}, 
 	{PHASE_DATAIN, "DATAIN"}, 
 	{PHASE_CMDOUT, "CMDOUT"}, 
@@ -575,7 +575,8 @@
  *	Locks: none, irqs must be enabled on entry
  */
 
-static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
+static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
+						int possible)
 {
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
@@ -629,7 +630,8 @@
  *	Locks: none
  */
 
-static void __init NCR5380_print_options(struct Scsi_Host *instance)
+static void __init __maybe_unused
+NCR5380_print_options(struct Scsi_Host *instance)
 {
 	printk(" generic options"
 #ifdef AUTOPROBE_IRQ
@@ -703,8 +705,8 @@
 static
 char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
 
-static
-int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+	char *buffer, char **start, off_t offset, int length, int inout)
 {
 	char *pos = buffer;
 	struct NCR5380_hostdata *hostdata;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 713a108..bccf13f 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -299,7 +299,7 @@
 static irqreturn_t NCR5380_intr(int irq, void *dev_id);
 #endif
 static void NCR5380_main(struct work_struct *work);
-static void NCR5380_print_options(struct Scsi_Host *instance);
+static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
 #ifdef NDEBUG
 static void NCR5380_print_phase(struct Scsi_Host *instance);
 static void NCR5380_print(struct Scsi_Host *instance);
@@ -307,8 +307,8 @@
 static int NCR5380_abort(Scsi_Cmnd * cmd);
 static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
 static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
-off_t offset, int length, int inout);
+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+	char *buffer, char **start, off_t offset, int length, int inout);
 
 static void NCR5380_reselect(struct Scsi_Host *instance);
 static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 7c0b17f..eda8c48 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -698,7 +698,7 @@
 	int i;
 
 	VDEB(printk("NCR53c406a_queue called\n"));
-	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen));
+	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
 
 #if 0
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
@@ -785,8 +785,8 @@
 	unsigned char status, int_reg;
 #if USE_PIO
 	unsigned char pio_status;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
+	struct scatterlist *sg;
+        int i;
 #endif
 
 	VDEB(printk("NCR53c406a_intr called\n"));
@@ -866,22 +866,18 @@
 			current_SC->SCp.phase = data_out;
 			VDEB(printk("NCR53c406a: Data-Out phase\n"));
 			outb(FLUSH_FIFO, CMD_REG);
-			LOAD_DMA_COUNT(current_SC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(scsi_bufflen(current_SC));	/* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-			NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen);
+			NCR53c406a_dma_write(scsi_sglist(current_SC),
+                                             scsdi_bufflen(current_SC));
+
 #endif				/* USE_DMA */
 			outb(TRANSFER_INFO | DMA_OP, CMD_REG);
 #if USE_PIO
-			if (!current_SC->use_sg)	/* Don't use scatter-gather */
-				NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen);
-			else {	/* use scatter-gather */
-				sgcount = current_SC->use_sg;
-				sglist = current_SC->request_buffer;
-				while (sgcount--) {
-					NCR53c406a_pio_write(page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
-			}
+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+                                NCR53c406a_pio_write(page_address(sg->page) + sg->offset,
+                                                     sg->length);
+                        }
 			REG0;
 #endif				/* USE_PIO */
 		}
@@ -893,22 +889,17 @@
 			current_SC->SCp.phase = data_in;
 			VDEB(printk("NCR53c406a: Data-In phase\n"));
 			outb(FLUSH_FIFO, CMD_REG);
-			LOAD_DMA_COUNT(current_SC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(scsi_bufflen(current_SC));	/* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-			NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen);
+			NCR53c406a_dma_read(scsi_sglist(current_SC),
+                                            scsdi_bufflen(current_SC));
 #endif				/* USE_DMA */
 			outb(TRANSFER_INFO | DMA_OP, CMD_REG);
 #if USE_PIO
-			if (!current_SC->use_sg)	/* Don't use scatter-gather */
-				NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen);
-			else {	/* Use scatter-gather */
-				sgcount = current_SC->use_sg;
-				sglist = current_SC->request_buffer;
-				while (sgcount--) {
-					NCR53c406a_pio_read(page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
-			}
+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+                                NCR53c406a_pio_read(page_address(sg->page) + sg->offset,
+                                                    sg->length);
+                        }
 			REG0;
 #endif				/* USE_PIO */
 		}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 7f4241b..7cedc72 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -796,7 +796,7 @@
 *****************************************************************************/
 static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt)
 {				/* Create corresponding SCB     */
-	struct scatterlist *pSrbSG;
+	struct scatterlist *sg;
 	ORC_SG *pSG;		/* Pointer to SG list           */
 	int i, count_sg;
 	ESCB *pEScb;
@@ -813,30 +813,22 @@
 	pSCB->SCB_Reserved1 = 0;
 	pSCB->SCB_SGLen = 0;
 
-	if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
-		pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
-		if (SCpnt->use_sg) {
-			pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-			count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
-					SCpnt->sc_data_direction);
-			pSCB->SCB_SGLen = (U32) (count_sg * 8);
-			for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
-				pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
-				pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
-			}
-		} else if (SCpnt->request_bufflen != 0) {/* Non SG */
-			pSCB->SCB_SGLen = 0x8;
-			SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev,
-					SCpnt->request_buffer,
-					SCpnt->request_bufflen,
-					SCpnt->sc_data_direction);
-			pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle;
-			pSG->SG_Len = (U32) SCpnt->request_bufflen;
-		} else {
-			pSCB->SCB_SGLen = 0;
-			pSG->SG_Ptr = 0;
-			pSG->SG_Len = 0;
+	pSCB->SCB_XferLen = (U32) scsi_bufflen(SCpnt);
+	pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
+
+	count_sg = scsi_dma_map(SCpnt);
+	BUG_ON(count_sg < 0);
+	if (count_sg) {
+		pSCB->SCB_SGLen = (U32) (count_sg * 8);
+		scsi_for_each_sg(SCpnt, sg, count_sg, i) {
+			pSG->SG_Ptr = (U32) sg_dma_address(sg);
+			pSG->SG_Len = (U32) sg_dma_len(sg);
+			pSG++;
 		}
+	} else {
+		pSCB->SCB_SGLen = 0;
+		pSG->SG_Ptr = 0;
+		pSG->SG_Len = 0;
 	}
 	pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
 	pSCB->SCB_HaStat = 0;
@@ -995,15 +987,7 @@
 	}
 	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
 
-	if (pSRB->use_sg) {
-		pci_unmap_sg(pHCB->pdev,
-			     (struct scatterlist *)pSRB->request_buffer,
-			     pSRB->use_sg, pSRB->sc_data_direction);
-	} else if (pSRB->request_bufflen != 0) {
-		pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle,
-				 pSRB->request_bufflen,
-				 pSRB->sc_data_direction);
-	}
+	scsi_dma_unmap(pSRB);
 
 	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
 
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 8dcfe4e..47014be 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -825,7 +825,7 @@
 	readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
 	readcmd->count = cpu_to_le32(count<<9);
 	readcmd->cid = cpu_to_le16(scmd_id(cmd));
-	readcmd->flags = cpu_to_le16(1);
+	readcmd->flags = cpu_to_le16(IO_TYPE_READ);
 	readcmd->bpTotal = 0;
 	readcmd->bpComplete = 0;
 
@@ -904,7 +904,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_raw_io *writecmd;
@@ -914,7 +914,9 @@
 	writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
 	writecmd->count = cpu_to_le32(count<<9);
 	writecmd->cid = cpu_to_le16(scmd_id(cmd));
-	writecmd->flags = 0;
+	writecmd->flags = fua ?
+		cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
+		cpu_to_le16(IO_TYPE_WRITE);
 	writecmd->bpTotal = 0;
 	writecmd->bpComplete = 0;
 
@@ -933,7 +935,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_write64 *writecmd;
@@ -964,7 +966,7 @@
 			  (void *) cmd);
 }
 
-static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
 {
 	u16 fibsize;
 	struct aac_write *writecmd;
@@ -1498,6 +1500,7 @@
 {
 	u64 lba;
 	u32 count;
+	int fua;
 	int status;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
@@ -1512,6 +1515,7 @@
 		count = scsicmd->cmnd[4];
 		if (count == 0)
 			count = 256;
+		fua = 0;
 	} else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
 		dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
 
@@ -1524,6 +1528,7 @@
 			(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
 		count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
 			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+		fua = scsicmd->cmnd[1] & 0x8;
 	} else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
 		dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
 
@@ -1531,10 +1536,12 @@
 		    | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
 		      | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+		fua = scsicmd->cmnd[1] & 0x8;
 	} else {
 		dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
 		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
+		fua = scsicmd->cmnd[1] & 0x8;
 	}
 	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
@@ -1549,7 +1556,7 @@
 		return 0;
 	}
 
-	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
+	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -1886,15 +1893,29 @@
 
 	case MODE_SENSE:
 	{
-		char mode_buf[4];
+		char mode_buf[7];
+		int mode_buf_length = 4;
 
 		dprintk((KERN_DEBUG "MODE SENSE command.\n"));
 		mode_buf[0] = 3;	/* Mode data length */
 		mode_buf[1] = 0;	/* Medium type - default */
-		mode_buf[2] = 0;	/* Device-specific param, bit 8: 0/1 = write enabled/protected */
+		mode_buf[2] = 0;	/* Device-specific param,
+					   bit 8: 0/1 = write enabled/protected
+					   bit 4: 0/1 = FUA enabled */
+		if (dev->raw_io_interface)
+			mode_buf[2] = 0x10;
 		mode_buf[3] = 0;	/* Block descriptor length */
-
-		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
+		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+			mode_buf[0] = 6;
+			mode_buf[4] = 8;
+			mode_buf[5] = 1;
+			mode_buf[6] = 0x04; /* WCE */
+			mode_buf_length = 7;
+			if (mode_buf_length > scsicmd->cmnd[4])
+				mode_buf_length = scsicmd->cmnd[4];
+		}
+		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
 
@@ -1902,18 +1923,33 @@
 	}
 	case MODE_SENSE_10:
 	{
-		char mode_buf[8];
+		char mode_buf[11];
+		int mode_buf_length = 8;
 
 		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
 		mode_buf[0] = 0;	/* Mode data length (MSB) */
 		mode_buf[1] = 6;	/* Mode data length (LSB) */
 		mode_buf[2] = 0;	/* Medium type - default */
-		mode_buf[3] = 0;	/* Device-specific param, bit 8: 0/1 = write enabled/protected */
+		mode_buf[3] = 0;	/* Device-specific param,
+					   bit 8: 0/1 = write enabled/protected
+					   bit 4: 0/1 = FUA enabled */
+		if (dev->raw_io_interface)
+			mode_buf[3] = 0x10;
 		mode_buf[4] = 0;	/* reserved */
 		mode_buf[5] = 0;	/* reserved */
 		mode_buf[6] = 0;	/* Block descriptor length (MSB) */
 		mode_buf[7] = 0;	/* Block descriptor length (LSB) */
-		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
+		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+			mode_buf[1] = 9;
+			mode_buf[8] = 8;
+			mode_buf[9] = 1;
+			mode_buf[10] = 0x04; /* WCE */
+			mode_buf_length = 11;
+			if (mode_buf_length > scsicmd->cmnd[8])
+				mode_buf_length = scsicmd->cmnd[8];
+		}
+		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
 
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index c81edf3..fdbedb1 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -464,12 +464,12 @@
 	int  (*adapter_restart)(struct aac_dev *dev, int bled);
 	/* Transport operations */
 	int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
-	irqreturn_t (*adapter_intr)(int irq, void *dev_id);
+	irq_handler_t adapter_intr;
 	/* Packet operations */
 	int  (*adapter_deliver)(struct fib * fib);
 	int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
 	int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
-	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua);
 	int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
 	/* Administrative operations */
 	int  (*adapter_comm)(struct aac_dev * dev, int comm);
@@ -1054,8 +1054,8 @@
 #define aac_adapter_read(fib,cmd,lba,count) \
 	((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
 
-#define aac_adapter_write(fib,cmd,lba,count) \
-	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
+#define aac_adapter_write(fib,cmd,lba,count,fua) \
+	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua)
 
 #define aac_adapter_scsi(fib,cmd) \
 	((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
@@ -1213,6 +1213,9 @@
 	__le32 		block;
 	__le16		pad;
 	__le16		flags;
+#define	IO_TYPE_WRITE 0x00000000
+#define	IO_TYPE_READ  0x00000001
+#define	IO_SUREWRITE  0x00000008
 	struct sgmap64	sg;	// Must be last in struct because it is variable
 };
 struct aac_write_reply
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 350ea7f..a270a3f 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -403,10 +403,6 @@
 
 static int aac_slave_configure(struct scsi_device *sdev)
 {
-	if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
-		sdev->skip_ms_page_8 = 1;
-		sdev->skip_ms_page_3f = 1;
-	}
 	if ((sdev->type == TYPE_DISK) &&
 			(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
 		if (expose_physicals == 0)
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 9b3303b..2b66897 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -798,7 +798,6 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
-#include "advansys.h"
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif /* CONFIG_PCI */
@@ -2014,7 +2013,7 @@
 STATIC void      AscEnableIsaDma(uchar);
 #endif /* CONFIG_ISA */
 STATIC ASC_DCNT  AscGetMaxDmaCount(ushort);
-
+static const char *advansys_info(struct Scsi_Host *shp);
 
 /*
  * --- Adv Library Constants and Macros
@@ -3970,10 +3969,6 @@
     ASC_IS_PCI,
 };
 
-/*
- * Used with the LILO 'advansys' option to eliminate or
- * limit I/O port probing at boot time, cf. advansys_setup().
- */
 STATIC int asc_iopflag = ASC_FALSE;
 STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
 
@@ -4055,10 +4050,6 @@
 #endif /* ADVANSYS_DEBUG */
 
 
-/*
- * --- Linux 'struct scsi_host_template' and advansys_setup() Functions
- */
-
 #ifdef CONFIG_PROC_FS
 /*
  * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
@@ -4080,7 +4071,7 @@
  * if 'prtbuf' is too small it will not be overwritten. Instead the
  * user just won't get all the available statistics.
  */
-int
+static int
 advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
 		off_t offset, int length, int inout)
 {
@@ -4296,7 +4287,7 @@
  * it must not call SCSI mid-level functions including scsi_malloc()
  * and scsi_free().
  */
-int __init
+static int __init
 advansys_detect(struct scsi_host_template *tpnt)
 {
     static int          detect_called = ASC_FALSE;
@@ -5428,7 +5419,7 @@
  *
  * Release resources allocated for a single AdvanSys adapter.
  */
-int
+static int
 advansys_release(struct Scsi_Host *shp)
 {
     asc_board_t    *boardp;
@@ -5475,7 +5466,7 @@
  * Note: The information line should not exceed ASC_INFO_SIZE bytes,
  * otherwise the static 'info' array will be overrun.
  */
-const char *
+static const char *
 advansys_info(struct Scsi_Host *shp)
 {
     static char     info[ASC_INFO_SIZE];
@@ -5568,7 +5559,7 @@
  * This function always returns 0. Command return status is saved
  * in the 'scp' result field.
  */
-int
+static int
 advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
     struct Scsi_Host    *shp;
@@ -5656,7 +5647,7 @@
  * sleeping is allowed and no locking other than for host structures is
  * required. Returns SUCCESS or FAILED.
  */
-int
+static int
 advansys_reset(struct scsi_cmnd *scp)
 {
     struct Scsi_Host     *shp;
@@ -5841,7 +5832,7 @@
  * ip[1]: sectors
  * ip[2]: cylinders
  */
-int
+static int
 advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int ip[])
 {
@@ -5875,82 +5866,6 @@
 }
 
 /*
- * advansys_setup()
- *
- * This function is called from init/main.c at boot time.
- * It it passed LILO parameters that can be set from the
- * LILO command line or in /etc/lilo.conf.
- *
- * It is used by the AdvanSys driver to either disable I/O
- * port scanning or to limit scanning to 1 - 4 I/O ports.
- * Regardless of the option setting EISA and PCI boards
- * will still be searched for and detected. This option
- * only affects searching for ISA and VL boards.
- *
- * If ADVANSYS_DEBUG is defined the driver debug level may
- * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
- *
- * Examples:
- * 1. Eliminate I/O port scanning:
- *         boot: linux advansys=
- *       or
- *         boot: linux advansys=0x0
- * 2. Limit I/O port scanning to one I/O port:
- *        boot: linux advansys=0x110
- * 3. Limit I/O port scanning to four I/O ports:
- *        boot: linux advansys=0x110,0x210,0x230,0x330
- * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
- *    set the driver debug level to 2.
- *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
- *
- * ints[0] - number of arguments
- * ints[1] - first argument
- * ints[2] - second argument
- * ...
- */
-void __init
-advansys_setup(char *str, int *ints)
-{
-    int    i;
-
-    if (asc_iopflag == ASC_TRUE) {
-        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
-        return;
-    }
-
-    asc_iopflag = ASC_TRUE;
-
-    if (ints[0] > ASC_NUM_IOPORT_PROBE) {
-#ifdef ADVANSYS_DEBUG
-        if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
-            (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
-            asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
-        } else {
-#endif /* ADVANSYS_DEBUG */
-            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
-                ASC_NUM_IOPORT_PROBE);
-#ifdef ADVANSYS_DEBUG
-        }
-#endif /* ADVANSYS_DEBUG */
-    }
-
-#ifdef ADVANSYS_DEBUG
-    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
-    for (i = 1; i < ints[0]; i++) {
-        ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]);
-    }
-    ASC_DBG(1, "\n");
-#endif /* ADVANSYS_DEBUG */
-
-    for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
-        asc_ioport[i-1] = ints[i];
-        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n",
-            i - 1, asc_ioport[i-1]);
-    }
-}
-
-
-/*
  * --- Loadable Driver Support
  */
 
diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
deleted file mode 100644
index 8ee7fb1..0000000
--- a/drivers/scsi/advansys.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
- * 
- * Copyright (c) 1995-2000 Advanced System Products, Inc.
- * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
- * changed its name to ConnectCom Solutions, Inc.
- *
- */
-
-#ifndef _ADVANSYS_H
-#define _ADVANSYS_H
-
-/*
- * struct scsi_host_template function prototypes.
- */
-int advansys_detect(struct scsi_host_template *);
-int advansys_release(struct Scsi_Host *);
-const char *advansys_info(struct Scsi_Host *);
-int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *));
-int advansys_reset(struct scsi_cmnd *);
-int advansys_biosparam(struct scsi_device *, struct block_device *,
-		sector_t, int[]);
-static int advansys_slave_configure(struct scsi_device *);
-
-/* init/main.c setup function */
-void advansys_setup(char *, int *);
-
-#endif /* _ADVANSYS_H */
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 4b4d123..85f2394 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -240,6 +240,7 @@
 #include <linux/io.h>
 #include <linux/blkdev.h>
 #include <asm/system.h>
+#include <linux/completion.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/wait.h>
@@ -253,7 +254,6 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
-#include <asm/semaphore.h>
 #include <scsi/scsicam.h>
 
 #include "scsi.h"
@@ -551,7 +551,7 @@
  */
 struct aha152x_scdata {
 	Scsi_Cmnd *next;	/* next sc in queue */
-	struct semaphore *sem;	/* semaphore to block on */
+	struct completion *done;/* semaphore to block on */
 	unsigned char cmd_len;
 	unsigned char cmnd[MAX_COMMAND_SIZE];
 	unsigned short use_sg;
@@ -608,7 +608,7 @@
 
 #define SCDATA(SCpnt)		((struct aha152x_scdata *) (SCpnt)->host_scribble)
 #define SCNEXT(SCpnt)		SCDATA(SCpnt)->next
-#define SCSEM(SCpnt)		SCDATA(SCpnt)->sem
+#define SCSEM(SCpnt)		SCDATA(SCpnt)->done
 
 #define SG_ADDRESS(buffer)	((char *) (page_address((buffer)->page)+(buffer)->offset))
 
@@ -969,7 +969,8 @@
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
+static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
+		int phase, void (*done)(Scsi_Cmnd *))
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
 	unsigned long flags;
@@ -1013,7 +1014,7 @@
 	}
 
 	SCNEXT(SCpnt)		= NULL;
-	SCSEM(SCpnt)		= sem;
+	SCSEM(SCpnt)		= complete;
 
 	/* setup scratch area
 	   SCp.ptr              : buffer pointer
@@ -1084,9 +1085,9 @@
 	DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt));
 #endif
 	if(SCSEM(SCpnt)) {
-		up(SCSEM(SCpnt));
+		complete(SCSEM(SCpnt));
 	} else {
-		printk(KERN_ERR "aha152x: reset_done w/o semaphore\n");
+		printk(KERN_ERR "aha152x: reset_done w/o completion\n");
 	}
 }
 
@@ -1139,21 +1140,6 @@
 	return FAILED;
 }
 
-static void timer_expired(unsigned long p)
-{
-	Scsi_Cmnd	 *SCp   = (Scsi_Cmnd *)p;
-	struct semaphore *sem   = SCSEM(SCp);
-	struct Scsi_Host *shpnt = SCp->device->host;
-	unsigned long flags;
-
-	/* remove command from issue queue */
-	DO_LOCK(flags);
-	remove_SC(&ISSUE_SC, SCp);
-	DO_UNLOCK(flags);
-
-	up(sem);
-}
-
 /*
  * Reset a device
  *
@@ -1161,14 +1147,14 @@
 static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
 {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
-	DECLARE_MUTEX_LOCKED(sem);
-	struct timer_list timer;
+	DECLARE_COMPLETION(done);
 	int ret, issued, disconnected;
 	unsigned char old_cmd_len = SCpnt->cmd_len;
 	unsigned short old_use_sg = SCpnt->use_sg;
 	void *old_buffer = SCpnt->request_buffer;
 	unsigned old_bufflen = SCpnt->request_bufflen;
 	unsigned long flags;
+	unsigned long timeleft;
 
 #if defined(AHA152X_DEBUG)
 	if(HOSTDATA(shpnt)->debug & debug_eh) {
@@ -1192,15 +1178,15 @@
 	SCpnt->request_buffer  = NULL;
 	SCpnt->request_bufflen = 0;
 
-	init_timer(&timer);
-	timer.data     = (unsigned long) SCpnt;
-	timer.expires  = jiffies + 100*HZ;   /* 10s */
-	timer.function = (void (*)(unsigned long)) timer_expired;
+	aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
 
-	aha152x_internal_queue(SCpnt, &sem, resetting, reset_done);
-	add_timer(&timer);
-	down(&sem);
-	del_timer(&timer);
+	timeleft = wait_for_completion_timeout(&done, 100*HZ);
+	if (!timeleft) {
+		/* remove command from issue queue */
+		DO_LOCK(flags);
+		remove_SC(&ISSUE_SC, SCpnt);
+		DO_UNLOCK(flags);
+	}
 
 	SCpnt->cmd_len         = old_cmd_len;
 	SCpnt->use_sg          = old_use_sg;
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index d7af9c6..e4a4f3a 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -271,20 +271,8 @@
 				continue;
 			}
 			sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
-			if (SCtmp->use_sg) {
-				/* We used scatter-gather.
-				   Do the unmapping dance. */
-				dma_unmap_sg (&edev->dev,
-					      (struct scatterlist *) SCtmp->request_buffer,
-					      SCtmp->use_sg,
-					      SCtmp->sc_data_direction);
-			} else {
-				dma_unmap_single (&edev->dev,
-						  sgptr->buf_dma_addr,
-						  SCtmp->request_bufflen,
-						  DMA_BIDIRECTIONAL);
-			}
-	    
+			scsi_dma_unmap(SCtmp);
+
 			/* Free the sg block */
 			dma_free_coherent (&edev->dev,
 					   sizeof (struct aha1740_sg),
@@ -349,11 +337,9 @@
 	unchar target = scmd_id(SCpnt);
 	struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
 	unsigned long flags;
-	void *buff = SCpnt->request_buffer;
-	int bufflen = SCpnt->request_bufflen;
 	dma_addr_t sg_dma;
 	struct aha1740_sg *sgptr;
-	int ecbno;
+	int ecbno, nseg;
 	DEB(int i);
 
 	if(*cmd == REQUEST_SENSE) {
@@ -423,24 +409,23 @@
 	}
 	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
 	sgptr->sg_dma_addr = sg_dma;
-    
-	if (SCpnt->use_sg) {
-		struct scatterlist * sgpnt;
+
+	nseg = scsi_dma_map(SCpnt);
+	BUG_ON(nseg < 0);
+	if (nseg) {
+		struct scatterlist *sg;
 		struct aha1740_chain * cptr;
-		int i, count;
+		int i;
 		DEB(unsigned char * ptr);
 
 		host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
 					   * w/scatter-gather*/
-		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 		cptr = sgptr->sg_chain;
-		count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg,
-				    SCpnt->sc_data_direction);
-		for(i=0; i < count; i++) {
-			cptr[i].datalen = sg_dma_len (sgpnt + i);
-			cptr[i].dataptr = sg_dma_address (sgpnt + i);
+		scsi_for_each_sg(SCpnt, sg, nseg, i) {
+			cptr[i].datalen = sg_dma_len (sg);
+			cptr[i].dataptr = sg_dma_address (sg);
 		}
-		host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain);
+		host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
 		host->ecb[ecbno].dataptr = sg_dma;
 #ifdef DEBUG
 		printk("cptr %x: ",cptr);
@@ -448,11 +433,8 @@
 		for(i=0;i<24;i++) printk("%02x ", ptr[i]);
 #endif
 	} else {
-		host->ecb[ecbno].datalen = bufflen;
-		sgptr->buf_dma_addr =  dma_map_single (&host->edev->dev,
-						       buff, bufflen,
-						       DMA_BIDIRECTIONAL);
-		host->ecb[ecbno].dataptr = sgptr->buf_dma_addr;
+		host->ecb[ecbno].datalen = 0;
+		host->ecb[ecbno].dataptr = 0;
 	}
 	host->ecb[ecbno].lun = SCpnt->device->lun;
 	host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 6054881..286ab83 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -376,21 +376,10 @@
 ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
 {
 	struct scsi_cmnd *cmd;
-	int direction;
 
 	cmd = scb->io_ctx;
-	direction = cmd->sc_data_direction;
 	ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
-	if (cmd->use_sg != 0) {
-		struct scatterlist *sg;
-
-		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahd->dev_softc,
-				 scb->platform_data->buf_busaddr,
-				 cmd->request_bufflen, direction);
-	}
+	scsi_dma_unmap(cmd);
 }
 
 /******************************** Macros **************************************/
@@ -1422,6 +1411,7 @@
 	u_int	 col_idx;
 	uint16_t mask;
 	unsigned long flags;
+	int nseg;
 
 	ahd_lock(ahd, &flags);
 
@@ -1494,18 +1484,17 @@
 	ahd_set_residual(scb, 0);
 	ahd_set_sense_residual(scb, 0);
 	scb->sg_count = 0;
-	if (cmd->use_sg != 0) {
-		void	*sg;
-		struct	 scatterlist *cur_seg;
-		u_int	 nseg;
-		int	 dir;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		dir = cmd->sc_data_direction;
-		nseg = pci_map_sg(ahd->dev_softc, cur_seg,
-				  cmd->use_sg, dir);
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (nseg > 0) {
+		void *sg = scb->sg_list;
+		struct scatterlist *cur_seg;
+		int i;
+
 		scb->platform_data->xfer_len = 0;
-		for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
+
+		scsi_for_each_sg(cmd, cur_seg, nseg, i) {
 			dma_addr_t addr;
 			bus_size_t len;
 
@@ -1513,22 +1502,8 @@
 			len = sg_dma_len(cur_seg);
 			scb->platform_data->xfer_len += len;
 			sg = ahd_sg_setup(ahd, scb, sg, addr, len,
-					  /*last*/nseg == 1);
+					  i == (nseg - 1));
 		}
-	} else if (cmd->request_bufflen != 0) {
-		void *sg;
-		dma_addr_t addr;
-		int dir;
-
-		sg = scb->sg_list;
-		dir = cmd->sc_data_direction;
-		addr = pci_map_single(ahd->dev_softc,
-				      cmd->request_buffer,
-				      cmd->request_bufflen, dir);
-		scb->platform_data->xfer_len = cmd->request_bufflen;
-		scb->platform_data->buf_busaddr = addr;
-		sg = ahd_sg_setup(ahd, scb, sg, addr,
-				  cmd->request_bufflen, /*last*/TRUE);
 	}
 
 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index ad9761b..853998b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -781,7 +781,7 @@
 static __inline
 void ahd_set_residual(struct scb *scb, u_long resid)
 {
-	scb->io_ctx->resid = resid;
+	scsi_set_resid(scb->io_ctx, resid);
 }
 
 static __inline
@@ -793,7 +793,7 @@
 static __inline
 u_long ahd_get_residual(struct scb *scb)
 {
-	return (scb->io_ctx->resid);
+	return scsi_get_resid(scb->io_ctx);
 }
 
 static __inline
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 660f26e..1803ab6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -402,18 +402,8 @@
 
 	cmd = scb->io_ctx;
 	ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
-	if (cmd->use_sg != 0) {
-		struct scatterlist *sg;
 
-		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,
-			     cmd->sc_data_direction);
-	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahc->dev_softc,
-				 scb->platform_data->buf_busaddr,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
-	}
+	scsi_dma_unmap(cmd);
 }
 
 static __inline int
@@ -1381,6 +1371,7 @@
 	struct	 ahc_tmode_tstate *tstate;
 	uint16_t mask;
 	struct scb_tailq *untagged_q = NULL;
+	int nseg;
 
 	/*
 	 * Schedule us to run later.  The only reason we are not
@@ -1472,23 +1463,21 @@
 	ahc_set_residual(scb, 0);
 	ahc_set_sense_residual(scb, 0);
 	scb->sg_count = 0;
-	if (cmd->use_sg != 0) {
+
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (nseg > 0) {
 		struct	ahc_dma_seg *sg;
 		struct	scatterlist *cur_seg;
-		struct	scatterlist *end_seg;
-		int	nseg;
+		int i;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
-				  cmd->sc_data_direction);
-		end_seg = cur_seg + nseg;
 		/* Copy the segments into the SG list. */
 		sg = scb->sg_list;
 		/*
 		 * The sg_count may be larger than nseg if
 		 * a transfer crosses a 32bit page.
-		 */ 
-		while (cur_seg < end_seg) {
+		 */
+		scsi_for_each_sg(cmd, cur_seg, nseg, i) {
 			dma_addr_t addr;
 			bus_size_t len;
 			int consumed;
@@ -1499,7 +1488,6 @@
 						     sg, addr, len);
 			sg += consumed;
 			scb->sg_count += consumed;
-			cur_seg++;
 		}
 		sg--;
 		sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
@@ -1516,33 +1504,6 @@
 		 */
 		scb->hscb->dataptr = scb->sg_list->addr;
 		scb->hscb->datacnt = scb->sg_list->len;
-	} else if (cmd->request_bufflen != 0) {
-		struct	 ahc_dma_seg *sg;
-		dma_addr_t addr;
-
-		sg = scb->sg_list;
-		addr = pci_map_single(ahc->dev_softc,
-				      cmd->request_buffer,
-				      cmd->request_bufflen,
-				      cmd->sc_data_direction);
-		scb->platform_data->buf_busaddr = addr;
-		scb->sg_count = ahc_linux_map_seg(ahc, scb,
-						  sg, addr,
-						  cmd->request_bufflen);
-		sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
-		/*
-		 * Reset the sg list pointer.
-		 */
-		scb->hscb->sgptr =
-			ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
-
-		/*
-		 * Copy the first SG into the "current"
-		 * data pointer area.
-		 */
-		scb->hscb->dataptr = sg->addr;
-		scb->hscb->datacnt = sg->len;
 	} else {
 		scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
 		scb->hscb->dataptr = 0;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 8fee7ed..b48dab4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -751,7 +751,7 @@
 static __inline
 void ahc_set_residual(struct scb *scb, u_long resid)
 {
-	scb->io_ctx->resid = resid;
+	scsi_set_resid(scb->io_ctx, resid);
 }
 
 static __inline
@@ -763,7 +763,7 @@
 static __inline
 u_long ahc_get_residual(struct scb *scb)
 {
-	return (scb->io_ctx->resid);
+	return scsi_get_resid(scb->io_ctx);
 }
 
 static __inline
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index a988d5a..f5e3c6b 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2690,17 +2690,8 @@
 	struct aic7xxx_scb *scbp;
 	unsigned char queue_depth;
 
-  if (cmd->use_sg > 1)
-  {
-    struct scatterlist *sg;
+        scsi_dma_unmap(cmd);
 
-    sg = (struct scatterlist *)cmd->request_buffer;
-    pci_unmap_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
-  }
-  else if (cmd->request_bufflen)
-    pci_unmap_single(p->pdev, aic7xxx_mapping(cmd),
-		     cmd->request_bufflen,
-                     cmd->sc_data_direction);
   if (scb->flags & SCB_SENSE)
   {
     pci_unmap_single(p->pdev,
@@ -3869,7 +3860,7 @@
        * the mid layer didn't check residual data counts to see if the
        * command needs retried.
        */
-      cmd->resid = scb->sg_length - actual;
+      scsi_set_resid(cmd, scb->sg_length - actual);
       aic7xxx_status(cmd) = hscb->target_status;
     }
   }
@@ -10137,6 +10128,7 @@
   struct scsi_device *sdptr = cmd->device;
   unsigned char tindex = TARGET_INDEX(cmd);
   struct request *req = cmd->request;
+  int use_sg;
 
   mask = (0x01 << tindex);
   hscb = scb->hscb;
@@ -10209,8 +10201,10 @@
   memcpy(scb->cmnd, cmd->cmnd, cmd->cmd_len);
   hscb->SCSI_cmd_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, scb->cmnd));
 
-  if (cmd->use_sg)
-  {
+  use_sg = scsi_dma_map(cmd);
+  BUG_ON(use_sg < 0);
+
+  if (use_sg) {
     struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
 
     /*
@@ -10219,11 +10213,11 @@
      * differences and the kernel SG list uses virtual addresses where
      * we need physical addresses.
      */
-    int i, use_sg;
+    int i;
 
-    sg = (struct scatterlist *)cmd->request_buffer;
     scb->sg_length = 0;
-    use_sg = pci_map_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
+
+
     /*
      * Copy the segments into the SG array.  NOTE!!! - We used to
      * have the first entry both in the data_pointer area and the first
@@ -10231,10 +10225,9 @@
      * entry in both places, but now we download the address of
      * scb->sg_list[1] instead of 0 to the sg pointer in the hscb.
      */
-    for (i = 0; i < use_sg; i++)
-    {
-      unsigned int len = sg_dma_len(sg+i);
-      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg+i));
+    scsi_for_each_sg(cmd, sg, use_sg, i) {
+      unsigned int len = sg_dma_len(sg);
+      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg));
       scb->sg_list[i].length = cpu_to_le32(len);
       scb->sg_length += len;
     }
@@ -10244,33 +10237,13 @@
     scb->sg_count = i;
     hscb->SG_segment_count = i;
     hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[1]));
-  }
-  else
-  {
-    if (cmd->request_bufflen)
-    {
-      unsigned int address = pci_map_single(p->pdev, cmd->request_buffer,
-					    cmd->request_bufflen,
-                                            cmd->sc_data_direction);
-      aic7xxx_mapping(cmd) = address;
-      scb->sg_list[0].address = cpu_to_le32(address);
-      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
-      scb->sg_count = 1;
-      scb->sg_length = cmd->request_bufflen;
-      hscb->SG_segment_count = 1;
-      hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[0]));
-      hscb->data_count = scb->sg_list[0].length;
-      hscb->data_pointer = scb->sg_list[0].address;
-    }
-    else
-    {
+  } else {
       scb->sg_count = 0;
       scb->sg_length = 0;
       hscb->SG_segment_count = 0;
       hscb->SG_list_pointer = 0;
       hscb->data_count = 0;
       hscb->data_pointer = 0;
-    }
   }
 }
 
diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
deleted file mode 100644
index d5d3c4d..0000000
--- a/drivers/scsi/amiga7xx.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
- *		Amiga MacroSystemUS WarpEngine SCSI controller.
- *		Amiga Technologies A4000T SCSI controller.
- *		Amiga Technologies/DKB A4091 SCSI controller.
- *
- * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
- * plus modifications of the 53c7xx.c driver to support the Amiga.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/zorro.h>
-#include <linux/stat.h>
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/dma.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "amiga7xx.h"
-
-
-static int amiga7xx_register_one(struct scsi_host_template *tpnt,
-				 unsigned long address)
-{
-    long long options;
-    int clock;
-
-    if (!request_mem_region(address, 0x1000, "ncr53c710"))
-	return 0;
-
-    address = (unsigned long)z_ioremap(address, 0x1000);
-    options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY |
-	      OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS |
-	      OPTION_DISCONNECT;
-    clock = 50000000;	/* 50 MHz SCSI Clock */
-    ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE,
-		   options, clock);
-    return 1;
-}
-
-
-#ifdef CONFIG_ZORRO
-
-static struct {
-    zorro_id id;
-    unsigned long offset;
-    int absolute;	/* offset is absolute address */
-} amiga7xx_table[] = {
-    { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000,
-      .absolute = 1 },
-    { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 },
-    { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 },
-    { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 },
-    { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 },
-    { 0 }
-};
-
-static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt)
-{
-    int num = 0, i;
-    struct zorro_dev *z = NULL;
-    unsigned long address;
-
-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-	for (i = 0; amiga7xx_table[i].id; i++)
-	    if (z->id == amiga7xx_table[i].id)
-		break;
-	if (!amiga7xx_table[i].id)
-	    continue;
-	if (amiga7xx_table[i].absolute)
-	    address = amiga7xx_table[i].offset;
-	else
-	    address = z->resource.start + amiga7xx_table[i].offset;
-	num += amiga7xx_register_one(tpnt, address);
-    }
-    return num;
-}
-
-#endif /* CONFIG_ZORRO */
-
-
-int __init amiga7xx_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int num = 0;
-
-    if (called || !MACH_IS_AMIGA)
-	return 0;
-
-    tpnt->proc_name = "Amiga7xx";
-
-    if (AMIGAHW_PRESENT(A4000_SCSI))
-	num += amiga7xx_register_one(tpnt, 0xdd0040);
-
-#ifdef CONFIG_ZORRO
-    num += amiga7xx_zorro_detect(tpnt);
-#endif
-
-    called = 1;
-    return num;
-}
-
-static int amiga7xx_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "Amiga NCR53c710 SCSI",
-	.detect			= amiga7xx_detect,
-	.release		= amiga7xx_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h
deleted file mode 100644
index 7cd63a9..0000000
--- a/drivers/scsi/amiga7xx.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef AMIGA7XX_H
-
-#include <linux/types.h>
-
-int amiga7xx_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* AMIGA7XX_H */
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 8b46158..672df79 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -369,19 +369,9 @@
 
 static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
 {
-	struct AdapterControlBlock *acb = ccb->acb;
 	struct scsi_cmnd *pcmd = ccb->pcmd;
 
-	if (pcmd->use_sg != 0) {
-		struct scatterlist *sl;
-
-		sl = (struct scatterlist *)pcmd->request_buffer;
-		pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
-	}
-	else if (pcmd->request_bufflen != 0)
-		pci_unmap_single(acb->pdev,
-			pcmd->SCp.dma_handle,
-			pcmd->request_bufflen, pcmd->sc_data_direction);
+	scsi_dma_unmap(pcmd);
 }
 
 static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
@@ -551,6 +541,7 @@
 	int8_t *psge = (int8_t *)&arcmsr_cdb->u;
 	uint32_t address_lo, address_hi;
 	int arccdbsize = 0x30;
+	int nseg;
 
 	ccb->pcmd = pcmd;
 	memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB));
@@ -561,20 +552,20 @@
 	arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len;
 	arcmsr_cdb->Context = (unsigned long)arcmsr_cdb;
 	memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
-	if (pcmd->use_sg) {
-		int length, sgcount, i, cdb_sgcount = 0;
-		struct scatterlist *sl;
 
-		/* Get Scatter Gather List from scsiport. */
-		sl = (struct scatterlist *) pcmd->request_buffer;
-		sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg,
-				pcmd->sc_data_direction);
+	nseg = scsi_dma_map(pcmd);
+	BUG_ON(nseg < 0);
+
+	if (nseg) {
+		int length, i, cdb_sgcount = 0;
+		struct scatterlist *sg;
+
 		/* map stor port SG list to our iop SG List. */
-		for (i = 0; i < sgcount; i++) {
+		scsi_for_each_sg(pcmd, sg, nseg, i) {
 			/* Get the physical address of the current data pointer */
-			length = cpu_to_le32(sg_dma_len(sl));
-			address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl)));
-			address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl)));
+			length = cpu_to_le32(sg_dma_len(sg));
+			address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg)));
+			address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg)));
 			if (address_hi == 0) {
 				struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
 
@@ -591,32 +582,12 @@
 				psge += sizeof (struct SG64ENTRY);
 				arccdbsize += sizeof (struct SG64ENTRY);
 			}
-			sl++;
 			cdb_sgcount++;
 		}
 		arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
-		arcmsr_cdb->DataLength = pcmd->request_bufflen;
+		arcmsr_cdb->DataLength = scsi_bufflen(pcmd);
 		if ( arccdbsize > 256)
 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
-	} else if (pcmd->request_bufflen) {
-		dma_addr_t dma_addr;
-		dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer,
-				pcmd->request_bufflen, pcmd->sc_data_direction);
-		pcmd->SCp.dma_handle = dma_addr;
-		address_lo = cpu_to_le32(dma_addr_lo32(dma_addr));
-		address_hi = cpu_to_le32(dma_addr_hi32(dma_addr));
-		if (address_hi == 0) {
-			struct  SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
-			pdma_sg->address = address_lo;
-			pdma_sg->length = pcmd->request_bufflen;
-		} else {
-			struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
-			pdma_sg->addresshigh = address_hi;
-			pdma_sg->address = address_lo;
-			pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR;
-		}
-		arcmsr_cdb->sgcount = 1;
-		arcmsr_cdb->DataLength = pcmd->request_bufflen;
 	}
 	if (pcmd->sc_data_direction == DMA_TO_DEVICE ) {
 		arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
@@ -848,24 +819,21 @@
 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
 	int retvalue = 0, transfer_len = 0;
 	char *buffer;
+	struct scatterlist *sg;
 	uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 |
 						(uint32_t ) cmd->cmnd[6] << 16 |
 						(uint32_t ) cmd->cmnd[7] << 8  |
 						(uint32_t ) cmd->cmnd[8];
 					/* 4 bytes: Areca io control code */
-	if (cmd->use_sg) {
-		struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
 
-		buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		if (cmd->use_sg > 1) {
-			retvalue = ARCMSR_MESSAGE_FAIL;
-			goto message_out;
-		}
-		transfer_len += sg->length;
-	} else {
-		buffer = cmd->request_buffer;
-		transfer_len = cmd->request_bufflen;
+	sg = scsi_sglist(cmd);
+	buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+	if (scsi_sg_count(cmd) > 1) {
+		retvalue = ARCMSR_MESSAGE_FAIL;
+		goto message_out;
 	}
+	transfer_len += sg->length;
+
 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
 		retvalue = ARCMSR_MESSAGE_FAIL;
 		goto message_out;
@@ -1057,12 +1025,9 @@
 		retvalue = ARCMSR_MESSAGE_FAIL;
 	}
  message_out:
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
+	sg = scsi_sglist(cmd);
+	kunmap_atomic(buffer - sg->offset, KM_IRQ0);
 
-		sg = (struct scatterlist *) cmd->request_buffer;
-		kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-	}
 	return retvalue;
 }
 
@@ -1085,6 +1050,7 @@
 	case INQUIRY: {
 		unsigned char inqdata[36];
 		char *buffer;
+		struct scatterlist *sg;
 
 		if (cmd->device->lun) {
 			cmd->result = (DID_TIME_OUT << 16);
@@ -1104,21 +1070,14 @@
 		strncpy(&inqdata[16], "RAID controller ", 16);
 		/* Product Identification */
 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
-		if (cmd->use_sg) {
-			struct scatterlist *sg;
 
-			sg = (struct scatterlist *) cmd->request_buffer;
-			buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-		} else {
-			buffer = cmd->request_buffer;
-		}
+		sg = scsi_sglist(cmd);
+		buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+
 		memcpy(buffer, inqdata, sizeof(inqdata));
-		if (cmd->use_sg) {
-			struct scatterlist *sg;
+		sg = scsi_sglist(cmd);
+		kunmap_atomic(buffer - sg->offset, KM_IRQ0);
 
-			sg = (struct scatterlist *) cmd->request_buffer;
-			kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-		}
 		cmd->scsi_done(cmd);
 	}
 	break;
diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
deleted file mode 100644
index 599b400..0000000
--- a/drivers/scsi/bvme6000.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
- *
- * Based on work by Alan Hourihane
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/zorro.h>
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/bvme6000hw.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "bvme6000.h"
-
-#include<linux/stat.h>
-
-
-int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int clock;
-    long long options;
-
-    if (called)
-	return 0;
-    if (!MACH_IS_BVME6000)
-	return 0;
-
-    tpnt->proc_name = "BVME6000";
-
-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
-
-    clock = 40000000;	/* 66MHz SCSI Clock */
-
-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
-			0, BVME_IRQ_SCSI, DMA_NONE,
-			options, clock);
-    called = 1;
-    return 1;
-}
-
-static int bvme6000_scsi_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "BVME6000 NCR53c710 SCSI",
-	.detect			= bvme6000_scsi_detect,
-	.release		= bvme6000_scsi_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h
deleted file mode 100644
index ea3e4b2..0000000
--- a/drivers/scsi/bvme6000.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef BVME6000_SCSI_H
-#define BVME6000_SCSI_H
-
-#include <linux/types.h>
-
-int bvme6000_scsi_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* BVME6000_SCSI_H */
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index 2d38025..a83e9f1 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1609,8 +1609,9 @@
 
 static void map_dma(unsigned int i, struct hostdata *ha)
 {
-	unsigned int k, count, pci_dir;
-	struct scatterlist *sgpnt;
+	unsigned int k, pci_dir;
+	int count;
+	struct scatterlist *sg;
 	struct mscp *cpp;
 	struct scsi_cmnd *SCpnt;
 
@@ -1625,38 +1626,19 @@
 
 	cpp->sense_len = sizeof SCpnt->sense_buffer;
 
-	if (!SCpnt->use_sg) {
-
-		/* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
-		if (!SCpnt->request_bufflen)
-			pci_dir = PCI_DMA_BIDIRECTIONAL;
-
-		if (SCpnt->request_buffer)
-			cpp->data_address = H2DEV(pci_map_single(ha->pdev,
-								 SCpnt->
-								 request_buffer,
-								 SCpnt->
-								 request_bufflen,
-								 pci_dir));
-
-		cpp->data_len = H2DEV(SCpnt->request_bufflen);
-		return;
-	}
-
-	sgpnt = (struct scatterlist *)SCpnt->request_buffer;
-	count = pci_map_sg(ha->pdev, sgpnt, SCpnt->use_sg, pci_dir);
-
-	for (k = 0; k < count; k++) {
-		cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
-		cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
+	count = scsi_dma_map(SCpnt);
+	BUG_ON(count < 0);
+	scsi_for_each_sg(SCpnt, sg, count, k) {
+		cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+		cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
 	}
 
 	cpp->sg = 1;
 	cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist,
-						 SCpnt->use_sg *
+						 scsi_sg_count(SCpnt) *
 						 sizeof(struct sg_list),
 						 pci_dir));
-	cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
+	cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list)));
 }
 
 static void unmap_dma(unsigned int i, struct hostdata *ha)
@@ -1673,9 +1655,7 @@
 		pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr),
 				 DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-	if (SCpnt->use_sg)
-		pci_unmap_sg(ha->pdev, SCpnt->request_buffer, SCpnt->use_sg,
-			     pci_dir);
+	scsi_dma_unmap(SCpnt);
 
 	if (!DEV2H(cpp->data_len))
 		pci_dir = PCI_DMA_BIDIRECTIONAL;
@@ -1700,9 +1680,9 @@
 					    DEV2H(cpp->sense_len),
 					    PCI_DMA_FROMDEVICE);
 
-	if (SCpnt->use_sg)
-		pci_dma_sync_sg_for_cpu(ha->pdev, SCpnt->request_buffer,
-					SCpnt->use_sg, pci_dir);
+	if (scsi_sg_count(SCpnt))
+		pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt),
+					scsi_sg_count(SCpnt), pci_dir);
 
 	if (!DEV2H(cpp->data_len))
 		pci_dir = PCI_DMA_BIDIRECTIONAL;
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 5d4ea6f..36169d5 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -410,6 +410,8 @@
 static char * fdomain = NULL;
 module_param(fdomain, charp, 0);
 
+#ifndef PCMCIA
+
 static unsigned long addresses[] = {
    0xc8000,
    0xca000,
@@ -426,6 +428,8 @@
 
 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 
+#endif /* !PCMCIA */
+
 /*
 
   READ THIS BEFORE YOU ADD A SIGNATURE!
@@ -458,6 +462,8 @@
 
 */
 
+#ifndef PCMCIA
+
 static struct signature {
    const char *signature;
    int  sig_offset;
@@ -503,6 +509,8 @@
 
 #define SIGNATURE_COUNT ARRAY_SIZE(signatures)
 
+#endif /* !PCMCIA */
+
 static void print_banner( struct Scsi_Host *shpnt )
 {
    if (!shpnt) return;		/* This won't ever happen */
@@ -633,6 +641,8 @@
    return 0;
 }
 
+#ifndef PCMCIA
+
 /* fdomain_get_irq assumes that we have a valid MCA ID for a
    TMC-1660/TMC-1680 Future Domain board.  Now, check to be sure the
    bios_base matches these ports.  If someone was unlucky enough to have
@@ -667,7 +677,6 @@
 
 static int fdomain_isa_detect( int *irq, int *iobase )
 {
-#ifndef PCMCIA
    int i, j;
    int base = 0xdeadbeef;
    int flag = 0;
@@ -786,11 +795,22 @@
    *iobase = base;
 
    return 1;			/* success */
-#else
-   return 0;
-#endif
 }
 
+#else /* PCMCIA */
+
+static int fdomain_isa_detect( int *irq, int *iobase )
+{
+	if (irq)
+		*irq = 0;
+	if (iobase)
+		*iobase = 0;
+	return 0;
+}
+
+#endif /* !PCMCIA */
+
+
 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
    iobase) This function gets the Interrupt Level and I/O base address from
    the PCI configuration registers. */
@@ -1345,16 +1365,15 @@
 
 #if ERRORS_ONLY
       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
-	 if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
+	      char *buf = scsi_sglist(current_SC);
+	 if ((unsigned char)(*(buf + 2)) & 0x0f) {
 	    unsigned char key;
 	    unsigned char code;
 	    unsigned char qualifier;
 
-	    key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
-		  & 0x0f;
-	    code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
-	    qualifier = (unsigned char)(*((char *)current_SC->request_buffer
-					  + 13));
+	    key = (unsigned char)(*(buf + 2)) & 0x0f;
+	    code = (unsigned char)(*(buf + 12));
+	    qualifier = (unsigned char)(*(buf + 13));
 
 	    if (key != UNIT_ATTENTION
 		&& !(key == NOT_READY
@@ -1405,8 +1424,8 @@
    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
 	   SCpnt->target,
 	   *(unsigned char *)SCpnt->cmnd,
-	   SCpnt->use_sg,
-	   SCpnt->request_bufflen );
+	   scsi_sg_count(SCpnt),
+	   scsi_bufflen(SCpnt));
 #endif
 
    fdomain_make_bus_idle();
@@ -1416,20 +1435,19 @@
 
    /* Initialize static data */
 
-   if (current_SC->use_sg) {
-      current_SC->SCp.buffer =
-	    (struct scatterlist *)current_SC->request_buffer;
-      current_SC->SCp.ptr              = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
-      current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
-      current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+   if (scsi_sg_count(current_SC)) {
+	   current_SC->SCp.buffer = scsi_sglist(current_SC);
+	   current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page)
+		   + current_SC->SCp.buffer->offset;
+	   current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
+	   current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
    } else {
-      current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
-      current_SC->SCp.this_residual    = current_SC->request_bufflen;
-      current_SC->SCp.buffer           = NULL;
-      current_SC->SCp.buffers_residual = 0;
+	   current_SC->SCp.ptr              = 0;
+	   current_SC->SCp.this_residual    = 0;
+	   current_SC->SCp.buffer           = NULL;
+	   current_SC->SCp.buffers_residual = 0;
    }
-	 
-   
+
    current_SC->SCp.Status              = 0;
    current_SC->SCp.Message             = 0;
    current_SC->SCp.have_data_in        = 0;
@@ -1472,8 +1490,8 @@
 	   SCpnt->SCp.phase,
 	   SCpnt->device->id,
 	   *(unsigned char *)SCpnt->cmnd,
-	   SCpnt->use_sg,
-	   SCpnt->request_bufflen );
+	   scsi_sg_count(SCpnt),
+	   scsi_bufflen(SCpnt));
    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
 	   SCpnt->SCp.sent_command,
 	   SCpnt->SCp.have_data_in,
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 60446b8..d0b95ce 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -876,7 +876,7 @@
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] __attribute_used__ = {
+static struct pci_device_id gdthtable[] __maybe_unused = {
     {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
@@ -1955,7 +1955,7 @@
         for (j = 0; j < 12; ++j) 
             rtc[j] = CMOS_READ(j);
     } while (rtc[0] != CMOS_READ(0));
-    spin_lock_irqrestore(&rtc_lock, flags);
+    spin_unlock_irqrestore(&rtc_lock, flags);
     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
     /* 3. send to controller firmware */
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 0e57fb6..4275d1b 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -31,14 +31,21 @@
 #include <linux/mca.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
-#include <linux/mca-legacy.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "ibmmca.h"
+
+/* Common forward declarations for all Linux-versions: */
+static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+static int ibmmca_abort (Scsi_Cmnd *);
+static int ibmmca_host_reset (Scsi_Cmnd *);
+static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
+static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout);
+
+
 
 /* current version of this driver-source: */
 #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac"
@@ -65,11 +72,11 @@
 #define IM_DEBUG_CMD_DEVICE	TYPE_TAPE
 
 /* relative addresses of hardware registers on a subsystem */
-#define IM_CMD_REG(hi)	(hosts[(hi)]->io_port)	/*Command Interface, (4 bytes long) */
-#define IM_ATTN_REG(hi)	(hosts[(hi)]->io_port+4)	/*Attention (1 byte) */
-#define IM_CTR_REG(hi)	(hosts[(hi)]->io_port+5)	/*Basic Control (1 byte) */
-#define IM_INTR_REG(hi)	(hosts[(hi)]->io_port+6)	/*Interrupt Status (1 byte, r/o) */
-#define IM_STAT_REG(hi)	(hosts[(hi)]->io_port+7)	/*Basic Status (1 byte, read only) */
+#define IM_CMD_REG(h)	((h)->io_port)	/*Command Interface, (4 bytes long) */
+#define IM_ATTN_REG(h)	((h)->io_port+4)	/*Attention (1 byte) */
+#define IM_CTR_REG(h)	((h)->io_port+5)	/*Basic Control (1 byte) */
+#define IM_INTR_REG(h)	((h)->io_port+6)	/*Interrupt Status (1 byte, r/o) */
+#define IM_STAT_REG(h)	((h)->io_port+7)	/*Basic Status (1 byte, read only) */
 
 /* basic I/O-port of first adapter */
 #define IM_IO_PORT	0x3540
@@ -266,30 +273,36 @@
     if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
     outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }
 
-/*list of supported subsystems */
-struct subsys_list_struct {
-	unsigned short mca_id;
-	char *description;
-};
-
 /* types of different supported hardware that goes to hostdata special */
 #define IBM_SCSI2_FW     0
 #define IBM_7568_WCACHE  1
 #define IBM_EXP_UNIT     2
 #define IBM_SCSI_WCACHE  3
 #define IBM_SCSI         4
+#define IBM_INTEGSCSI	 5
 
 /* other special flags for hostdata structure */
 #define FORCED_DETECTION         100
 #define INTEGRATED_SCSI          101
 
 /* List of possible IBM-SCSI-adapters */
-static struct subsys_list_struct subsys_list[] = {
-	{0x8efc, "IBM SCSI-2 F/W Adapter"},	/* special = 0 */
-	{0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"},	/* special = 1 */
-	{0x8ef8, "IBM Expansion Unit SCSI Controller"},	/* special = 2 */
-	{0x8eff, "IBM SCSI Adapter w/Cache"},	/* special = 3 */
-	{0x8efe, "IBM SCSI Adapter"},	/* special = 4 */
+static short ibmmca_id_table[] = {
+	0x8efc,
+	0x8efd,
+	0x8ef8,
+	0x8eff,
+	0x8efe,
+	/* No entry for integrated SCSI, that's part of the register */
+	0
+};
+
+static const char *ibmmca_description[] = {
+	"IBM SCSI-2 F/W Adapter",	/* special = 0 */
+	"IBM 7568 Industrial Computer SCSI Adapter w/Cache",	/* special = 1 */
+	"IBM Expansion Unit SCSI Controller",	/* special = 2 */
+	"IBM SCSI Adapter w/Cache",	/* special = 3 */
+	"IBM SCSI Adapter",	/* special = 4 */
+	"IBM Integrated SCSI Controller", /* special = 5 */
 };
 
 /* Max number of logical devices (can be up from 0 to 14).  15 is the address
@@ -375,30 +388,30 @@
 };
 
 /* macros to access host data structure */
-#define subsystem_pun(hi) (hosts[(hi)]->this_id)
-#define subsystem_maxid(hi) (hosts[(hi)]->max_id)
-#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
-#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
-#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
-#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
-#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
-#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
-#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
-#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
-#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
-#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount)
-#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block)
-#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
-#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
-#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
-#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
-#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size)
-#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed)
-#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[2])
-#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[3])
-#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[4])
-#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[5])
-#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[6])
+#define subsystem_pun(h) ((h)->this_id)
+#define subsystem_maxid(h) ((h)->max_id)
+#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld)
+#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn)
+#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi)
+#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag)
+#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt)
+#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result)
+#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status)
+#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command)
+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount)
+#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block)
+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn)
+#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS)
+#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special)
+#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size)
+#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed)
+#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2])
+#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3])
+#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4])
+#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5])
+#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6])
 
 /* Define a arbitrary number as subsystem-marker-type. This number is, as
    described in the ANSI-SCSI-standard, not occupied by other device-types. */
@@ -459,11 +472,6 @@
 /*counter of concurrent disk read/writes, to turn on/off disk led */
 static int disk_rw_in_progress = 0;
 
-/* host information */
-static int found = 0;
-static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = {
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
 static unsigned int pos[8];	/* whole pos register-line for diagnosis */
 /* Taking into account the additions, made by ZP Gu.
  * This selects now the preset value from the configfile and
@@ -474,70 +482,68 @@
 static char ibm_ansi_order = 0;
 #endif
 
-static void issue_cmd(int, unsigned long, unsigned char);
+static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char);
 static void internal_done(Scsi_Cmnd * cmd);
-static void check_devices(int, int);
-static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int);
-static int immediate_feature(int, unsigned int, unsigned int);
+static void check_devices(struct Scsi_Host *, int);
+static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int);
+static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int);
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(int, unsigned int);
+static int immediate_reset(struct Scsi_Host *, unsigned int);
 #endif
-static int device_inquiry(int, int);
-static int read_capacity(int, int);
-static int get_pos_info(int);
+static int device_inquiry(struct Scsi_Host *, int);
+static int read_capacity(struct Scsi_Host *, int);
+static int get_pos_info(struct Scsi_Host *);
 static char *ti_p(int);
 static char *ti_l(int);
 static char *ibmrate(unsigned int, int);
 static int probe_display(int);
-static int probe_bus_mode(int);
-static int device_exists(int, int, int *, int *);
-static struct Scsi_Host *ibmmca_register(struct scsi_host_template *, int, int, int, char *);
+static int probe_bus_mode(struct Scsi_Host *);
+static int device_exists(struct Scsi_Host *, int, int *, int *);
 static int option_setup(char *);
 /* local functions needed for proc_info */
-static int ldn_access_load(int, int);
-static int ldn_access_total_read_write(int);
+static int ldn_access_load(struct Scsi_Host *, int);
+static int ldn_access_total_read_write(struct Scsi_Host *);
 
 static irqreturn_t interrupt_handler(int irq, void *dev_id)
 {
-	int host_index, ihost_index;
 	unsigned int intr_reg;
 	unsigned int cmd_result;
 	unsigned int ldn;
+	unsigned long flags;
 	Scsi_Cmnd *cmd;
 	int lastSCSI;
-	struct Scsi_Host *dev = dev_id;
+	struct device *dev = dev_id;
+	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 
-	spin_lock(dev->host_lock);
-	    /* search for one adapter-response on shared interrupt */
-	    for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++);
-	/* return if some other device on this IRQ caused the interrupt */
-	if (!hosts[host_index]) {
-		spin_unlock(dev->host_lock);
+	spin_lock_irqsave(shpnt->host_lock, flags);
+
+	if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) {
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_NONE;
 	}
 
 	/* the reset-function already did all the job, even ints got
 	   renabled on the subsystem, so just return */
-	if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) {
-		reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
-		spin_unlock(dev->host_lock);
+	if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) {
+		reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 
 	/*must wait for attention reg not busy, then send EOI to subsystem */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 		cpu_relax();
 	}
-	ihost_index = host_index;
+
 	/*get command result and logical device */
-	intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index)));
+	intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt)));
 	cmd_result = intr_reg & 0xf0;
 	ldn = intr_reg & 0x0f;
 	/* get the last_scsi_command here */
-	lastSCSI = last_scsi_command(ihost_index)[ldn];
-	outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index));
+	lastSCSI = last_scsi_command(shpnt)[ldn];
+	outb(IM_EOI | ldn, IM_ATTN_REG(shpnt));
 	
 	/*these should never happen (hw fails, or a local programming bug) */
 	if (!global_command_error_excuse) {
@@ -547,38 +553,38 @@
 		case IM_SOFTWARE_SEQUENCING_ERROR:
 		case IM_CMD_ERROR:
 			printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n");
-			printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable);
-			if (ld(ihost_index)[ldn].cmd)
-				printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length));
+			printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable);
+			if (ld(shpnt)[ldn].cmd)
+				printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length));
 			else
 				printk("none,");
-			if (ld(ihost_index)[ldn].cmd)
-				printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length);
+			if (ld(shpnt)[ldn].cmd)
+				printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length);
 			else
 				printk("Blocksize=none");
-			printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn);
-			if (ld(ihost_index)[ldn].cmd) {
-				printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count);
-				printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr);
+			printk(", host=%p, ldn=0x%x\n", shpnt, ldn);
+			if (ld(shpnt)[ldn].cmd) {
+				printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count);
+				printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr);
 			}
 			printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
 			/* if errors appear, enter this section to give detailed info */
 			printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n");
-			printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]);
-			printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index)));
-			printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index)));
+			printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(shpnt)[ldn]);
+			printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt)));
+			printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt)));
 			printk(KERN_ERR "              Interrupt Status Register...: %x\n", intr_reg);
-			printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index)));
-			if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) {
-				printk(KERN_ERR "              SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command);
-				printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable);
-				printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr);
-				printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr);
-				printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length);
-				printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr);
-				printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr);
-				printk(KERN_ERR "              SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count);
-				printk(KERN_ERR "              SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length);
+			printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt)));
+			if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) {
+				printk(KERN_ERR "              SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command);
+				printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable);
+				printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr);
+				printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr);
+				printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length);
+				printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr);
+				printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr);
+				printk(KERN_ERR "              SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count);
+				printk(KERN_ERR "              SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length);
 			}
 			printk(KERN_ERR "              Send this report to the maintainer.\n");
 			panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result);
@@ -600,72 +606,73 @@
 		}
 	}
 	/* if no panic appeared, increase the interrupt-counter */
-	IBM_DS(ihost_index).total_interrupts++;
+	IBM_DS(shpnt).total_interrupts++;
 	/*only for local checking phase */
-	if (local_checking_phase_flag(ihost_index)) {
-		stat_result(ihost_index) = cmd_result;
-		got_interrupt(ihost_index) = 1;
-		reset_status(ihost_index) = IM_RESET_FINISHED_OK;
-		last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-		spin_unlock(dev->host_lock);
+	if (local_checking_phase_flag(shpnt)) {
+		stat_result(shpnt) = cmd_result;
+		got_interrupt(shpnt) = 1;
+		reset_status(shpnt) = IM_RESET_FINISHED_OK;
+		last_scsi_command(shpnt)[ldn] = NO_SCSI;
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 	/* handling of commands coming from upper level of scsi driver */
-	if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) {
+	if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) {
 		/* verify ldn, and may handle rare reset immediate command */
-		if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) {
+		if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) {
 			if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
 				disk_rw_in_progress = 0;
 				PS2_DISK_LED_OFF();
-				reset_status(ihost_index) = IM_RESET_FINISHED_FAIL;
+				reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 			} else {
 				/*reset disk led counter, turn off disk led */
 				disk_rw_in_progress = 0;
 				PS2_DISK_LED_OFF();
-				reset_status(ihost_index) = IM_RESET_FINISHED_OK;
+				reset_status(shpnt) = IM_RESET_FINISHED_OK;
 			}
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			last_scsi_type(ihost_index)[ldn] = 0;
-			spin_unlock(dev->host_lock);
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			last_scsi_type(shpnt)[ldn] = 0;
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
-		} else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) {
+		} else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) {
 			/* react on SCSI abort command */
 #ifdef IM_DEBUG_PROBE
 			printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
 #endif
 			disk_rw_in_progress = 0;
 			PS2_DISK_LED_OFF();
-			cmd = ld(ihost_index)[ldn].cmd;
-			ld(ihost_index)[ldn].cmd = NULL;
+			cmd = ld(shpnt)[ldn].cmd;
+			ld(shpnt)[ldn].cmd = NULL;
 			if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
 				cmd->result = DID_NO_CONNECT << 16;
 			else
 				cmd->result = DID_ABORT << 16;
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			last_scsi_type(ihost_index)[ldn] = 0;
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			last_scsi_type(shpnt)[ldn] = 0;
 			if (cmd->scsi_done)
 				(cmd->scsi_done) (cmd);	/* should be the internal_done */
-			spin_unlock(dev->host_lock);
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
 		} else {
 			disk_rw_in_progress = 0;
 			PS2_DISK_LED_OFF();
-			reset_status(ihost_index) = IM_RESET_FINISHED_OK;
-			stat_result(ihost_index) = cmd_result;
-			last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-			spin_unlock(dev->host_lock);
+			reset_status(shpnt) = IM_RESET_FINISHED_OK;
+			stat_result(shpnt) = cmd_result;
+			last_scsi_command(shpnt)[ldn] = NO_SCSI;
+			spin_unlock_irqrestore(shpnt->host_lock, flags);
 			return IRQ_HANDLED;
 		}
 	}
-	last_scsi_command(ihost_index)[ldn] = NO_SCSI;
-	last_scsi_type(ihost_index)[ldn] = 0;
-	cmd = ld(ihost_index)[ldn].cmd;
-	ld(ihost_index)[ldn].cmd = NULL;
+	last_scsi_command(shpnt)[ldn] = NO_SCSI;
+	last_scsi_type(shpnt)[ldn] = 0;
+	cmd = ld(shpnt)[ldn].cmd;
+	ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_TIMEOUT
 	if (cmd) {
 		if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) {
+			spin_unlock_irqsave(shpnt->host_lock, flags);
 			printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun);
 			return IRQ_HANDLED;
 		}
@@ -674,15 +681,15 @@
 	/*if no command structure, just return, else clear cmd */
 	if (!cmd)
 	{
-		spin_unlock(dev->host_lock);
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 		return IRQ_HANDLED;
 	}
 
 #ifdef IM_DEBUG_INT
-	printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error);
+	printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error);
 #endif
 	/*if this is end of media read/write, may turn off PS/2 disk led */
-	if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) {
+	if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) {
 		/* only access this, if there was a valid device addressed */
 		if (--disk_rw_in_progress == 0)
 			PS2_DISK_LED_OFF();
@@ -693,8 +700,8 @@
 	 * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
 	 * ACA_ACTIVE as returning statusbyte information. (ML) */
 	if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
-		cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e);
-		IBM_DS(ihost_index).total_errors++;
+		cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e);
+		IBM_DS(shpnt).total_errors++;
 	} else
 		cmd->result = 0;
 	/* write device status into cmd->result, and call done function */
@@ -705,24 +712,25 @@
 		cmd->result |= DID_OK << 16;
 	if (cmd->scsi_done)
 		(cmd->scsi_done) (cmd);
-	spin_unlock(dev->host_lock);
+	spin_unlock_irqrestore(shpnt->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg)
+static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg,
+		      unsigned char attn_reg)
 {
 	unsigned long flags;
 	/* must wait for attention reg not busy */
 	while (1) {
-		spin_lock_irqsave(hosts[host_index]->host_lock, flags);
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		spin_lock_irqsave(shpnt->host_lock, flags);
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
-		spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
 	}
 	/* write registers and enable system interrupts */
-	outl(cmd_reg, IM_CMD_REG(host_index));
-	outb(attn_reg, IM_ATTN_REG(host_index));
-	spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+	outl(cmd_reg, IM_CMD_REG(shpnt));
+	outb(attn_reg, IM_ATTN_REG(shpnt));
+	spin_unlock_irqrestore(shpnt->host_lock, flags);
 }
 
 static void internal_done(Scsi_Cmnd * cmd)
@@ -732,34 +740,34 @@
 }
 
 /* SCSI-SCB-command for device_inquiry */
-static int device_inquiry(int host_index, int ldn)
+static int device_inquiry(struct Scsi_Host *shpnt, int ldn)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[ldn].scb);
-	tsb = &(ld(host_index)[ldn].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
-	ld(host_index)[ldn].tsb.dev_status = 0;	/* prepare statusblock */
+	scb = &(ld(shpnt)[ldn].scb);
+	tsb = &(ld(shpnt)[ldn].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+	ld(shpnt)[ldn].tsb.dev_status = 0;	/* prepare statusblock */
 	for (retr = 0; retr < 3; retr++) {
 		/* fill scb with inquiry command */
 		scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
 		scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
-		last_scsi_type(host_index)[ldn] = IM_SCB;
+		last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
 		scb->sys_buf_length = 255;	/* maximum bufferlength gives max info */
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/* issue scb to passed ldn, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		while (!got_interrupt(host_index))
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if command successful, break */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/*if all three retries failed, return "no device at this ldn" */
@@ -769,34 +777,34 @@
 		return 1;
 }
 
-static int read_capacity(int host_index, int ldn)
+static int read_capacity(struct Scsi_Host *shpnt, int ldn)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[ldn].scb);
-	tsb = &(ld(host_index)[ldn].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
-	ld(host_index)[ldn].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[ldn].scb);
+	tsb = &(ld(shpnt)[ldn].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+	ld(shpnt)[ldn].tsb.dev_status = 0;
 	for (retr = 0; retr < 3; retr++) {
 		/*fill scb with read capacity command */
 		scb->command = IM_READ_CAPACITY_CMD;
 		scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
-		last_scsi_type(host_index)[ldn] = IM_SCB;
+		last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
 		scb->sys_buf_length = 8;
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/*issue scb to passed ldn, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		while (!got_interrupt(host_index))
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if got capacity, get block length and return one device found */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/*if all three retries failed, return "no device at this ldn" */
@@ -806,39 +814,39 @@
 		return 1;
 }
 
-static int get_pos_info(int host_index)
+static int get_pos_info(struct Scsi_Host *shpnt)
 {
 	int retr;
 	struct im_scb *scb;
 	struct im_tsb *tsb;
 	unsigned char *buf;
 
-	scb = &(ld(host_index)[MAX_LOG_DEV].scb);
-	tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);
-	buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf));
-	ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[MAX_LOG_DEV].scb);
+	tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb);
+	buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+	ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0;
 	for (retr = 0; retr < 3; retr++) {
 		/*fill scb with get_pos_info command */
 		scb->command = IM_GET_POS_INFO_CMD;
 		scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB;
 		scb->sys_buf_adr = isa_virt_to_bus(buf);
-		if (special(host_index) == IBM_SCSI2_FW)
+		if (special(shpnt) == IBM_SCSI2_FW)
 			scb->sys_buf_length = 256;	/* get all info from F/W adapter */
 		else
 			scb->sys_buf_length = 18;	/* get exactly 18 bytes for other SCSI */
 		scb->tsb_adr = isa_virt_to_bus(tsb);
 		/*issue scb to ldn=15, and busy wait for interrupt */
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
 		
 		/* FIXME: timeout */
-		while (!got_interrupt(host_index))
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if got POS-stuff, get block length and return one device found */
-		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+		if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
 	/* if all three retries failed, return "no device at this ldn" */
@@ -851,14 +859,16 @@
 /* SCSI-immediate-command for assign. This functions maps/unmaps specific
  ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
  subsystem and for dynamical remapping od ldns. */
-static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation)
+static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
+			    unsigned int lun, unsigned int ldn,
+			    unsigned int operation)
 {
 	int retr;
 	unsigned long imm_cmd;
 
 	for (retr = 0; retr < 3; retr++) {
 		/* select mutation level of the SCSI-adapter */
-		switch (special(host_index)) {
+		switch (special(shpnt)) {
 		case IBM_SCSI2_FW:
 			imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD);
 			imm_cmd |= (unsigned long) ((lun & 7) << 24);
@@ -867,7 +877,7 @@
 			imm_cmd |= (unsigned long) ((ldn & 15) << 16);
 			break;
 		default:
-			imm_cmd = inl(IM_CMD_REG(host_index));
+			imm_cmd = inl(IM_CMD_REG(shpnt));
 			imm_cmd &= (unsigned long) (0xF8000000);	/* keep reserved bits */
 			imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD);
 			imm_cmd |= (unsigned long) ((lun & 7) << 24);
@@ -876,15 +886,15 @@
 			imm_cmd |= (unsigned long) ((ldn & 15) << 16);
 			break;
 		}
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
-		issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-		while (!got_interrupt(host_index))
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
+		issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+		while (!got_interrupt(shpnt))
 			barrier();
 
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retr >= 3)
@@ -893,7 +903,7 @@
 		return 1;
 }
 
-static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout)
+static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout)
 {
 	int retr;
 	unsigned long imm_cmd;
@@ -903,16 +913,16 @@
 		imm_cmd = IM_FEATURE_CTR_IMM_CMD;
 		imm_cmd |= (unsigned long) ((speed & 0x7) << 29);
 		imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16);
-		last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
-		last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
+		last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
+		last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
 		/* we need to run into command errors in order to probe for the
 		 * right speed! */
 		global_command_error_excuse = 1;
-		issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+		issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
 		
 		/* FIXME: timeout */
-		while (!got_interrupt(host_index))
+		while (!got_interrupt(shpnt))
 			barrier();
 		if (global_command_error_excuse == CMD_FAIL) {
 			global_command_error_excuse = 0;
@@ -920,7 +930,7 @@
 		} else
 			global_command_error_excuse = 0;
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retr >= 3)
@@ -930,35 +940,35 @@
 }
 
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(int host_index, unsigned int ldn)
+static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn)
 {
 	int retries;
 	int ticks;
 	unsigned long imm_command;
 
 	for (retries = 0; retries < 3; retries++) {
-		imm_command = inl(IM_CMD_REG(host_index));
+		imm_command = inl(IM_CMD_REG(shpnt));
 		imm_command &= (unsigned long) (0xFFFF0000);	/* keep reserved bits */
 		imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
-		last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
-		last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
-		got_interrupt(host_index) = 0;
-		reset_status(host_index) = IM_RESET_IN_PROGRESS;
-		issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
+		last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD;
+		last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+		got_interrupt(shpnt) = 0;
+		reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+		issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
 		ticks = IM_RESET_DELAY * HZ;
-		while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) {
+		while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) {
 			udelay((1 + 999 / HZ) * 1000);
 			barrier();
 		}
 		/* if reset did not complete, just complain */
 		if (!ticks) {
 			printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
-			reset_status(host_index) = IM_RESET_FINISHED_OK;
+			reset_status(shpnt) = IM_RESET_FINISHED_OK;
 			/* did not work, finish */
 			return 1;
 		}
 		/*if command successful, break */
-		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+		if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
 	if (retries >= 3)
@@ -1060,35 +1070,35 @@
 	return 0;
 }
 
-static int probe_bus_mode(int host_index)
+static int probe_bus_mode(struct Scsi_Host *shpnt)
 {
 	struct im_pos_info *info;
 	int num_bus = 0;
 	int ldn;
 
-	info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf));
-	if (get_pos_info(host_index)) {
+	info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+	if (get_pos_info(shpnt)) {
 		if (info->connector_size & 0xf000)
-			subsystem_connector_size(host_index) = 16;
+			subsystem_connector_size(shpnt) = 16;
 		else
-			subsystem_connector_size(host_index) = 32;
+			subsystem_connector_size(shpnt) = 32;
 		num_bus |= (info->pos_4b & 8) >> 3;
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) {
+			if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) {
 				if (!((info->cache_stat >> ldn) & 1))
-					ld(host_index)[ldn].cache_flag = 0;
+					ld(shpnt)[ldn].cache_flag = 0;
 			}
 			if (!((info->retry_stat >> ldn) & 1))
-				ld(host_index)[ldn].retry_flag = 0;
+				ld(shpnt)[ldn].retry_flag = 0;
 		}
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: SCSI-Cache bits: ");
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			printk("%d", ld(host_index)[ldn].cache_flag);
+			printk("%d", ld(shpnt)[ldn].cache_flag);
 		}
 		printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
 		for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-			printk("%d", ld(host_index)[ldn].retry_flag);
+			printk("%d", ld(shpnt)[ldn].retry_flag);
 		}
 		printk("\n");
 #endif
@@ -1097,7 +1107,7 @@
 }
 
 /* probing scsi devices */
-static void check_devices(int host_index, int adaptertype)
+static void check_devices(struct Scsi_Host *shpnt, int adaptertype)
 {
 	int id, lun, ldn, ticks;
 	int count_devices;	/* local counter for connected device */
@@ -1108,24 +1118,24 @@
 	/* assign default values to certain variables */
 	ticks = 0;
 	count_devices = 0;
-	IBM_DS(host_index).dyn_flag = 0;	/* normally no need for dynamical ldn management */
-	IBM_DS(host_index).total_errors = 0;	/* set errorcounter to 0 */
-	next_ldn(host_index) = 7;	/* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
+	IBM_DS(shpnt).dyn_flag = 0;	/* normally no need for dynamical ldn management */
+	IBM_DS(shpnt).total_errors = 0;	/* set errorcounter to 0 */
+	next_ldn(shpnt) = 7;	/* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
 
 	/* initialize the very important driver-informational arrays/structs */
-	memset(ld(host_index), 0, sizeof(ld(host_index)));
+	memset(ld(shpnt), 0, sizeof(ld(shpnt)));
 	for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
-		last_scsi_command(host_index)[ldn] = NO_SCSI;	/* emptify last SCSI-command storage */
-		last_scsi_type(host_index)[ldn] = 0;
-		ld(host_index)[ldn].cache_flag = 1;
-		ld(host_index)[ldn].retry_flag = 1;
+		last_scsi_command(shpnt)[ldn] = NO_SCSI;	/* emptify last SCSI-command storage */
+		last_scsi_type(shpnt)[ldn] = 0;
+		ld(shpnt)[ldn].cache_flag = 1;
+		ld(shpnt)[ldn].retry_flag = 1;
 	}
-	memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index)));	/* this is essential ! */
-	memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index)));	/* this is essential ! */
+	memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt)));	/* this is essential ! */
+	memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt)));	/* this is essential ! */
 	for (lun = 0; lun < 8; lun++) {
 		/* mark the adapter at its pun on all luns */
-		get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
-		get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV;	/* make sure, the subsystem
+		get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER;
+		get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV;	/* make sure, the subsystem
 											   ldn is active for all
 											   luns. */
 	}
@@ -1134,9 +1144,9 @@
 	/* monitor connected on model XX95. */
 
 	/* STEP 1: */
-	adapter_speed(host_index) = global_adapter_speed;
-	speedrun = adapter_speed(host_index);
-	while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) {
+	adapter_speed(shpnt) = global_adapter_speed;
+	speedrun = adapter_speed(shpnt);
+	while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) {
 		probe_display(1);
 		if (speedrun == 7)
 			panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
@@ -1144,30 +1154,30 @@
 		if (speedrun > 7)
 			speedrun = 7;
 	}
-	adapter_speed(host_index) = speedrun;
+	adapter_speed(shpnt) = speedrun;
 	/* Get detailed information about the current adapter, necessary for
 	 * device operations: */
-	num_bus = probe_bus_mode(host_index);
+	num_bus = probe_bus_mode(shpnt);
 
 	/* num_bus contains only valid data for the F/W adapter! */
 	if (adaptertype == IBM_SCSI2_FW) {	/* F/W SCSI adapter: */
 		/* F/W adapter PUN-space extension evaluation: */
 		if (num_bus) {
 			printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n");
-			subsystem_maxid(host_index) = 16;
+			subsystem_maxid(shpnt) = 16;
 		} else {
 			printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
-			subsystem_maxid(host_index) = 8;
+			subsystem_maxid(shpnt) = 8;
 		}
 		printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype));
 	} else			/* all other IBM SCSI adapters: */
 		printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype));
 
 	/* assign correct PUN device space */
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 
 #ifdef IM_DEBUG_PROBE
-	printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index);
+	printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt);
 	printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
 #else
 	printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New");
@@ -1177,7 +1187,7 @@
 #ifdef IM_DEBUG_PROBE
 		printk(".");
 #endif
-		immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);	/* remove ldn (wherever) */
+		immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);	/* remove ldn (wherever) */
 	}
 	lun = 0;		/* default lun is 0 */
 #ifndef IM_DEBUG_PROBE
@@ -1196,18 +1206,18 @@
 #ifdef IM_DEBUG_PROBE
 			printk(".");
 #endif
-			if (id != subsystem_pun(host_index)) {
+			if (id != subsystem_pun(shpnt)) {
 				/* if pun is not the adapter: */
 				/* set ldn=0 to pun,lun */
-				immediate_assign(host_index, id, lun, PROBE_LDN, SET_LDN);
-				if (device_inquiry(host_index, PROBE_LDN)) {	/* probe device */
-					get_scsi(host_index)[id][lun] = (unsigned char) (ld(host_index)[PROBE_LDN].buf[0]);
+				immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN);
+				if (device_inquiry(shpnt, PROBE_LDN)) {	/* probe device */
+					get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]);
 					/* entry, even for NO_LUN */
-					if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
+					if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
 						count_devices++;	/* a existing device is found */
 				}
 				/* remove ldn */
-				immediate_assign(host_index, id, lun, PROBE_LDN, REMOVE_LDN);
+				immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN);
 			}
 		}
 #ifndef IM_DEBUG_PROBE
@@ -1227,16 +1237,16 @@
 #ifdef IM_DEBUG_PROBE
 			printk(".");
 #endif
-			if (id != subsystem_pun(host_index)) {
-				if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) {
+			if (id != subsystem_pun(shpnt)) {
+				if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) {
 					/* Only map if accepted type. Always enter for
 					   lun == 0 to get no gaps into ldn-mapping for ldn<7. */
-					immediate_assign(host_index, id, lun, ldn, SET_LDN);
-					get_ldn(host_index)[id][lun] = ldn;	/* map ldn */
-					if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
+					immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+					get_ldn(shpnt)[id][lun] = ldn;	/* map ldn */
+					if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
 #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
 						printk("resetting device at ldn=%x ... ", ldn);
-						immediate_reset(host_index, ldn);
+						immediate_reset(shpnt, ldn);
 #endif
 						ldn++;
 					} else {
@@ -1244,15 +1254,15 @@
 						 * handle it or because it has problems */
 						if (lun > 0) {
 							/* remove mapping */
-							get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
-							immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);
+							get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+							immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);
 						} else
 							ldn++;
 					}
 				} else if (lun == 0) {
 					/* map lun == 0, even if no device exists */
-					immediate_assign(host_index, id, lun, ldn, SET_LDN);
-					get_ldn(host_index)[id][lun] = ldn;	/* map ldn */
+					immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+					get_ldn(shpnt)[id][lun] = ldn;	/* map ldn */
 					ldn++;
 				}
 			}
@@ -1262,14 +1272,14 @@
 	/* map remaining ldns to non-existing devices */
 	for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++)
 		for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
-			if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) {
+			if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) {
 				probe_display(1);
 				/* Map remaining ldns only to NON-existing pun,lun
 				   combinations to make sure an inquiry will fail.
 				   For MULTI_LUN, it is needed to avoid adapter autonome
 				   SCSI-remapping. */
-				immediate_assign(host_index, id, lun, ldn, SET_LDN);
-				get_ldn(host_index)[id][lun] = ldn;
+				immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+				get_ldn(shpnt)[id][lun] = ldn;
 				ldn++;
 			}
 		}
@@ -1292,51 +1302,51 @@
 	for (id = 0; id < max_pun; id++) {
 		printk("%2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			printk("%2s ", ti_p(get_scsi(host_index)[id][lun]));
+			printk("%2s ", ti_p(get_scsi(shpnt)[id][lun]));
 		printk("      %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			printk("%2s ", ti_l(get_ldn(host_index)[id][lun]));
+			printk("%2s ", ti_l(get_ldn(shpnt)[id][lun]));
 		printk("\n");
 	}
 #endif
 
 	/* assign total number of found SCSI-devices to the statistics struct */
-	IBM_DS(host_index).total_scsi_devices = count_devices;
+	IBM_DS(shpnt).total_scsi_devices = count_devices;
 
 	/* decide for output in /proc-filesystem, if the configuration of
 	   SCSI-devices makes dynamical reassignment of devices necessary */
 	if (count_devices >= MAX_LOG_DEV)
-		IBM_DS(host_index).dyn_flag = 1;	/* dynamical assignment is necessary */
+		IBM_DS(shpnt).dyn_flag = 1;	/* dynamical assignment is necessary */
 	else
-		IBM_DS(host_index).dyn_flag = 0;	/* dynamical assignment is not necessary */
+		IBM_DS(shpnt).dyn_flag = 0;	/* dynamical assignment is not necessary */
 
 	/* If no SCSI-devices are assigned, return 1 in order to cause message. */
 	if (ldn == 0)
 		printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
 
 	/* reset the counters for statistics on the current adapter */
-	IBM_DS(host_index).scbs = 0;
-	IBM_DS(host_index).long_scbs = 0;
-	IBM_DS(host_index).total_accesses = 0;
-	IBM_DS(host_index).total_interrupts = 0;
-	IBM_DS(host_index).dynamical_assignments = 0;
-	memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access));
-	memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access));
-	memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access));
-	memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access));
-	memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access));
-	memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments));
+	IBM_DS(shpnt).scbs = 0;
+	IBM_DS(shpnt).long_scbs = 0;
+	IBM_DS(shpnt).total_accesses = 0;
+	IBM_DS(shpnt).total_interrupts = 0;
+	IBM_DS(shpnt).dynamical_assignments = 0;
+	memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access));
+	memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access));
+	memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access));
+	memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access));
+	memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access));
+	memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments));
 	probe_display(0);
 	return;
 }
 
-static int device_exists(int host_index, int ldn, int *block_length, int *device_type)
+static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type)
 {
 	unsigned char *buf;
 	/* if no valid device found, return immediately with 0 */
-	if (!(device_inquiry(host_index, ldn)))
+	if (!(device_inquiry(shpnt, ldn)))
 		return 0;
-	buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
+	buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
 	if (*buf == TYPE_ROM) {
 		*device_type = TYPE_ROM;
 		*block_length = 2048;	/* (standard blocksize for yellow-/red-book) */
@@ -1349,7 +1359,7 @@
 	}
 	if (*buf == TYPE_DISK) {
 		*device_type = TYPE_DISK;
-		if (read_capacity(host_index, ldn)) {
+		if (read_capacity(shpnt, ldn)) {
 			*block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
 			return 1;
 		} else
@@ -1357,7 +1367,7 @@
 	}
 	if (*buf == TYPE_MOD) {
 		*device_type = TYPE_MOD;
-		if (read_capacity(host_index, ldn)) {
+		if (read_capacity(shpnt, ldn)) {
 			*block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
 			return 1;
 		} else
@@ -1430,6 +1440,9 @@
 	return;
 }
 
+#if 0
+ FIXME NEED TO MOVE TO SYSFS
+
 static int ibmmca_getinfo(char *buf, int slot, void *dev_id)
 {
 	struct Scsi_Host *shpnt;
@@ -1480,58 +1493,34 @@
 
 	return len;
 }
+#endif
 
-int ibmmca_detect(struct scsi_host_template * scsi_template)
+static struct scsi_host_template ibmmca_driver_template = {
+          .proc_name      = "ibmmca",
+	  .proc_info	  = ibmmca_proc_info,
+          .name           = "IBM SCSI-Subsystem",
+          .queuecommand   = ibmmca_queuecommand,
+	  .eh_abort_handler = ibmmca_abort,
+	  .eh_host_reset_handler = ibmmca_host_reset,
+          .bios_param     = ibmmca_biosparam,
+          .can_queue      = 16,
+          .this_id        = 7,
+          .sg_tablesize   = 16,
+          .cmd_per_lun    = 1,
+          .use_clustering = ENABLE_CLUSTERING,
+};
+
+static int ibmmca_probe(struct device *dev)
 {
 	struct Scsi_Host *shpnt;
-	int port, id, i, j, k, slot;
-	int devices_on_irq_11 = 0;
-	int devices_on_irq_14 = 0;
-	int IRQ14_registered = 0;
-	int IRQ11_registered = 0;
-
-	found = 0;		/* make absolutely sure, that found is set to 0 */
+	int port, id, i, j, k, irq, enabled, ret = -EINVAL;
+	struct mca_device *mca_dev = to_mca_device(dev);
+	const char *description = ibmmca_description[mca_dev->index];
 
 	/* First of all, print the version number of the driver. This is
 	 * important to allow better user bugreports in case of already
 	 * having problems with the MCA_bus probing. */
 	printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION);
-	/* if this is not MCA machine, return "nothing found" */
-	if (!MCA_bus) {
-		printk(KERN_INFO "IBM MCA SCSI:  No Microchannel-bus present --> Aborting.\n" "      	     This machine does not have any IBM MCA-bus\n" "    	     or the MCA-Kernel-support is not enabled!\n");
-		return 0;
-	}
-
-#ifdef MODULE
-	/* If the driver is run as module, read from conf.modules or cmd-line */
-	if (boot_options)
-		option_setup(boot_options);
-#endif
-
-	/* get interrupt request level */
-	if (request_irq(IM_IRQ, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
-		printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
-		return 0;
-	} else
-		IRQ14_registered++;
-
-	/* if ibmmcascsi setup option was passed to kernel, return "found" */
-	for (i = 0; i < IM_MAX_HOSTS; i++)
-		if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) {
-			printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]);
-			if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) {
-				for (k = 2; k < 7; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0;
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION;
-				mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
-				mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(MCA_INTEGSCSI);
-				devices_on_irq_14++;
-			}
-		}
-	if (found)
-		return found;
-
 	/* The POS2-register of all PS/2 model SCSI-subsystems has the following
 	 * interpretation of bits:
 	 *                             Bit 7 - 4 : Chip Revision ID (Release)
@@ -1558,7 +1547,14 @@
 
 	/* first look for the IBM SCSI integrated subsystem on the motherboard */
 	for (j = 0; j < 8; j++)	/* read the pos-information */
-		pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j);
+		pos[j] = mca_device_read_pos(mca_dev, j);
+	id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
+	enabled = (pos[2] &0x01);
+	if (!enabled) {
+		printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+		printk(KERN_WARNING "              SCSI-operations may not work.\n");
+	}
+
 	/* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but
 	 * if we ignore the settings of all surrounding pos registers, it is not
 	 * completely sufficient to only check pos2 and pos3. */
@@ -1566,232 +1562,137 @@
 	 * make sure, we see a real integrated onboard SCSI-interface and no
 	 * internal system information, which gets mapped to some pos registers
 	 * on models 95xx. */
-	if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) {
-		if ((pos[2] & 1) == 1)	/* is the subsystem chip enabled ? */
-			port = IM_IO_PORT;
-		else {		/* if disabled, no IRQs will be generated, as the chip won't
-				 * listen to the incoming commands and will do really nothing,
-				 * except for listening to the pos-register settings. If this
-				 * happens, I need to hugely think about it, as one has to
-				 * write something to the MCA-Bus pos register in order to
-				 * enable the chip. Normally, IBM-SCSI won't pass the POST,
-				 * when the chip is disabled (see IBM tech. ref.). */
-			port = IM_IO_PORT;	/* anyway, set the portnumber and warn */
-			printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" "              SCSI-operations may not work.\n");
+	if (mca_dev->slot == MCA_INTEGSCSI &&
+	    ((!pos[0] && !pos[1] && pos[2] > 0 &&
+	      pos[3] > 0 && !pos[4] && !pos[5] &&
+	      !pos[6] && !pos[7]) ||
+	     (pos[0] == 0xff && pos[1] == 0xff &&
+	      pos[2] < 0xff && pos[3] < 0xff &&
+	      pos[4] == 0xff && pos[5] == 0xff &&
+	      pos[6] == 0xff && pos[7] == 0xff))) {
+		irq = IM_IRQ;
+		port = IM_IO_PORT;
+	} else {
+		irq = IM_IRQ;
+		port = IM_IO_PORT + ((pos[2] &0x0e) << 2);
+		if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) {
+			printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
+			printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
+			printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
+			id = 7;
+		} else {
+			id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
+			if (mca_dev->index == IBM_SCSI2_FW) {
+				id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
+								 * for F/W adapters */
+			}
 		}
-		id = (pos[3] & 0xe0) >> 5;	/* this is correct and represents the PUN */
-		/* give detailed information on the subsystem. This helps me
-		 * additionally during debugging and analyzing bug-reports. */
-		printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id);
+		if ((mca_dev->index == IBM_SCSI2_FW) &&
+		    (pos[4] & 0x01) && (pos[6] == 0)) {
+			/* IRQ11 is used by SCSI-2 F/W Adapter/A */
+			printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
+			irq = IM_IRQ_FW;
+		}
+	}
+
+
+
+	/* give detailed information on the subsystem. This helps me
+	 * additionally during debugging and analyzing bug-reports. */
+	printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n",
+	       description, port, id);
+	if (mca_dev->slot == MCA_INTEGSCSI)
 		printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
+	else {
+		if ((pos[2] & 0xf0) == 0xf0)
+			printk(KERN_DEBUG "              ROM Addr.=off,");
+		else
+			printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
 
-		/* register the found integrated SCSI-subsystem */
-		if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) 
-		{
-			for (k = 2; k < 7; k++)
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-			((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
-			mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
-			mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-			mca_mark_as_used(MCA_INTEGSCSI);
-			devices_on_irq_14++;
-		}
+		printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
 	}
 
-	/* now look for other adapters in MCA slots, */
-	/* determine the number of known IBM-SCSI-subsystem types */
-	/* see the pos[2] dependence to get the adapter port-offset. */
-	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
-		/* scan each slot for a fitting adapter id */
-		slot = 0;	/* start at slot 0 */
-		while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
-		       != MCA_NOTFOUND) {	/* scan through all slots */
-			for (j = 0; j < 8; j++)	/* read the pos-information */
-				pos[j] = mca_read_stored_pos(slot, j);
-			if ((pos[2] & 1) == 1)
-				/* is the subsystem chip enabled ? */
-				/* (explanations see above) */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-			else {
-				/* anyway, set the portnumber and warn */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-				printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
-				printk(KERN_WARNING "              SCSI-operations may not work.\n");
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
-				printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
-				printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
-				printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
-				id = 7;
-			} else {
-				id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
-				if (i == IBM_SCSI2_FW) {
-					id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
-									 * for F/W adapters */
-				}
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
-				/* IRQ11 is used by SCSI-2 F/W Adapter/A */
-				printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
-				/* get interrupt request level */
-				if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
-					printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
-				} else
-					IRQ11_registered++;
-			}
-			printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
-			if ((pos[2] & 0xf0) == 0xf0)
-				printk(KERN_DEBUG"              ROM Addr.=off,");
-			else
-				printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
-			printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
-
-			/* register the hostadapter */
-			if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
-				for (k = 2; k < 8; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
-				mca_set_adapter_name(slot, subsys_list[i].description);
-				mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(slot);
-				if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
-					devices_on_irq_11++;
-				else
-					devices_on_irq_14++;
-			}
-			slot++;	/* advance to next slot */
-		}		/* advance to next adapter id in the list of IBM-SCSI-subsystems */
-	}
-
-	/* now check for SCSI-adapters, mapped to the integrated SCSI
-	 * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here,
-	 * as this is a known effect on some models 95xx. */
-	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
-		/* scan each slot for a fitting adapter id */
-		slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
-		if (slot != MCA_NOTFOUND) {	/* scan through all slots */
-			for (j = 0; j < 8; j++)	/* read the pos-information */
-				pos[j] = mca_read_stored_pos(slot, j);
-			if ((pos[2] & 1) == 1) {	/* is the subsystem chip enabled ? */
-				/* (explanations see above) */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-			} else {	/* anyway, set the portnumber and warn */
-				port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
-				printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
-				printk(KERN_WARNING "              SCSI-operations may not work.\n");
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
-				printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
-				printk(KERN_ERR  "              Impossible to determine adapter PUN!\n");
-				printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
-				id = 7;
-			} else {
-				id = (pos[3] & 0xe0) >> 5;	/* get subsystem PUN */
-				if (i == IBM_SCSI2_FW)
-					id |= (pos[3] & 0x10) >> 1;	/* get subsystem PUN high-bit
-									 * for F/W adapters */
-			}
-			if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
-				/* IRQ11 is used by SCSI-2 F/W Adapter/A */
-				printk(KERN_DEBUG  "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
-				/* get interrupt request level */
-				if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts))
-					printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
-				else
-					IRQ11_registered++;
-			}
-			printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
-			if ((pos[2] & 0xf0) == 0xf0)
-				printk(KERN_DEBUG "              ROM Addr.=off,");
-			else
-				printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
-			printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
-
-			/* register the hostadapter */
-			if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
-				for (k = 2; k < 7; k++)
-					((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-				((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
-				mca_set_adapter_name(slot, subsys_list[i].description);
-				mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-				mca_mark_as_used(slot);
-				if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
-					devices_on_irq_11++;
-				else
-					devices_on_irq_14++;
-			}
-			slot++;	/* advance to next slot */
-		}		/* advance to next adapter id in the list of IBM-SCSI-subsystems */
-	}
-	if (IRQ11_registered && !devices_on_irq_11)
-		free_irq(IM_IRQ_FW, hosts);	/* no devices on IRQ 11 */
-	if (IRQ14_registered && !devices_on_irq_14)
-		free_irq(IM_IRQ, hosts);	/* no devices on IRQ 14 */
-	if (!devices_on_irq_11 && !devices_on_irq_14)
-		printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
-	return found;		/* return the number of found SCSI hosts. Should be 1 or 0. */
-}
-
-static struct Scsi_Host *ibmmca_register(struct scsi_host_template * scsi_template, int port, int id, int adaptertype, char *hostname)
-{
-	struct Scsi_Host *shpnt;
-	int i, j;
-	unsigned int ctrl;
-
 	/* check I/O region */
-	if (!request_region(port, IM_N_IO_PORT, hostname)) {
+	if (!request_region(port, IM_N_IO_PORT, description)) {
 		printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
-		return NULL;
+		goto out_fail;
 	}
 
 	/* register host */
-	shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
+	shpnt = scsi_host_alloc(&ibmmca_driver_template,
+				sizeof(struct ibmmca_hostdata));
 	if (!shpnt) {
 		printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n");
-		release_region(port, IM_N_IO_PORT);
-		return NULL;
+		goto out_release;
+	}
+
+	dev_set_drvdata(dev, shpnt);
+	if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) {
+		printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq);
+		goto out_free_host;
 	}
 
 	/* request I/O region */
-	hosts[found] = shpnt;	/* add new found hostadapter to the list */
-	special(found) = adaptertype;	/* important assignment or else crash! */
-	subsystem_connector_size(found) = 0;	/* preset slot-size */
-	shpnt->irq = IM_IRQ;	/* assign necessary stuff for the adapter */
+	special(shpnt) = mca_dev->index;	/* important assignment or else crash! */
+	subsystem_connector_size(shpnt) = 0;	/* preset slot-size */
+	shpnt->irq = irq;	/* assign necessary stuff for the adapter */
 	shpnt->io_port = port;
 	shpnt->n_io_port = IM_N_IO_PORT;
 	shpnt->this_id = id;
 	shpnt->max_id = 8;	/* 8 PUNs are default */
 	/* now, the SCSI-subsystem is connected to Linux */
 
-	ctrl = (unsigned int) (inb(IM_CTR_REG(found)));	/* get control-register status */
 #ifdef IM_DEBUG_PROBE
+	ctrl = (unsigned int) (inb(IM_CTR_REG(found)));	/* get control-register status */
 	printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found)));
 	printk("IBM MCA SCSI: This adapters' POS-registers: ");
 	for (i = 0; i < 8; i++)
 		printk("%x ", pos[i]);
 	printk("\n");
 #endif
-	reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
+	reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
 
 	for (i = 0; i < 16; i++)	/* reset the tables */
 		for (j = 0; j < 8; j++)
-			get_ldn(found)[i][j] = MAX_LOG_DEV;
+			get_ldn(shpnt)[i][j] = MAX_LOG_DEV;
 
 	/* check which logical devices exist */
 	/* after this line, local interrupting is possible: */
-	local_checking_phase_flag(found) = 1;
-	check_devices(found, adaptertype);	/* call by value, using the global variable hosts */
-	local_checking_phase_flag(found) = 0;
-	found++;		/* now increase index to be prepared for next found subsystem */
+	local_checking_phase_flag(shpnt) = 1;
+	check_devices(shpnt, mca_dev->index);	/* call by value, using the global variable hosts */
+	local_checking_phase_flag(shpnt) = 0;
+
 	/* an ibm mca subsystem has been detected */
-	return shpnt;
+
+	for (k = 2; k < 7; k++)
+		((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
+	((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
+	mca_device_set_name(mca_dev, description);
+	/* FIXME: NEED TO REPLUMB TO SYSFS
+	   mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
+	*/
+	mca_device_set_claim(mca_dev, 1);
+	if (scsi_add_host(shpnt, dev)) {
+		dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n");
+		goto out_free_host;
+	}
+	scsi_scan_host(shpnt);
+
+	return 0;
+ out_free_host:
+	scsi_host_put(shpnt);
+ out_release:
+	release_region(port, IM_N_IO_PORT);
+ out_fail:
+	return ret;
 }
 
-static int ibmmca_release(struct Scsi_Host *shpnt)
+static int __devexit ibmmca_remove(struct device *dev)
 {
+	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
+	scsi_remove_host(shpnt);
 	release_region(shpnt->io_port, shpnt->n_io_port);
-	if (!(--found))
-		free_irq(shpnt->irq, hosts);
+	free_irq(shpnt->irq, dev);
 	return 0;
 }
 
@@ -1805,33 +1706,24 @@
 	int current_ldn;
 	int id, lun;
 	int target;
-	int host_index;
 	int max_pun;
 	int i;
-	struct scatterlist *sl;
+	struct scatterlist *sg;
 
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index]) {	/* invalid hostadapter descriptor address */
-		cmd->result = DID_NO_CONNECT << 16;
-		if (done)
-			done(cmd);
-		return 0;
-	}
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 	if (ibm_ansi_order) {
 		target = max_pun - 1 - cmd->device->id;
-		if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+		if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
 			target--;
-		else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+		else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
 			target++;
 	} else
 		target = cmd->device->id;
 
 	/* if (target,lun) is NO LUN or not existing at all, return error */
-	if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
+	if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
 		cmd->result = DID_NO_CONNECT << 16;
 		if (done)
 			done(cmd);
@@ -1839,16 +1731,16 @@
 	}
 
 	/*if (target,lun) unassigned, do further checks... */
-	ldn = get_ldn(host_index)[target][cmd->device->lun];
+	ldn = get_ldn(shpnt)[target][cmd->device->lun];
 	if (ldn >= MAX_LOG_DEV) {	/* on invalid ldn do special stuff */
 		if (ldn > MAX_LOG_DEV) {	/* dynamical remapping if ldn unassigned */
-			current_ldn = next_ldn(host_index);	/* stop-value for one circle */
-			while (ld(host_index)[next_ldn(host_index)].cmd) {	/* search for a occupied, but not in */
+			current_ldn = next_ldn(shpnt);	/* stop-value for one circle */
+			while (ld(shpnt)[next_ldn(shpnt)].cmd) {	/* search for a occupied, but not in */
 				/* command-processing ldn. */
-				next_ldn(host_index)++;
-				if (next_ldn(host_index) >= MAX_LOG_DEV)
-					next_ldn(host_index) = 7;
-				if (current_ldn == next_ldn(host_index)) {	/* One circle done ? */
+				next_ldn(shpnt)++;
+				if (next_ldn(shpnt) >= MAX_LOG_DEV)
+					next_ldn(shpnt) = 7;
+				if (current_ldn == next_ldn(shpnt)) {	/* One circle done ? */
 					/* no non-processing ldn found */
 					scmd_printk(KERN_WARNING, cmd,
 	"IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
@@ -1864,56 +1756,56 @@
 			/* unmap non-processing ldn */
 			for (id = 0; id < max_pun; id++)
 				for (lun = 0; lun < 8; lun++) {
-					if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) {
-						get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
-						get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE;
+					if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) {
+						get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+						get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE;
 						/* unmap entry */
 					}
 				}
 			/* set reduced interrupt_handler-mode for checking */
-			local_checking_phase_flag(host_index) = 1;
+			local_checking_phase_flag(shpnt) = 1;
 			/* map found ldn to pun,lun */
-			get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index);
+			get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt);
 			/* change ldn to the right value, that is now next_ldn */
-			ldn = next_ldn(host_index);
+			ldn = next_ldn(shpnt);
 			/* unassign all ldns (pun,lun,ldn does not matter for remove) */
-			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+			immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
 			/* set only LDN for remapped device */
-			immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN);
+			immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN);
 			/* get device information for ld[ldn] */
-			if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
-				ld(host_index)[ldn].cmd = NULL;	/* To prevent panic set 0, because
+			if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
+				ld(shpnt)[ldn].cmd = NULL;	/* To prevent panic set 0, because
 								   devices that were not assigned,
 								   should have nothing in progress. */
-				get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type;
+				get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type;
 				/* increase assignment counters for statistics in /proc */
-				IBM_DS(host_index).dynamical_assignments++;
-				IBM_DS(host_index).ldn_assignments[ldn]++;
+				IBM_DS(shpnt).dynamical_assignments++;
+				IBM_DS(shpnt).ldn_assignments[ldn]++;
 			} else
 				/* panic here, because a device, found at boottime has
 				   vanished */
 				panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);
 			/* unassign again all ldns (pun,lun,ldn does not matter for remove) */
-			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+			immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
 			/* remap all ldns, as written in the pun/lun table */
 			lun = 0;
 #ifdef CONFIG_SCSI_MULTI_LUN
 			for (lun = 0; lun < 8; lun++)
 #endif
 				for (id = 0; id < max_pun; id++) {
-					if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV)
-						immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN);
+					if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV)
+						immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN);
 				}
 			/* set back to normal interrupt_handling */
-			local_checking_phase_flag(host_index) = 0;
+			local_checking_phase_flag(shpnt) = 0;
 #ifdef IM_DEBUG_PROBE
 			/* Information on syslog terminal */
 			printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);
 #endif
 			/* increase next_ldn for next dynamical assignment */
-			next_ldn(host_index)++;
-			if (next_ldn(host_index) >= MAX_LOG_DEV)
-				next_ldn(host_index) = 7;
+			next_ldn(shpnt)++;
+			if (next_ldn(shpnt) >= MAX_LOG_DEV)
+				next_ldn(shpnt) = 7;
 		} else {	/* wall against Linux accesses to the subsystem adapter */
 			cmd->result = DID_BAD_TARGET << 16;
 			if (done)
@@ -1923,34 +1815,32 @@
 	}
 
 	/*verify there is no command already in progress for this log dev */
-	if (ld(host_index)[ldn].cmd)
+	if (ld(shpnt)[ldn].cmd)
 		panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");
 
 	/*save done in cmd, and save cmd for the interrupt handler */
 	cmd->scsi_done = done;
-	ld(host_index)[ldn].cmd = cmd;
+	ld(shpnt)[ldn].cmd = cmd;
 
 	/*fill scb information independent of the scsi command */
-	scb = &(ld(host_index)[ldn].scb);
-	ld(host_index)[ldn].tsb.dev_status = 0;
+	scb = &(ld(shpnt)[ldn].scb);
+	ld(shpnt)[ldn].tsb.dev_status = 0;
 	scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
-	scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
+	scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb));
 	scsi_cmd = cmd->cmnd[0];
 
-	if (cmd->use_sg) {
-		i = cmd->use_sg;
-		sl = (struct scatterlist *) (cmd->request_buffer);
-		if (i > 16)
-			panic("IBM MCA SCSI: scatter-gather list too long.\n");
-		while (--i >= 0) {
-			ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset);
-			ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
+	if (scsi_sg_count(cmd)) {
+		BUG_ON(scsi_sg_count(cmd) > 16);
+
+		scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
+			ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset);
+			ld(shpnt)[ldn].sge[i].byte_length = sg->length;
 		}
 		scb->enable |= IM_POINTER_TO_LIST;
-		scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
-		scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge);
+		scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0]));
+		scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge);
 	} else {
-		scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
+ 		scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd));
 		/* recent Linux midlevel SCSI places 1024 byte for inquiry
 		 * command. Far too much for old PS/2 hardware. */
 		switch (scsi_cmd) {
@@ -1961,16 +1851,16 @@
 		case REQUEST_SENSE:
 		case MODE_SENSE:
 		case MODE_SELECT:
-			if (cmd->request_bufflen > 255)
+			if (scsi_bufflen(cmd) > 255)
 				scb->sys_buf_length = 255;
 			else
-				scb->sys_buf_length = cmd->request_bufflen;
+				scb->sys_buf_length = scsi_bufflen(cmd);
 			break;
 		case TEST_UNIT_READY:
 			scb->sys_buf_length = 0;
 			break;
 		default:
-			scb->sys_buf_length = cmd->request_bufflen;
+			scb->sys_buf_length = scsi_bufflen(cmd);
 			break;
 		}
 	}
@@ -1982,16 +1872,16 @@
 
 	/* for specific device-type debugging: */
 #ifdef IM_DEBUG_CMD_SPEC_DEV
-	if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
-		printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn);
+	if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
+		printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn);
 #endif
 
 	/* for possible panics store current command */
-	last_scsi_command(host_index)[ldn] = scsi_cmd;
-	last_scsi_type(host_index)[ldn] = IM_SCB;
+	last_scsi_command(shpnt)[ldn] = scsi_cmd;
+	last_scsi_type(shpnt)[ldn] = IM_SCB;
 	/* update statistical info */
-	IBM_DS(host_index).total_accesses++;
-	IBM_DS(host_index).ldn_access[ldn]++;
+	IBM_DS(shpnt).total_accesses++;
+	IBM_DS(shpnt).ldn_access[ldn]++;
 
 	switch (scsi_cmd) {
 	case READ_6:
@@ -2003,17 +1893,17 @@
 		/* Distinguish between disk and other devices. Only disks (that are the
 		   most frequently accessed devices) should be supported by the
 		   IBM-SCSI-Subsystem commands. */
-		switch (ld(host_index)[ldn].device_type) {
+		switch (ld(shpnt)[ldn].device_type) {
 		case TYPE_DISK:	/* for harddisks enter here ... */
 		case TYPE_MOD:	/* ... try it also for MO-drives (send flames as */
 			/*     you like, if this won't work.) */
 			if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {
 				/* read command preparations */
 				scb->enable |= IM_READ_CONTROL;
-				IBM_DS(host_index).ldn_read_access[ldn]++;	/* increase READ-access on ldn stat. */
+				IBM_DS(shpnt).ldn_read_access[ldn]++;	/* increase READ-access on ldn stat. */
 				scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
 			} else {	/* write command preparations */
-				IBM_DS(host_index).ldn_write_access[ldn]++;	/* increase write-count on ldn stat. */
+				IBM_DS(shpnt).ldn_write_access[ldn]++;	/* increase write-count on ldn stat. */
 				scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
 			}
 			if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {
@@ -2023,9 +1913,9 @@
 				scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);
 				scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);
 			}
-			last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;
-			last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;
-			scb->u2.blk.length = ld(host_index)[ldn].block_length;
+			last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr;
+			last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count;
+			scb->u2.blk.length = ld(shpnt)[ldn].block_length;
 			break;
 			/* for other devices, enter here. Other types are not known by
 			   Linux! TYPE_NO_LUN is forbidden as valid device. */
@@ -2046,14 +1936,14 @@
 			scb->enable |= IM_BYPASS_BUFFER;
 			scb->u1.scsi_cmd_length = cmd->cmd_len;
 			memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-			last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+			last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 			/* Read/write on this non-disk devices is also displayworthy,
 			   so flash-up the LED/display. */
 			break;
 		}
 		break;
 	case INQUIRY:
-		IBM_DS(host_index).ldn_inquiry_access[ldn]++;
+		IBM_DS(shpnt).ldn_inquiry_access[ldn]++;
 		scb->command = IM_DEVICE_INQUIRY_CMD;
 		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
 		scb->u1.log_blk_adr = 0;
@@ -2064,7 +1954,7 @@
 		scb->u1.log_blk_adr = 0;
 		scb->u1.scsi_cmd_length = 6;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, 6);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 	case READ_CAPACITY:
 		/* the length of system memory buffer must be exactly 8 bytes */
@@ -2081,12 +1971,12 @@
 		/* Commands that need write-only-mode (system -> device): */
 	case MODE_SELECT:
 	case MODE_SELECT_10:
-		IBM_DS(host_index).ldn_modeselect_access[ldn]++;
+		IBM_DS(shpnt).ldn_modeselect_access[ldn]++;
 		scb->command = IM_OTHER_SCSI_CMD_CMD;
 		scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;	/*Select needs WRITE-enabled */
 		scb->u1.scsi_cmd_length = cmd->cmd_len;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 		/* For other commands, read-only is useful. Most other commands are
 		   running without an input-data-block. */
@@ -2095,19 +1985,19 @@
 		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
 		scb->u1.scsi_cmd_length = cmd->cmd_len;
 		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+		last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
 		break;
 	}
 	/*issue scb command, and return */
 	if (++disk_rw_in_progress == 1)
 		PS2_DISK_LED_ON(shpnt->host_no, target);
 
-	if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
-		IBM_DS(host_index).long_scbs++;
+	if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) {
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
+		IBM_DS(shpnt).long_scbs++;
 	} else {
-		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
-		IBM_DS(host_index).scbs++;
+		issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+		IBM_DS(shpnt).scbs++;
 	}
 	return 0;
 }
@@ -2122,7 +2012,6 @@
 	unsigned int ldn;
 	void (*saved_done) (Scsi_Cmnd *);
 	int target;
-	int host_index;
 	int max_pun;
 	unsigned long imm_command;
 
@@ -2131,35 +2020,23 @@
 #endif
 
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index]) {	/* invalid hostadapter descriptor address */
-		cmd->result = DID_NO_CONNECT << 16;
-		if (cmd->scsi_done)
-			(cmd->scsi_done) (cmd);
-		shpnt = cmd->device->host;
-#ifdef IM_DEBUG_PROBE
-		printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n");
-#endif
-		return SUCCESS;
-	}
-	max_pun = subsystem_maxid(host_index);
+	max_pun = subsystem_maxid(shpnt);
 	if (ibm_ansi_order) {
 		target = max_pun - 1 - cmd->device->id;
-		if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+		if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
 			target--;
-		else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+		else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
 			target++;
 	} else
 		target = cmd->device->id;
 
 	/* get logical device number, and disable system interrupts */
 	printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun);
-	ldn = get_ldn(host_index)[target][cmd->device->lun];
+	ldn = get_ldn(shpnt)[target][cmd->device->lun];
 
 	/*if cmd for this ldn has already finished, no need to abort */
-	if (!ld(host_index)[ldn].cmd) {
+	if (!ld(shpnt)[ldn].cmd) {
 		    return SUCCESS;
 	}
 
@@ -2170,20 +2047,20 @@
 	saved_done = cmd->scsi_done;
 	cmd->scsi_done = internal_done;
 	cmd->SCp.Status = 0;
-	last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;
-	last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
-	imm_command = inl(IM_CMD_REG(host_index));
+	last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD;
+	last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+	imm_command = inl(IM_CMD_REG(shpnt));
 	imm_command &= (unsigned long) (0xffff0000);	/* mask reserved stuff */
 	imm_command |= (unsigned long) (IM_ABORT_IMM_CMD);
 	/* must wait for attention reg not busy */
 	/* FIXME - timeout, politeness */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 	}
 	/* write registers and enable system interrupts */
-	outl(imm_command, IM_CMD_REG(host_index));
-	outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+	outl(imm_command, IM_CMD_REG(shpnt));
+	outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt));
 #ifdef IM_DEBUG_PROBE
 	printk("IBM MCA SCSI: Abort queued to adapter...\n");
 #endif
@@ -2202,7 +2079,7 @@
 		cmd->result |= DID_ABORT << 16;
 		if (cmd->scsi_done)
 			(cmd->scsi_done) (cmd);
-		ld(host_index)[ldn].cmd = NULL;
+		ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: Abort finished with success.\n");
 #endif
@@ -2211,7 +2088,7 @@
 		cmd->result |= DID_NO_CONNECT << 16;
 		if (cmd->scsi_done)
 			(cmd->scsi_done) (cmd);
-		ld(host_index)[ldn].cmd = NULL;
+		ld(shpnt)[ldn].cmd = NULL;
 #ifdef IM_DEBUG_PROBE
 		printk("IBM MCA SCSI: Abort failed.\n");
 #endif
@@ -2236,71 +2113,65 @@
 	struct Scsi_Host *shpnt;
 	Scsi_Cmnd *cmd_aid;
 	int ticks, i;
-	int host_index;
 	unsigned long imm_command;
 
 	BUG_ON(cmd == NULL);
 
 	ticks = IM_RESET_DELAY * HZ;
 	shpnt = cmd->device->host;
-	/* search for the right hostadapter */
-	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
 
-	if (!hosts[host_index])	/* invalid hostadapter descriptor address */
-		return FAILED;
-
-	if (local_checking_phase_flag(host_index)) {
+	if (local_checking_phase_flag(shpnt)) {
 		printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n");
 		return FAILED;
 	}
 
 	/* issue reset immediate command to subsystem, and wait for interrupt */
 	printk("IBM MCA SCSI: resetting all devices.\n");
-	reset_status(host_index) = IM_RESET_IN_PROGRESS;
-	last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;
-	last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
-	imm_command = inl(IM_CMD_REG(host_index));
+	reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+	last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD;
+	last_scsi_type(shpnt)[0xf] = IM_IMM_CMD;
+	imm_command = inl(IM_CMD_REG(shpnt));
 	imm_command &= (unsigned long) (0xffff0000);	/* mask reserved stuff */
 	imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
 	/* must wait for attention reg not busy */
 	while (1) {
-		if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+		if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
 			break;
 		spin_unlock_irq(shpnt->host_lock);
 		yield();
 		spin_lock_irq(shpnt->host_lock);
 	}
 	/*write registers and enable system interrupts */
-	outl(imm_command, IM_CMD_REG(host_index));
-	outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
+	outl(imm_command, IM_CMD_REG(shpnt));
+	outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt));
 	/* wait for interrupt finished or intr_stat register to be set, as the
 	 * interrupt will not be executed, while we are in here! */
 	 
 	/* FIXME: This is really really icky we so want a sleeping version of this ! */
-	while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) {
+	while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) {
 		udelay((1 + 999 / HZ) * 1000);
 		barrier();
 	}
 	/* if reset did not complete, just return an error */
 	if (!ticks) {
 		printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
-		reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+		reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 		return FAILED;
 	}
 
-	if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) {
+	if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) {
 		/* analysis done by this routine and not by the intr-routine */
-		if (inb(IM_INTR_REG(host_index)) == 0xaf)
-			reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
-		else if (inb(IM_INTR_REG(host_index)) == 0xcf)
-			reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+		if (inb(IM_INTR_REG(shpnt)) == 0xaf)
+			reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT;
+		else if (inb(IM_INTR_REG(shpnt)) == 0xcf)
+			reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
 		else		/* failed, 4get it */
-			reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
-		outb(IM_EOI | 0xf, IM_ATTN_REG(host_index));
+			reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
+		outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt));
 	}
 
 	/* if reset failed, just return an error */
-	if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
+	if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) {
 		printk(KERN_ERR "IBM MCA SCSI: reset failed.\n");
 		return FAILED;
 	}
@@ -2308,9 +2179,9 @@
 	/* so reset finished ok - call outstanding done's, and return success */
 	printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n");
 	for (i = 0; i < MAX_LOG_DEV; i++) {
-		cmd_aid = ld(host_index)[i].cmd;
+		cmd_aid = ld(shpnt)[i].cmd;
 		if (cmd_aid && cmd_aid->scsi_done) {
-			ld(host_index)[i].cmd = NULL;
+			ld(shpnt)[i].cmd = NULL;
 			cmd_aid->result = DID_RESET << 16;
 		}
 	}
@@ -2351,46 +2222,46 @@
 }
 
 /* calculate percentage of total accesses on a ldn */
-static int ldn_access_load(int host_index, int ldn)
+static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
 {
-	if (IBM_DS(host_index).total_accesses == 0)
+	if (IBM_DS(shpnt).total_accesses == 0)
 		return (0);
-	if (IBM_DS(host_index).ldn_access[ldn] == 0)
+	if (IBM_DS(shpnt).ldn_access[ldn] == 0)
 		return (0);
-	return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
+	return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses;
 }
 
 /* calculate total amount of r/w-accesses */
-static int ldn_access_total_read_write(int host_index)
+static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i];
+		a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i];
 	return (a);
 }
 
-static int ldn_access_total_inquiry(int host_index)
+static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_inquiry_access[i];
+		a += IBM_DS(shpnt).ldn_inquiry_access[i];
 	return (a);
 }
 
-static int ldn_access_total_modeselect(int host_index)
+static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
 {
 	int a;
 	int i;
 
 	a = 0;
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		a += IBM_DS(host_index).ldn_modeselect_access[i];
+		a += IBM_DS(shpnt).ldn_modeselect_access[i];
 	return (a);
 }
 
@@ -2398,19 +2269,14 @@
 static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
 {
 	int len = 0;
-	int i, id, lun, host_index;
+	int i, id, lun;
 	unsigned long flags;
 	int max_pun;
 
-	for (i = 0; hosts[i] && hosts[i] != shpnt; i++);
 	
-	spin_lock_irqsave(hosts[i]->host_lock, flags);	/* Check it */
-	host_index = i;
-	if (!shpnt) {
-		len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
-		return len;
-	}
-	max_pun = subsystem_maxid(host_index);
+	spin_lock_irqsave(shpnt->host_lock, flags);	/* Check it */
+
+	max_pun = subsystem_maxid(shpnt);
 
 	len += sprintf(buffer + len, "\n             IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION);
 	len += sprintf(buffer + len, " SCSI Access-Statistics:\n");
@@ -2421,40 +2287,40 @@
 	len += sprintf(buffer + len, "               Multiple LUN probing.....: No\n");
 #endif
 	len += sprintf(buffer + len, "               This Hostnumber..........: %d\n", shpnt->host_no);
-	len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index)));
+	len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt)));
 	len += sprintf(buffer + len, "               (Shared) IRQ.............: %d\n", IM_IRQ);
-	len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts);
-	len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses);
-	len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(host_index).scbs);
-	len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs);
-	len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index));
-	len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
-		       - ldn_access_total_modeselect(host_index)
-		       - ldn_access_total_inquiry(host_index));
-	len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors);
+	len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts);
+	len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses);
+	len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs);
+	len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs);
+	len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt));
+	len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt)
+		       - ldn_access_total_modeselect(shpnt)
+		       - ldn_access_total_inquiry(shpnt));
+	len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors);
 	len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n");
 	len += sprintf(buffer + len, "         LDN | Accesses [%%] |   READ    |   WRITE   | ASSIGNMENTS\n");
 	len += sprintf(buffer + len, "        -----|--------------|-----------|-----------|--------------\n");
 	for (i = 0; i <= MAX_LOG_DEV; i++)
-		len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
+		len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]);
 	len += sprintf(buffer + len, "        -----------------------------------------------------------\n\n");
 	len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n");
-	len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices);
-	len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
-	len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index));
-	len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments);
+	len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices);
+	len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No ");
+	len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt));
+	len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments);
 	len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n");
 	len += sprintf(buffer + len, "        Physical SCSI-Device Map               Logical SCSI-Device Map\n");
 	len += sprintf(buffer + len, "    ID\\LUN  0  1  2  3  4  5  6  7       ID\\LUN  0  1  2  3  4  5  6  7\n");
 	for (id = 0; id < max_pun; id++) {
 		len += sprintf(buffer + len, "    %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun]));
+			len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun]));
 		len += sprintf(buffer + len, "      %2d     ", id);
 		for (lun = 0; lun < 8; lun++)
-			len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun]));
+			len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun]));
 		len += sprintf(buffer + len, "\n");
 	}
 
@@ -2488,20 +2354,31 @@
 
 __setup("ibmmcascsi=", option_setup);
 
-static struct scsi_host_template driver_template = {
-          .proc_name      = "ibmmca",
-	  .proc_info	  = ibmmca_proc_info,
-          .name           = "IBM SCSI-Subsystem",
-          .detect         = ibmmca_detect,
-          .release        = ibmmca_release,
-          .queuecommand   = ibmmca_queuecommand,
-	  .eh_abort_handler = ibmmca_abort,
-	  .eh_host_reset_handler = ibmmca_host_reset,
-          .bios_param     = ibmmca_biosparam,
-          .can_queue      = 16,
-          .this_id        = 7,
-          .sg_tablesize   = 16,
-          .cmd_per_lun    = 1,
-          .use_clustering = ENABLE_CLUSTERING,
+static struct mca_driver ibmmca_driver = {
+	.id_table = ibmmca_id_table,
+	.driver = {
+		.name	= "ibmmca",
+		.bus	= &mca_bus_type,
+		.probe	= ibmmca_probe,
+		.remove	= __devexit_p(ibmmca_remove),
+	},
 };
-#include "scsi_module.c"
+
+static int __init ibmmca_init(void)
+{
+#ifdef MODULE
+	/* If the driver is run as module, read from conf.modules or cmd-line */
+	if (boot_options)
+		option_setup(boot_options);
+#endif
+
+	return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI);
+}
+
+static void __exit ibmmca_exit(void)
+{
+	mca_unregister_driver(&ibmmca_driver);
+}
+
+module_init(ibmmca_init);
+module_exit(ibmmca_exit);
diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h
deleted file mode 100644
index 017ee2f..0000000
--- a/drivers/scsi/ibmmca.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Low Level Driver for the IBM Microchannel SCSI Subsystem
- * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the
- * IBM MCA SCSI-driver.
- * For use under the GNU General Public License within the Linux-kernel project.
- * This include file works only correctly with kernel 2.4.0 or higher!!! */
-
-#ifndef _IBMMCA_H
-#define _IBMMCA_H
-
-/* Common forward declarations for all Linux-versions: */
-
-/* Interfaces to the midlevel Linux SCSI driver */
-static int ibmmca_detect (struct scsi_host_template *);
-static int ibmmca_release (struct Scsi_Host *);
-static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-static int ibmmca_abort (Scsi_Cmnd *);
-static int ibmmca_host_reset (Scsi_Cmnd *);
-static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
-
-#endif /* _IBMMCA_H */
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index b10eefe..b580af95 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1375,6 +1375,23 @@
 	return 0;
 }
 
+/**
+ * ibmvscsi_change_queue_depth - Change the device's queue depth
+ * @sdev:	scsi device struct
+ * @qdepth:	depth to set
+ *
+ * Return value:
+ * 	actual depth set
+ **/
+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+	if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
+		qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
+
+	scsi_adjust_queue_depth(sdev, 0, qdepth);
+	return sdev->queue_depth;
+}
+
 /* ------------------------------------------------------------
  * sysfs attributes
  */
@@ -1521,6 +1538,7 @@
 	.eh_abort_handler = ibmvscsi_eh_abort_handler,
 	.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
 	.slave_configure = ibmvscsi_slave_configure,
+	.change_queue_depth = ibmvscsi_change_queue_depth,
 	.cmd_per_lun = 16,
 	.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
 	.this_id = -1,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 77cc1d4..727ca7c 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -45,6 +45,7 @@
 #define MAX_INDIRECT_BUFS 10
 
 #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+#define IBMVSCSI_MAX_CMDS_PER_LUN 64
 
 /* ------------------------------------------------------------
  * Data Structures
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 7e7635c..d9dfb69 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 1994-1998 Initio Corporation
  * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
- * All rights reserved.
+ * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2007 Red Hat <alan@redhat.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,38 +20,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
  *
  *************************************************************************
  *
@@ -70,14 +39,14 @@
  *		- Fix memory allocation problem
  * 03/04/98 hc	- v1.01l
  *		- Fix tape rewind which will hang the system problem
- *		- Set can_queue to tul_num_scb
+ *		- Set can_queue to initio_num_scb
  * 06/25/98 hc	- v1.01m
  *		- Get it work for kernel version >= 2.1.75
- *		- Dynamic assign SCSI bus reset holding time in init_tulip()
+ *		- Dynamic assign SCSI bus reset holding time in initio_init()
  * 07/02/98 hc	- v1.01n
  *		- Support 0002134A
  * 08/07/98 hc  - v1.01o
- *		- Change the tul_abort_srb routine to use scsi_done. <01>
+ *		- Change the initio_abort_srb routine to use scsi_done. <01>
  * 09/07/98 hl  - v1.02
  *              - Change the INI9100U define and proc_dir_entry to
  *                reflect the newer Kernel 2.1.118, but the v1.o1o
@@ -150,23 +119,13 @@
 static unsigned int i91u_debug = DEBUG_DEFAULT;
 #endif
 
-#define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
-
-typedef struct PCI_ID_Struc {
-	unsigned short vendor_id;
-	unsigned short device_id;
-} PCI_ID;
-
-static int tul_num_ch = 4;	/* Maximum 4 adapters           */
-static int tul_num_scb;
-static int tul_tag_enable = 1;
-static SCB *tul_scb;
+static int initio_tag_enable = 1;
 
 #ifdef DEBUG_i91u
 static int setup_debug = 0;
 #endif
 
-static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
+static void i91uSCBPost(u8 * pHcb, u8 * pScb);
 
 /* PCI Devices supported by this driver */
 static struct pci_device_id i91u_pci_devices[] = {
@@ -184,74 +143,66 @@
 #define DEBUG_STATE     0
 #define INT_DISC	0
 
-/*--- external functions --*/
-static void tul_se2_wait(void);
+/*--- forward references ---*/
+static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
+static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);
 
-/*--- forward refrence ---*/
-static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
-static SCB *tul_find_done_scb(HCS * pCurHcb);
+static int tulip_main(struct initio_host * host);
 
-static int tulip_main(HCS * pCurHcb);
+static int initio_next_state(struct initio_host * host);
+static int initio_state_1(struct initio_host * host);
+static int initio_state_2(struct initio_host * host);
+static int initio_state_3(struct initio_host * host);
+static int initio_state_4(struct initio_host * host);
+static int initio_state_5(struct initio_host * host);
+static int initio_state_6(struct initio_host * host);
+static int initio_state_7(struct initio_host * host);
+static int initio_xfer_data_in(struct initio_host * host);
+static int initio_xfer_data_out(struct initio_host * host);
+static int initio_xpad_in(struct initio_host * host);
+static int initio_xpad_out(struct initio_host * host);
+static int initio_status_msg(struct initio_host * host);
 
-static int tul_next_state(HCS * pCurHcb);
-static int tul_state_1(HCS * pCurHcb);
-static int tul_state_2(HCS * pCurHcb);
-static int tul_state_3(HCS * pCurHcb);
-static int tul_state_4(HCS * pCurHcb);
-static int tul_state_5(HCS * pCurHcb);
-static int tul_state_6(HCS * pCurHcb);
-static int tul_state_7(HCS * pCurHcb);
-static int tul_xfer_data_in(HCS * pCurHcb);
-static int tul_xfer_data_out(HCS * pCurHcb);
-static int tul_xpad_in(HCS * pCurHcb);
-static int tul_xpad_out(HCS * pCurHcb);
-static int tul_status_msg(HCS * pCurHcb);
+static int initio_msgin(struct initio_host * host);
+static int initio_msgin_sync(struct initio_host * host);
+static int initio_msgin_accept(struct initio_host * host);
+static int initio_msgout_reject(struct initio_host * host);
+static int initio_msgin_extend(struct initio_host * host);
 
-static int tul_msgin(HCS * pCurHcb);
-static int tul_msgin_sync(HCS * pCurHcb);
-static int tul_msgin_accept(HCS * pCurHcb);
-static int tul_msgout_reject(HCS * pCurHcb);
-static int tul_msgin_extend(HCS * pCurHcb);
+static int initio_msgout_ide(struct initio_host * host);
+static int initio_msgout_abort_targ(struct initio_host * host);
+static int initio_msgout_abort_tag(struct initio_host * host);
 
-static int tul_msgout_ide(HCS * pCurHcb);
-static int tul_msgout_abort_targ(HCS * pCurHcb);
-static int tul_msgout_abort_tag(HCS * pCurHcb);
+static int initio_bus_device_reset(struct initio_host * host);
+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
+static int int_initio_busfree(struct initio_host * host);
+static int int_initio_scsi_rst(struct initio_host * host);
+static int int_initio_bad_seq(struct initio_host * host);
+static int int_initio_resel(struct initio_host * host);
+static int initio_sync_done(struct initio_host * host);
+static int wdtr_done(struct initio_host * host);
+static int wait_tulip(struct initio_host * host);
+static int initio_wait_done_disc(struct initio_host * host);
+static int initio_wait_disc(struct initio_host * host);
+static void tulip_scsi(struct initio_host * host);
+static int initio_post_scsi_rst(struct initio_host * host);
 
-static int tul_bus_device_reset(HCS * pCurHcb);
-static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
-static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
-static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
-static int int_tul_busfree(HCS * pCurHcb);
-static int int_tul_scsi_rst(HCS * pCurHcb);
-static int int_tul_bad_seq(HCS * pCurHcb);
-static int int_tul_resel(HCS * pCurHcb);
-static int tul_sync_done(HCS * pCurHcb);
-static int wdtr_done(HCS * pCurHcb);
-static int wait_tulip(HCS * pCurHcb);
-static int tul_wait_done_disc(HCS * pCurHcb);
-static int tul_wait_disc(HCS * pCurHcb);
-static void tulip_scsi(HCS * pCurHcb);
-static int tul_post_scsi_rst(HCS * pCurHcb);
+static void initio_se2_ew_en(unsigned long base);
+static void initio_se2_ew_ds(unsigned long base);
+static int initio_se2_rd_all(unsigned long base);
+static void initio_se2_update_all(unsigned long base);	/* setup default pattern */
+static void initio_read_eeprom(unsigned long base);
 
-static void tul_se2_ew_en(WORD CurBase);
-static void tul_se2_ew_ds(WORD CurBase);
-static int tul_se2_rd_all(WORD CurBase);
-static void tul_se2_update_all(WORD CurBase);	/* setup default pattern */
-static void tul_read_eeprom(WORD CurBase);
+/* ---- INTERNAL VARIABLES ---- */
 
-				/* ---- INTERNAL VARIABLES ---- */
-static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
-static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
-
-/*NVRAM nvram, *nvramp = &nvram; */
 static NVRAM i91unvram;
 static NVRAM *i91unvramp;
 
-
-
-static UCHAR i91udftNvRam[64] =
+static u8 i91udftNvRam[64] =
 {
-/*----------- header -----------*/
+	/*----------- header -----------*/
 	0x25, 0xc9,		/* Signature    */
 	0x40,			/* Size         */
 	0x01,			/* Revision     */
@@ -289,7 +240,7 @@
 	0, 0};			/*      - CheckSum -            */
 
 
-static UCHAR tul_rate_tbl[8] =	/* fast 20      */
+static u8 initio_rate_tbl[8] =	/* fast 20      */
 {
 				/* nanosecond devide by 4 */
 	12,			/* 50ns,  20M   */
@@ -302,53 +253,17 @@
 	62			/* 250ns, 4M    */
 };
 
-static void tul_do_pause(unsigned amount)
-{				/* Pause for amount jiffies */
+static void initio_do_pause(unsigned amount)
+{
+	/* Pause for amount jiffies */
 	unsigned long the_time = jiffies + amount;
 
-	while (time_before_eq(jiffies, the_time));
+	while (time_before_eq(jiffies, the_time))
+		cpu_relax();
 }
 
 /*-- forward reference --*/
 
-/*******************************************************************
-	Use memeory refresh time        ~ 15us * 2
-********************************************************************/
-void tul_se2_wait(void)
-{
-#if 1
-	udelay(30);
-#else
-	UCHAR readByte;
-
-	readByte = TUL_RD(0, 0x61);
-	if ((readByte & 0x10) == 0x10) {
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) == 0x10)
-				break;
-		}
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) != 0x10)
-				break;
-		}
-	} else {
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) == 0x10)
-				break;
-		}
-		for (;;) {
-			readByte = TUL_RD(0, 0x61);
-			if ((readByte & 0x10) != 0x10)
-				break;
-		}
-	}
-#endif
-}
-
-
 /******************************************************************
  Input: instruction for  Serial E2PROM
 
@@ -379,1174 +294,1019 @@
 
 
 ******************************************************************/
-static void tul_se2_instr(WORD CurBase, UCHAR instr)
+
+/**
+ *	initio_se2_instr	-	bitbang an instruction
+ *	@base: Base of InitIO controller
+ *	@instr: Instruction for serial E2PROM
+ *
+ *	Bitbang an instruction out to the serial E2Prom
+ */
+
+static void initio_se2_instr(unsigned long base, u8 instr)
 {
 	int i;
-	UCHAR b;
+	u8 b;
 
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* cs+start bit */
-	tul_se2_wait();
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);	/* +CLK */
-	tul_se2_wait();
+	outb(SE2CS | SE2DO, base + TUL_NVRAM);		/* cs+start bit */
+	udelay(30);
+	outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM);	/* +CLK */
+	udelay(30);
 
 	for (i = 0; i < 8; i++) {
 		if (instr & 0x80)
-			b = SE2CS | SE2DO;	/* -CLK+dataBit */
+			b = SE2CS | SE2DO;		/* -CLK+dataBit */
 		else
-			b = SE2CS;	/* -CLK */
-		TUL_WR(CurBase + TUL_NVRAM, b);
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);	/* +CLK */
-		tul_se2_wait();
+			b = SE2CS;			/* -CLK */
+		outb(b, base + TUL_NVRAM);
+		udelay(30);
+		outb(b | SE2CLK, base + TUL_NVRAM);	/* +CLK */
+		udelay(30);
 		instr <<= 1;
 	}
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-	tul_se2_wait();
-	return;
+	outb(SE2CS, base + TUL_NVRAM);			/* -CLK */
+	udelay(30);
 }
 
 
-/******************************************************************
- Function name  : tul_se2_ew_en
- Description    : Enable erase/write state of serial EEPROM
-******************************************************************/
-void tul_se2_ew_en(WORD CurBase)
+/**
+ *	initio_se2_ew_en	-	Enable erase/write
+ *	@base: Base address of InitIO controller
+ *
+ *	Enable erase/write state of serial EEPROM
+ */
+void initio_se2_ew_en(unsigned long base)
 {
-	tul_se2_instr(CurBase, 0x30);	/* EWEN */
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
-	return;
+	initio_se2_instr(base, 0x30);	/* EWEN */
+	outb(0, base + TUL_NVRAM);	/* -CS  */
+	udelay(30);
 }
 
 
-/************************************************************************
- Disable erase/write state of serial EEPROM
-*************************************************************************/
-void tul_se2_ew_ds(WORD CurBase)
+/**
+ *	initio_se2_ew_ds	-	Disable erase/write
+ *	@base: Base address of InitIO controller
+ *
+ *	Disable erase/write state of serial EEPROM
+ */
+void initio_se2_ew_ds(unsigned long base)
 {
-	tul_se2_instr(CurBase, 0);	/* EWDS */
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
-	return;
+	initio_se2_instr(base, 0);	/* EWDS */
+	outb(0, base + TUL_NVRAM);	/* -CS  */
+	udelay(30);
 }
 
 
-/******************************************************************
-	Input  :address of Serial E2PROM
-	Output :value stored in  Serial E2PROM
-*******************************************************************/
-static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+/**
+ *	initio_se2_rd		-	read E2PROM word
+ *	@base: Base of InitIO controller
+ *	@addr: Address of word in E2PROM
+ *
+ *	Read a word from the NV E2PROM device
+ */
+static u16 initio_se2_rd(unsigned long base, u8 addr)
 {
-	UCHAR instr, readByte;
-	USHORT readWord;
+	u8 instr, rb;
+	u16 val = 0;
 	int i;
 
-	instr = (UCHAR) (adr | 0x80);
-	tul_se2_instr(CurBase, instr);	/* READ INSTR */
-	readWord = 0;
+	instr = (u8) (addr | 0x80);
+	initio_se2_instr(base, instr);	/* READ INSTR */
 
 	for (i = 15; i >= 0; i--) {
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);	/* +CLK */
+		udelay(30);
+		outb(SE2CS, base + TUL_NVRAM);		/* -CLK */
 
 		/* sample data after the following edge of clock  */
-		readByte = TUL_RD(CurBase, TUL_NVRAM);
-		readByte &= SE2DI;
-		readWord += (readByte << i);
-		tul_se2_wait();	/* 6/20/95 */
+		rb = inb(base + TUL_NVRAM);
+		rb &= SE2DI;
+		val += (rb << i);
+		udelay(30);	/* 6/20/95 */
 	}
 
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* no chip select */
-	tul_se2_wait();
-	return readWord;
+	outb(0, base + TUL_NVRAM);		/* no chip select */
+	udelay(30);
+	return val;
 }
 
-
-/******************************************************************
- Input: new value in  Serial E2PROM, address of Serial E2PROM
-*******************************************************************/
-static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+/**
+ *	initio_se2_wr		-	read E2PROM word
+ *	@base: Base of InitIO controller
+ *	@addr: Address of word in E2PROM
+ *	@val: Value to write
+ *
+ *	Write a word to the NV E2PROM device. Used when recovering from
+ *	a problem with the NV.
+ */
+static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
 {
-	UCHAR readByte;
-	UCHAR instr;
+	u8 rb;
+	u8 instr;
 	int i;
 
-	instr = (UCHAR) (adr | 0x40);
-	tul_se2_instr(CurBase, instr);	/* WRITE INSTR */
+	instr = (u8) (addr | 0x40);
+	initio_se2_instr(base, instr);	/* WRITE INSTR */
 	for (i = 15; i >= 0; i--) {
-		if (writeWord & 0x8000)
-			TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* -CLK+dataBit 1 */
+		if (val & 0x8000)
+			outb(SE2CS | SE2DO, base + TUL_NVRAM);	/* -CLK+dataBit 1 */
 		else
-			TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK+dataBit 0 */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		writeWord <<= 1;
+			outb(SE2CS, base + TUL_NVRAM);		/* -CLK+dataBit 0 */
+		udelay(30);
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */
+		udelay(30);
+		val <<= 1;
 	}
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-	tul_se2_wait();
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
-	tul_se2_wait();
+	outb(SE2CS, base + TUL_NVRAM);				/* -CLK */
+	udelay(30);
+	outb(0, base + TUL_NVRAM);				/* -CS  */
+	udelay(30);
 
-	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* +CS  */
-	tul_se2_wait();
+	outb(SE2CS, base + TUL_NVRAM);				/* +CS  */
+	udelay(30);
 
 	for (;;) {
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
-		tul_se2_wait();
-		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
-		tul_se2_wait();
-		if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
+		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */
+		udelay(30);
+		outb(SE2CS, base + TUL_NVRAM);			/* -CLK */
+		udelay(30);
+		if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
 			break;	/* write complete */
 	}
-	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS */
-	return;
+	outb(0, base + TUL_NVRAM);				/* -CS */
 }
 
+/**
+ *	initio_se2_rd_all	-	read hostadapter NV configuration
+ *	@base: Base address of InitIO controller
+ *
+ *	Reads the E2PROM data into main memory. Ensures that the checksum
+ *	and header marker are valid. Returns 1 on success -1 on error.
+ */
 
-/***********************************************************************
- Read SCSI H/A configuration parameters from serial EEPROM
-************************************************************************/
-int tul_se2_rd_all(WORD CurBase)
+static int initio_se2_rd_all(unsigned long base)
 {
 	int i;
-	ULONG chksum = 0;
-	USHORT *np;
+	u16 chksum = 0;
+	u16 *np;
 
 	i91unvramp = &i91unvram;
-	np = (USHORT *) i91unvramp;
-	for (i = 0; i < 32; i++) {
-		*np++ = tul_se2_rd(CurBase, i);
-	}
+	np = (u16 *) i91unvramp;
+	for (i = 0; i < 32; i++)
+		*np++ = initio_se2_rd(base, i);
 
-/*--------------------Is signature "ini" ok ? ----------------*/
+	/* Is signature "ini" ok ? */
 	if (i91unvramp->NVM_Signature != INI_SIGNATURE)
 		return -1;
-/*---------------------- Is ckecksum ok ? ----------------------*/
-	np = (USHORT *) i91unvramp;
+	/* Is ckecksum ok ? */
+	np = (u16 *) i91unvramp;
 	for (i = 0; i < 31; i++)
 		chksum += *np++;
-	if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
+	if (i91unvramp->NVM_CheckSum != chksum)
 		return -1;
 	return 1;
 }
 
-
-/***********************************************************************
- Update SCSI H/A configuration parameters from serial EEPROM
-************************************************************************/
-void tul_se2_update_all(WORD CurBase)
+/**
+ *	initio_se2_update_all		-	Update E2PROM
+ *	@base: Base of InitIO controller
+ *
+ *	Update the E2PROM by wrting any changes into the E2PROM
+ *	chip, rewriting the checksum.
+ */
+static void initio_se2_update_all(unsigned long base)
 {				/* setup default pattern */
 	int i;
-	ULONG chksum = 0;
-	USHORT *np, *np1;
+	u16 chksum = 0;
+	u16 *np, *np1;
 
 	i91unvramp = &i91unvram;
 	/* Calculate checksum first */
-	np = (USHORT *) i91udftNvRam;
+	np = (u16 *) i91udftNvRam;
 	for (i = 0; i < 31; i++)
 		chksum += *np++;
-	*np = (USHORT) chksum;
-	tul_se2_ew_en(CurBase);	/* Enable write  */
+	*np = chksum;
+	initio_se2_ew_en(base);	/* Enable write  */
 
-	np = (USHORT *) i91udftNvRam;
-	np1 = (USHORT *) i91unvramp;
+	np = (u16 *) i91udftNvRam;
+	np1 = (u16 *) i91unvramp;
 	for (i = 0; i < 32; i++, np++, np1++) {
-		if (*np != *np1) {
-			tul_se2_wr(CurBase, i, *np);
-		}
+		if (*np != *np1)
+			initio_se2_wr(base, i, *np);
 	}
-
-	tul_se2_ew_ds(CurBase);	/* Disable write   */
-	return;
+	initio_se2_ew_ds(base);	/* Disable write   */
 }
 
-/*************************************************************************
- Function name  : read_eeprom
-**************************************************************************/
-void tul_read_eeprom(WORD CurBase)
+/**
+ *	initio_read_eeprom		-	Retrieve configuration
+ *	@base: Base of InitIO Host Adapter
+ *
+ *	Retrieve the host adapter configuration data from E2Prom. If the
+ *	data is invalid then the defaults are used and are also restored
+ *	into the E2PROM. This forms the access point for the SCSI driver
+ *	into the E2PROM layer, the other functions for the E2PROM are all
+ *	internal use.
+ *
+ *	Must be called single threaded, uses a shared global area.
+ */
+
+static void initio_read_eeprom(unsigned long base)
 {
-	UCHAR gctrl;
+	u8 gctrl;
 
 	i91unvramp = &i91unvram;
-/*------Enable EEProm programming ---*/
-	gctrl = TUL_RD(CurBase, TUL_GCTRL);
-	TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
-	if (tul_se2_rd_all(CurBase) != 1) {
-		tul_se2_update_all(CurBase);	/* setup default pattern */
-		tul_se2_rd_all(CurBase);	/* load again  */
+	/* Enable EEProm programming */
+	gctrl = inb(base + TUL_GCTRL);
+	outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
+	if (initio_se2_rd_all(base) != 1) {
+		initio_se2_update_all(base);	/* setup default pattern */
+		initio_se2_rd_all(base);	/* load again  */
 	}
-/*------ Disable EEProm programming ---*/
-	gctrl = TUL_RD(CurBase, TUL_GCTRL);
-	TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
-}				/* read_eeprom */
-
-static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
-				      BYTE bBus, BYTE bDevice)
-{
-	int i, j;
-
-	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
-		if (i91u_adpt[i].ADPT_BIOS < wBIOS)
-			continue;
-		if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
-			if (i91u_adpt[i].ADPT_BASE == wBASE) {
-				if (i91u_adpt[i].ADPT_Bus != 0xFF)
-					return 1;
-			} else if (i91u_adpt[i].ADPT_BASE < wBASE)
-					continue;
-		}
-		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
-			i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
-			i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
-			i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
-			i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
-			i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
-		}
-		i91u_adpt[i].ADPT_BASE = wBASE;
-		i91u_adpt[i].ADPT_INTR = bInterrupt;
-		i91u_adpt[i].ADPT_BIOS = wBIOS;
-		i91u_adpt[i].ADPT_Bus = bBus;
-		i91u_adpt[i].ADPT_Device = bDevice;
-		return 0;
-	}
-	return 1;
+	/* Disable EEProm programming */
+	gctrl = inb(base + TUL_GCTRL);
+	outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
 }
 
-static void init_i91uAdapter_table(void)
-{
-	int i;
+/**
+ *	initio_stop_bm		-	stop bus master
+ *	@host: InitIO we are stopping
+ *
+ *	Stop any pending DMA operation, aborting the DMA if neccessary
+ */
 
-	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
-		i91u_adpt[i].ADPT_BIOS = 0xffff;
-		i91u_adpt[i].ADPT_BASE = 0xffff;
-		i91u_adpt[i].ADPT_INTR = 0xff;
-		i91u_adpt[i].ADPT_Bus = 0xff;
-		i91u_adpt[i].ADPT_Device = 0xff;
-	}
-	return;
-}
-
-static void tul_stop_bm(HCS * pCurHcb)
+static void initio_stop_bm(struct initio_host * host)
 {
 
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+	if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
 		/* wait Abort DMA xfer done */
-		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+		while ((inb(host->addr + TUL_Int) & XABT) == 0)
+			cpu_relax();
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 }
 
-/***************************************************************************/
-static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
-{
-	pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
-	pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
-	pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
-	return;
-}
+/**
+ *	initio_reset_scsi		-	Reset SCSI host controller
+ *	@host: InitIO host to reset
+ *	@seconds: Recovery time
+ *
+ *	Perform a full reset of the SCSI subsystem.
+ */
 
-/***************************************************************************/
-static int tul_reset_scsi(HCS * pCurHcb, int seconds)
+static int initio_reset_scsi(struct initio_host * host, int seconds)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
+	outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);
 
-	while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
+	while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))
+		cpu_relax();
+
 	/* reset tulip chip */
-
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
+	outb(0, host->addr + TUL_SSignal);
 
 	/* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
 	/* SONY 5200 tape drive won't work if only stall for 1 sec */
-	tul_do_pause(seconds * HZ);
+	/* FIXME: this is a very long busy wait right now */
+	initio_do_pause(seconds * HZ);
 
-	TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-	return (SCSI_RESET_SUCCESS);
+	inb(host->addr + TUL_SInt);
+	return SCSI_RESET_SUCCESS;
 }
 
-/***************************************************************************/
-static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
-		      BYTE * pbBiosAdr, int seconds)
+/**
+ *	initio_init		-	set up an InitIO host adapter
+ *	@host: InitIO host adapter
+ *	@num_scbs: Number of SCBS
+ *	@bios_addr: BIOS address
+ *
+ *	Set up the host adapter and devices according to the configuration
+ *	retrieved from the E2PROM.
+ *
+ *	Locking: Calls E2PROM layer code which is not re-enterable so must
+ *	run single threaded for now.
+ */
+
+static void initio_init(struct initio_host * host, u8 *bios_addr)
 {
 	int i;
-	BYTE *pwFlags;
-	BYTE *pbHeads;
-	SCB *pTmpScb, *pPrevScb = NULL;
+	u8 *flags;
+	u8 *heads;
 
-	pCurHcb->HCS_NumScbs = tul_num_scb;
-	pCurHcb->HCS_Semaph = 1;
-	spin_lock_init(&pCurHcb->HCS_SemaphLock);
-	pCurHcb->HCS_JSStatus0 = 0;
-	pCurHcb->HCS_Scb = scbp;
-	pCurHcb->HCS_NxtPend = scbp;
-	pCurHcb->HCS_NxtAvail = scbp;
-	for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
-		pTmpScb->SCB_TagId = i;
-		if (i != 0)
-			pPrevScb->SCB_NxtScb = pTmpScb;
-		pPrevScb = pTmpScb;
-	}
-	pPrevScb->SCB_NxtScb = NULL;
-	pCurHcb->HCS_ScbEnd = pTmpScb;
-	pCurHcb->HCS_FirstAvail = scbp;
-	pCurHcb->HCS_LastAvail = pPrevScb;
-	spin_lock_init(&pCurHcb->HCS_AvailLock);
-	pCurHcb->HCS_FirstPend = NULL;
-	pCurHcb->HCS_LastPend = NULL;
-	pCurHcb->HCS_FirstBusy = NULL;
-	pCurHcb->HCS_LastBusy = NULL;
-	pCurHcb->HCS_FirstDone = NULL;
-	pCurHcb->HCS_LastDone = NULL;
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
-
-	tul_read_eeprom(pCurHcb->HCS_Base);
-/*---------- get H/A configuration -------------*/
+	/* Get E2Prom configuration */
+	initio_read_eeprom(host->addr);
 	if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
-		pCurHcb->HCS_MaxTar = 8;
+		host->max_tar = 8;
 	else
-		pCurHcb->HCS_MaxTar = 16;
+		host->max_tar = 16;
 
-	pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
+	host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
 
-	pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
-	pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
+	host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
+	host->idmask = ~(1 << host->scsi_id);
 
 #ifdef CHK_PARITY
 	/* Enable parity error response */
-	TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
+	outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);
 #endif
 
 	/* Mask all the interrupt       */
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	outb(0x1F, host->addr + TUL_Mask);
 
-	tul_stop_bm(pCurHcb);
+	initio_stop_bm(host);
 	/* --- Initialize the tulip --- */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
+	outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);
 
 	/* program HBA's SCSI ID        */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
+	outb(host->scsi_id << 4, host->addr + TUL_SScsiId);
 
 	/* Enable Initiator Mode ,phase latch,alternate sync period mode,
 	   disable SCSI reset */
-	if (pCurHcb->HCS_Config & HCC_EN_PAR)
-		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
+	if (host->config & HCC_EN_PAR)
+		host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
 	else
-		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
+		host->sconf1 = (TSC_INITDEFAULT);
+	outb(host->sconf1, host->addr + TUL_SConfig);
 
-	/* Enable HW reselect           */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+	/* Enable HW reselect */
+	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
+	outb(0, host->addr + TUL_SPeriod);
 
 	/* selection time out = 250 ms */
-	TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
+	outb(153, host->addr + TUL_STimeOut);
 
-/*--------- Enable SCSI terminator -----*/
-	TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
-	TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
-	       ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
+	/* Enable SCSI terminator */
+	outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),
+		host->addr + TUL_XCtrl);
+	outb(((host->config & HCC_AUTO_TERM) >> 4) |
+		(inb(host->addr + TUL_GCTRL1) & 0xFE),
+		host->addr + TUL_GCTRL1);
 
 	for (i = 0,
-	     pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
-	     pbHeads = pbBiosAdr + 0x180;
-	     i < pCurHcb->HCS_MaxTar;
-	     i++, pwFlags++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-		if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+	     flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
+	     heads = bios_addr + 0x180;
+	     i < host->max_tar;
+	     i++, flags++) {
+		host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+		if (host->targets[i].flags & TCF_EN_255)
+			host->targets[i].drv_flags = TCF_DRV_255_63;
 		else
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
-		pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
-		pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
-		pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
-		if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+			host->targets[i].drv_flags = 0;
+		host->targets[i].js_period = 0;
+		host->targets[i].sconfig0 = host->sconf1;
+		host->targets[i].heads = *heads++;
+		if (host->targets[i].heads == 255)
+			host->targets[i].drv_flags = TCF_DRV_255_63;
 		else
-			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
-		pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
-		pCurHcb->HCS_ActTags[i] = 0;
-		pCurHcb->HCS_MaxTags[i] = 0xFF;
+			host->targets[i].drv_flags = 0;
+		host->targets[i].sectors = *heads++;
+		host->targets[i].flags &= ~TCF_BUSY;
+		host->act_tags[i] = 0;
+		host->max_tags[i] = 0xFF;
 	}			/* for                          */
 	printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
-	       pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
-	       pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
-/*------------------- reset SCSI Bus ---------------------------*/
-	if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
-		printk("i91u: Reset SCSI Bus ... \n");
-		tul_reset_scsi(pCurHcb, seconds);
+	       host->addr, host->irq,
+	       host->bios_addr, host->scsi_id);
+	/* Reset SCSI Bus */
+	if (host->config & HCC_SCSI_RESET) {
+		printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");
+		initio_reset_scsi(host, 10);
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
-	return (0);
+	outb(0x17, host->addr + TUL_SCFG1);
+	outb(0xE9, host->addr + TUL_SIntEnable);
 }
 
-/***************************************************************************/
-static SCB *tul_alloc_scb(HCS * hcsp)
+/**
+ *	initio_alloc_scb		-	Allocate an SCB
+ *	@host: InitIO host we are allocating for
+ *
+ *	Walk the SCB list for the controller and allocate a free SCB if
+ *	one exists.
+ */
+static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)
 {
-	SCB *pTmpScb;
-	ULONG flags;
-	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
-	if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
+	struct scsi_ctrl_blk *scb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->avail_lock, flags);
+	if ((scb = host->first_avail) != NULL) {
 #if DEBUG_QUEUE
-		printk("find scb at %08lx\n", (ULONG) pTmpScb);
+		printk("find scb at %p\n", scb);
 #endif
-		if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
-			hcsp->HCS_LastAvail = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
-		pTmpScb->SCB_Status = SCB_RENT;
+		if ((host->first_avail = scb->next) == NULL)
+			host->last_avail = NULL;
+		scb->next = NULL;
+		scb->status = SCB_RENT;
 	}
-	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
-	return (pTmpScb);
+	spin_unlock_irqrestore(&host->avail_lock, flags);
+	return scb;
 }
 
-/***************************************************************************/
-static void tul_release_scb(HCS * hcsp, SCB * scbp)
+/**
+ *	initio_release_scb		-	Release an SCB
+ *	@host: InitIO host that owns the SCB
+ *	@cmnd: SCB command block being returned
+ *
+ *	Return an allocated SCB to the host free list
+ */
+
+static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)
 {
-	ULONG flags;
+	unsigned long flags;
 
 #if DEBUG_QUEUE
-	printk("Release SCB %lx; ", (ULONG) scbp);
+	printk("Release SCB %p; ", cmnd);
 #endif
-	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
-	scbp->SCB_Srb = NULL;
-	scbp->SCB_Status = 0;
-	scbp->SCB_NxtScb = NULL;
-	if (hcsp->HCS_LastAvail != NULL) {
-		hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
-		hcsp->HCS_LastAvail = scbp;
+	spin_lock_irqsave(&(host->avail_lock), flags);
+	cmnd->srb = NULL;
+	cmnd->status = 0;
+	cmnd->next = NULL;
+	if (host->last_avail != NULL) {
+		host->last_avail->next = cmnd;
+		host->last_avail = cmnd;
 	} else {
-		hcsp->HCS_FirstAvail = scbp;
-		hcsp->HCS_LastAvail = scbp;
+		host->first_avail = cmnd;
+		host->last_avail = cmnd;
 	}
-	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+	spin_unlock_irqrestore(&(host->avail_lock), flags);
 }
 
 /***************************************************************************/
-static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("Append pend SCB %lx; ", (ULONG) scbp);
+	printk("Append pend SCB %p; ", scbp);
 #endif
-	scbp->SCB_Status = SCB_PEND;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastPend != NULL) {
-		pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+	scbp->status = SCB_PEND;
+	scbp->next = NULL;
+	if (host->last_pending != NULL) {
+		host->last_pending->next = scbp;
+		host->last_pending = scbp;
 	} else {
-		pCurHcb->HCS_FirstPend = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+		host->first_pending = scbp;
+		host->last_pending = scbp;
 	}
 }
 
 /***************************************************************************/
-static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("Push pend SCB %lx; ", (ULONG) scbp);
+	printk("Push pend SCB %p; ", scbp);
 #endif
-	scbp->SCB_Status = SCB_PEND;
-	if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
-		pCurHcb->HCS_FirstPend = scbp;
+	scbp->status = SCB_PEND;
+	if ((scbp->next = host->first_pending) != NULL) {
+		host->first_pending = scbp;
 	} else {
-		pCurHcb->HCS_FirstPend = scbp;
-		pCurHcb->HCS_LastPend = scbp;
+		host->first_pending = scbp;
+		host->last_pending = scbp;
 	}
 }
 
-/***************************************************************************/
-static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)
 {
-	SCB *pFirstPend;
+	struct scsi_ctrl_blk *first;
 
 
-	pFirstPend = pCurHcb->HCS_FirstPend;
-	while (pFirstPend != NULL) {
-		if (pFirstPend->SCB_Opcode != ExecSCSI) {
-			return (pFirstPend);
-		}
-		if (pFirstPend->SCB_TagMsg == 0) {
-			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
-			    !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
-				return (pFirstPend);
-			}
+	first = host->first_pending;
+	while (first != NULL) {
+		if (first->opcode != ExecSCSI)
+			return first;
+		if (first->tagmsg == 0) {
+			if ((host->act_tags[first->target] == 0) &&
+			    !(host->targets[first->target].flags & TCF_BUSY))
+				return first;
 		} else {
-			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
-			  pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
-			    (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
-				pFirstPend = pFirstPend->SCB_NxtScb;
+			if ((host->act_tags[first->target] >=
+			  host->max_tags[first->target]) |
+			    (host->targets[first->target].flags & TCF_BUSY)) {
+				first = first->next;
 				continue;
 			}
-			return (pFirstPend);
+			return first;
 		}
-		pFirstPend = pFirstPend->SCB_NxtScb;
+		first = first->next;
 	}
-
-
-	return (pFirstPend);
+	return first;
 }
-/***************************************************************************/
-static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+
+static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	SCB *pTmpScb, *pPrevScb;
+	struct scsi_ctrl_blk *tmp, *prev;
 
 #if DEBUG_QUEUE
-	printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
+	printk("unlink pend SCB %p; ", scb);
 #endif
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
-	while (pTmpScb != NULL) {
-		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
-			if (pTmpScb == pCurHcb->HCS_FirstPend) {
-				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastPend = NULL;
+	prev = tmp = host->first_pending;
+	while (tmp != NULL) {
+		if (scb == tmp) {	/* Unlink this SCB              */
+			if (tmp == host->first_pending) {
+				if ((host->first_pending = tmp->next) == NULL)
+					host->last_pending = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastPend)
-					pCurHcb->HCS_LastPend = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_pending)
+					host->last_pending = prev;
 			}
-			pTmpScb->SCB_NxtScb = NULL;
+			tmp->next = NULL;
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
-	return;
 }
-/***************************************************************************/
-static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+
+static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
 
 #if DEBUG_QUEUE
-	printk("append busy SCB %lx; ", (ULONG) scbp);
+	printk("append busy SCB %o; ", scbp);
 #endif
-	if (scbp->SCB_TagMsg)
-		pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
+	if (scbp->tagmsg)
+		host->act_tags[scbp->target]++;
 	else
-		pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
-	scbp->SCB_Status = SCB_BUSY;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastBusy != NULL) {
-		pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastBusy = scbp;
+		host->targets[scbp->target].flags |= TCF_BUSY;
+	scbp->status = SCB_BUSY;
+	scbp->next = NULL;
+	if (host->last_busy != NULL) {
+		host->last_busy->next = scbp;
+		host->last_busy = scbp;
 	} else {
-		pCurHcb->HCS_FirstBusy = scbp;
-		pCurHcb->HCS_LastBusy = scbp;
+		host->first_busy = scbp;
+		host->last_busy = scbp;
 	}
 }
 
 /***************************************************************************/
-static SCB *tul_pop_busy_scb(HCS * pCurHcb)
+static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)
 {
-	SCB *pTmpScb;
+	struct scsi_ctrl_blk *tmp;
 
 
-	if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
-		if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-			pCurHcb->HCS_LastBusy = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
-		if (pTmpScb->SCB_TagMsg)
-			pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+	if ((tmp = host->first_busy) != NULL) {
+		if ((host->first_busy = tmp->next) == NULL)
+			host->last_busy = NULL;
+		tmp->next = NULL;
+		if (tmp->tagmsg)
+			host->act_tags[tmp->target]--;
 		else
-			pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+			host->targets[tmp->target].flags &= ~TCF_BUSY;
 	}
 #if DEBUG_QUEUE
-	printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
+	printk("Pop busy SCB %p; ", tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
 /***************************************************************************/
-static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	SCB *pTmpScb, *pPrevScb;
+	struct scsi_ctrl_blk *tmp, *prev;
 
 #if DEBUG_QUEUE
-	printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
+	printk("unlink busy SCB %p; ", scb);
 #endif
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
-	while (pTmpScb != NULL) {
-		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
-			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastBusy = NULL;
+	prev = tmp = host->first_busy;
+	while (tmp != NULL) {
+		if (scb == tmp) {	/* Unlink this SCB              */
+			if (tmp == host->first_busy) {
+				if ((host->first_busy = tmp->next) == NULL)
+					host->last_busy = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastBusy)
-					pCurHcb->HCS_LastBusy = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_busy)
+					host->last_busy = prev;
 			}
-			pTmpScb->SCB_NxtScb = NULL;
-			if (pTmpScb->SCB_TagMsg)
-				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+			tmp->next = NULL;
+			if (tmp->tagmsg)
+				host->act_tags[tmp->target]--;
 			else
-				pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+				host->targets[tmp->target].flags &= ~TCF_BUSY;
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 	return;
 }
 
-/***************************************************************************/
-SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
+struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)
 {
-	SCB *pTmpScb, *pPrevScb;
-	WORD scbp_tarlun;
+	struct scsi_ctrl_blk *tmp, *prev;
+	u16 scbp_tarlun;
 
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
-	while (pTmpScb != NULL) {
-		scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
+	prev = tmp = host->first_busy;
+	while (tmp != NULL) {
+		scbp_tarlun = (tmp->lun << 8) | (tmp->target);
 		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */
 			break;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 #if DEBUG_QUEUE
-	printk("find busy SCB %lx; ", (ULONG) pTmpScb);
+	printk("find busy SCB %p; ", tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
-/***************************************************************************/
-static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
 {
-
 #if DEBUG_QUEUE
-	printk("append done SCB %lx; ", (ULONG) scbp);
+	printk("append done SCB %p; ", scbp);
 #endif
 
-	scbp->SCB_Status = SCB_DONE;
-	scbp->SCB_NxtScb = NULL;
-	if (pCurHcb->HCS_LastDone != NULL) {
-		pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
-		pCurHcb->HCS_LastDone = scbp;
+	scbp->status = SCB_DONE;
+	scbp->next = NULL;
+	if (host->last_done != NULL) {
+		host->last_done->next = scbp;
+		host->last_done = scbp;
 	} else {
-		pCurHcb->HCS_FirstDone = scbp;
-		pCurHcb->HCS_LastDone = scbp;
+		host->first_done = scbp;
+		host->last_done = scbp;
 	}
 }
 
-/***************************************************************************/
-SCB *tul_find_done_scb(HCS * pCurHcb)
+struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)
 {
-	SCB *pTmpScb;
+	struct scsi_ctrl_blk *tmp;
 
-
-	if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
-		if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
-			pCurHcb->HCS_LastDone = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
+	if ((tmp = host->first_done) != NULL) {
+		if ((host->first_done = tmp->next) == NULL)
+			host->last_done = NULL;
+		tmp->next = NULL;
 	}
 #if DEBUG_QUEUE
-	printk("find done SCB %lx; ", (ULONG) pTmpScb);
+	printk("find done SCB %p; ",tmp);
 #endif
-	return (pTmpScb);
+	return tmp;
 }
 
-/***************************************************************************/
-static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
+static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)
 {
-	ULONG flags;
-	SCB *pTmpScb, *pPrevScb;
+	unsigned long flags;
+	struct scsi_ctrl_blk *tmp, *prev;
 
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_lock_irqsave(&host->semaph_lock, flags);
 
-	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	if ((host->semaph == 0) && (host->active == NULL)) {
 		/* disable Jasmin SCSI Int        */
-
-                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-		tulip_main(pCurHcb);
-
-        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-
-		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
+		outb(0x1F, host->addr + TUL_Mask);
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
+		/* FIXME: synchronize_irq needed ? */
+		tulip_main(host);
+		spin_lock_irqsave(&host->semaph_lock, flags);
+		host->semaph = 1;
+		outb(0x0F, host->addr + TUL_Mask);
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
 		return SCSI_ABORT_SNOOZE;
 	}
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;	/* Check Pend queue */
-	while (pTmpScb != NULL) {
+	prev = tmp = host->first_pending;	/* Check Pend queue */
+	while (tmp != NULL) {
 		/* 07/27/98 */
-		if (pTmpScb->SCB_Srb == srbp) {
-			if (pTmpScb == pCurHcb->HCS_ActScb) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+		if (tmp->srb == srbp) {
+			if (tmp == host->active) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
-			} else if (pTmpScb == pCurHcb->HCS_FirstPend) {
-				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastPend = NULL;
+			} else if (tmp == host->first_pending) {
+				if ((host->first_pending = tmp->next) == NULL)
+					host->last_pending = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastPend)
-					pCurHcb->HCS_LastPend = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_pending)
+					host->last_pending = prev;
 			}
-			pTmpScb->SCB_HaStat = HOST_ABORTED;
-			pTmpScb->SCB_Flags |= SCF_DONE;
-			if (pTmpScb->SCB_Flags & SCF_POST)
-				(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+			tmp->hastat = HOST_ABORTED;
+			tmp->flags |= SCF_DONE;
+			if (tmp->flags & SCF_POST)
+				(*tmp->post) ((u8 *) host, (u8 *) tmp);
+			spin_unlock_irqrestore(&host->semaph_lock, flags);
 			return SCSI_ABORT_SUCCESS;
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
 
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-	while (pTmpScb != NULL) {
-
-		if (pTmpScb->SCB_Srb == srbp) {
-
-			if (pTmpScb == pCurHcb->HCS_ActScb) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	prev = tmp = host->first_busy;	/* Check Busy queue */
+	while (tmp != NULL) {
+		if (tmp->srb == srbp) {
+			if (tmp == host->active) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
-			} else if (pTmpScb->SCB_TagMsg == 0) {
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+			} else if (tmp->tagmsg == 0) {
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_BUSY;
 			} else {
-				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
-				if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-					if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-						pCurHcb->HCS_LastBusy = NULL;
+				host->act_tags[tmp->target]--;
+				if (tmp == host->first_busy) {
+					if ((host->first_busy = tmp->next) == NULL)
+						host->last_busy = NULL;
 				} else {
-					pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-					if (pTmpScb == pCurHcb->HCS_LastBusy)
-						pCurHcb->HCS_LastBusy = pPrevScb;
+					prev->next = tmp->next;
+					if (tmp == host->last_busy)
+						host->last_busy = prev;
 				}
-				pTmpScb->SCB_NxtScb = NULL;
+				tmp->next = NULL;
 
 
-				pTmpScb->SCB_HaStat = HOST_ABORTED;
-				pTmpScb->SCB_Flags |= SCF_DONE;
-				if (pTmpScb->SCB_Flags & SCF_POST)
-					(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
-				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+				tmp->hastat = HOST_ABORTED;
+				tmp->flags |= SCF_DONE;
+				if (tmp->flags & SCF_POST)
+					(*tmp->post) ((u8 *) host, (u8 *) tmp);
+				spin_unlock_irqrestore(&host->semaph_lock, flags);
 				return SCSI_ABORT_SUCCESS;
 			}
 		}
-		pPrevScb = pTmpScb;
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		prev = tmp;
+		tmp = tmp->next;
 	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return (SCSI_ABORT_NOT_RUNNING);
+	spin_unlock_irqrestore(&host->semaph_lock, flags);
+	return SCSI_ABORT_NOT_RUNNING;
 }
 
 /***************************************************************************/
-static int tul_bad_seq(HCS * pCurHcb)
+static int initio_bad_seq(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 
-	printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
+	printk("initio_bad_seg c=%d\n", host->index);
 
-	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
-		tul_unlink_busy_scb(pCurHcb, pCurScb);
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		pCurScb->SCB_TaStat = 0;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	if ((scb = host->active) != NULL) {
+		initio_unlink_busy_scb(host, scb);
+		scb->hastat = HOST_BAD_PHAS;
+		scb->tastat = 0;
+		initio_append_done_scb(host, scb);
 	}
-	tul_stop_bm(pCurHcb);
-
-	tul_reset_scsi(pCurHcb, 8);	/* 7/29/98 */
-
-	return (tul_post_scsi_rst(pCurHcb));
+	initio_stop_bm(host);
+	initio_reset_scsi(host, 8);	/* 7/29/98 */
+	return initio_post_scsi_rst(host);
 }
 
-#if 0
 
 /************************************************************************/
-static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
-			    unsigned int target, unsigned int ResetFlags)
+static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	ULONG flags;
-	SCB *pScb;
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+	unsigned long flags;
 
-	if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
+	scb->mode = 0;
 
-		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-			/* disable Jasmin SCSI Int        */
+	scb->sgidx = 0;
+	scb->sgmax = scb->sglen;
 
-        		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_lock_irqsave(&host->semaph_lock, flags);
 
-			tulip_main(pCurHcb);
-
-        		spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-			pCurHcb->HCS_Semaph = 1;
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-			return SCSI_RESET_SNOOZE;
-		}
-		pScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-		while (pScb != NULL) {
-			if (pScb->SCB_Srb == pSrb)
-				break;
-			pScb = pScb->SCB_NxtScb;
-		}
-		if (pScb == NULL) {
-			printk("Unable to Reset - No SCB Found\n");
-
-			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-			return SCSI_RESET_NOT_RUNNING;
-		}
-	}
-	if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
-		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-		return SCSI_RESET_NOT_RUNNING;
-	}
-	pScb->SCB_Opcode = BusDevRst;
-	pScb->SCB_Flags = SCF_POST;
-	pScb->SCB_Target = target;
-	pScb->SCB_Mode = 0;
-
-	pScb->SCB_Srb = NULL;
-	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
-		pScb->SCB_Srb = pSrb;
-	}
-	tul_push_pend_scb(pCurHcb, pScb);	/* push this SCB to Pending queue */
-
-	if (pCurHcb->HCS_Semaph == 1) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-		/* disable Jasmin SCSI Int        */
-		pCurHcb->HCS_Semaph = 0;
-
-        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-		tulip_main(pCurHcb);
-
-                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return SCSI_RESET_PENDING;
-}
-
-static int tul_reset_scsi_bus(HCS * pCurHcb)
-{
-	ULONG flags;
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-	pCurHcb->HCS_Semaph = 0;
-
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tul_stop_bm(pCurHcb);
-
-	tul_reset_scsi(pCurHcb, 2);	/* 7/29/98 */
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-	tul_post_scsi_rst(pCurHcb);
-
-        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tulip_main(pCurHcb);
-
-        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-	pCurHcb->HCS_Semaph = 1;
-	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
-}
-
-#endif  /*  0  */
-
-/************************************************************************/
-static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
-{
-	ULONG flags;
-
-	pCurScb->SCB_Mode = 0;
-
-	pCurScb->SCB_SGIdx = 0;
-	pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
-
-	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-	tul_append_pend_scb(pCurHcb, pCurScb);	/* Append this SCB to Pending queue */
+	initio_append_pend_scb(host, scb);	/* Append this SCB to Pending queue */
 
 /* VVVVV 07/21/98 */
-	if (pCurHcb->HCS_Semaph == 1) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-		/* disable Jasmin SCSI Int        */
-		pCurHcb->HCS_Semaph = 0;
+	if (host->semaph == 1) {
+		/* Disable Jasmin SCSI Int */
+		outb(0x1F, host->addr + TUL_Mask);
+		host->semaph = 0;
+		spin_unlock_irqrestore(&host->semaph_lock, flags);
 
-        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+		tulip_main(host);
 
-		tulip_main(pCurHcb);
-
-        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-
-		pCurHcb->HCS_Semaph = 1;
-		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+		spin_lock_irqsave(&host->semaph_lock, flags);
+		host->semaph = 1;
+		outb(0x0F, host->addr + TUL_Mask);
 	}
-	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+	spin_unlock_irqrestore(&host->semaph_lock, flags);
 	return;
 }
 
 /***************************************************************************/
-static int tul_isr(HCS * pCurHcb)
+static int initio_isr(struct initio_host * host)
 {
-	/* Enter critical section       */
-
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
-		if (pCurHcb->HCS_Semaph == 1) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {
+		if (host->semaph == 1) {
+			outb(0x1F, host->addr + TUL_Mask);
 			/* Disable Tulip SCSI Int */
-			pCurHcb->HCS_Semaph = 0;
+			host->semaph = 0;
 
-			tulip_main(pCurHcb);
+			tulip_main(host);
 
-			pCurHcb->HCS_Semaph = 1;
-			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-			return (1);
+			host->semaph = 1;
+			outb(0x0F, host->addr + TUL_Mask);
+			return 1;
 		}
 	}
-	return (0);
+	return 0;
 }
 
-/***************************************************************************/
-int tulip_main(HCS * pCurHcb)
+static int tulip_main(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 
 	for (;;) {
+		tulip_scsi(host);	/* Call tulip_scsi              */
 
-		tulip_scsi(pCurHcb);	/* Call tulip_scsi              */
-
-		while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {	/* find done entry */
-			if (pCurScb->SCB_TaStat == INI_QUEUE_FULL) {
-				pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
-				    pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
-				pCurScb->SCB_TaStat = 0;
-				tul_append_pend_scb(pCurHcb, pCurScb);
+		/* Walk the list of completed SCBs */
+		while ((scb = initio_find_done_scb(host)) != NULL) {	/* find done entry */
+			if (scb->tastat == INI_QUEUE_FULL) {
+				host->max_tags[scb->target] =
+				    host->act_tags[scb->target] - 1;
+				scb->tastat = 0;
+				initio_append_pend_scb(host, scb);
 				continue;
 			}
-			if (!(pCurScb->SCB_Mode & SCM_RSENS)) {		/* not in auto req. sense mode */
-				if (pCurScb->SCB_TaStat == 2) {
+			if (!(scb->mode & SCM_RSENS)) {		/* not in auto req. sense mode */
+				if (scb->tastat == 2) {
 
 					/* clr sync. nego flag */
 
-					if (pCurScb->SCB_Flags & SCF_SENSE) {
-						BYTE len;
-						len = pCurScb->SCB_SenseLen;
+					if (scb->flags & SCF_SENSE) {
+						u8 len;
+						len = scb->senselen;
 						if (len == 0)
 							len = 1;
-						pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
-						pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
-						pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
-/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
-						/* so, we won't report worng direction in xfer_data_in,
+						scb->buflen = scb->senselen;
+						scb->bufptr = scb->senseptr;
+						scb->flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
+						/* so, we won't report wrong direction in xfer_data_in,
 						   and won't report HOST_DO_DU in state_6 */
-						pCurScb->SCB_Mode = SCM_RSENS;
-						pCurScb->SCB_Ident &= 0xBF;	/* Disable Disconnect */
-						pCurScb->SCB_TagMsg = 0;
-						pCurScb->SCB_TaStat = 0;
-						pCurScb->SCB_CDBLen = 6;
-						pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
-						pCurScb->SCB_CDB[1] = 0;
-						pCurScb->SCB_CDB[2] = 0;
-						pCurScb->SCB_CDB[3] = 0;
-						pCurScb->SCB_CDB[4] = len;
-						pCurScb->SCB_CDB[5] = 0;
-						tul_push_pend_scb(pCurHcb, pCurScb);
+						scb->mode = SCM_RSENS;
+						scb->ident &= 0xBF;	/* Disable Disconnect */
+						scb->tagmsg = 0;
+						scb->tastat = 0;
+						scb->cdblen = 6;
+						scb->cdb[0] = SCSICMD_RequestSense;
+						scb->cdb[1] = 0;
+						scb->cdb[2] = 0;
+						scb->cdb[3] = 0;
+						scb->cdb[4] = len;
+						scb->cdb[5] = 0;
+						initio_push_pend_scb(host, scb);
 						break;
 					}
 				}
 			} else {	/* in request sense mode */
 
-				if (pCurScb->SCB_TaStat == 2) {		/* check contition status again after sending
+				if (scb->tastat == 2) {		/* check contition status again after sending
 									   requset sense cmd 0x3 */
-					pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+					scb->hastat = HOST_BAD_PHAS;
 				}
-				pCurScb->SCB_TaStat = 2;
+				scb->tastat = 2;
 			}
-			pCurScb->SCB_Flags |= SCF_DONE;
-			if (pCurScb->SCB_Flags & SCF_POST) {
-				(*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
+			scb->flags |= SCF_DONE;
+			if (scb->flags & SCF_POST) {
+				/* FIXME: only one post method and lose casts */
+				(*scb->post) ((u8 *) host, (u8 *) scb);
 			}
 		}		/* while */
-
 		/* find_active: */
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
+		if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)
 			continue;
-
-		if (pCurHcb->HCS_ActScb) {	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
+		if (host->active)	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
 			return 1;	/* return to OS, enable interrupt */
-		}
 		/* Check pending SCB            */
-		if (tul_find_first_pend_scb(pCurHcb) == NULL) {
+		if (initio_find_first_pend_scb(host) == NULL)
 			return 1;	/* return to OS, enable interrupt */
-		}
 	}			/* End of for loop */
 	/* statement won't reach here */
 }
 
-
-
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-
-/***************************************************************************/
-void tulip_scsi(HCS * pCurHcb)
+static void tulip_scsi(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
 
 	/* make sure to service interrupt asap */
-
-	if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
-
-		pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
-		pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
-		pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-		if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
-			int_tul_scsi_rst(pCurHcb);
+	if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {
+		host->phase = host->jsstatus0 & TSS_PH_MASK;
+		host->jsstatus1 = inb(host->addr + TUL_SStatus1);
+		host->jsint = inb(host->addr + TUL_SInt);
+		if (host->jsint & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
+			int_initio_scsi_rst(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
-			if (int_tul_resel(pCurHcb) == 0)
-				tul_next_state(pCurHcb);
+		if (host->jsint & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
+			if (int_initio_resel(host) == 0)
+				initio_next_state(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
-			int_tul_busfree(pCurHcb);
+		if (host->jsint & TSS_SEL_TIMEOUT) {
+			int_initio_busfree(host);
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-			int_tul_busfree(pCurHcb);	/* unexpected bus free or sel timeout */
+		if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */
+			int_initio_busfree(host);	/* unexpected bus free or sel timeout */
 			return;
 		}
-		if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
-			if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
-				tul_next_state(pCurHcb);
+		if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
+			if ((scb = host->active) != NULL)
+				initio_next_state(host);
 			return;
 		}
 	}
-	if (pCurHcb->HCS_ActScb != NULL)
+	if (host->active != NULL)
 		return;
 
-	if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
+	if ((scb = initio_find_first_pend_scb(host)) == NULL)
 		return;
 
 	/* program HBA's SCSI ID & target SCSI ID */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
-	     (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
-	if (pCurScb->SCB_Opcode == ExecSCSI) {
-		pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+	outb((host->scsi_id << 4) | (scb->target & 0x0F),
+		host->addr + TUL_SScsiId);
+	if (scb->opcode == ExecSCSI) {
+		active_tc = &host->targets[scb->target];
 
-		if (pCurScb->SCB_TagMsg)
-			pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
+		if (scb->tagmsg)
+			active_tc->drv_flags |= TCF_DRV_EN_TAG;
 		else
-			pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
+			active_tc->drv_flags &= ~TCF_DRV_EN_TAG;
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
-		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
-			tul_select_atn_stop(pCurHcb, pCurScb);
+		outb(active_tc->js_period, host->addr + TUL_SPeriod);
+		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
+			initio_select_atn_stop(host, scb);
 		} else {
-			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
-				tul_select_atn_stop(pCurHcb, pCurScb);
+			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
+				initio_select_atn_stop(host, scb);
 			} else {
-				if (pCurScb->SCB_TagMsg)
-					tul_select_atn3(pCurHcb, pCurScb);
+				if (scb->tagmsg)
+					initio_select_atn3(host, scb);
 				else
-					tul_select_atn(pCurHcb, pCurScb);
+					initio_select_atn(host, scb);
 			}
 		}
-		if (pCurScb->SCB_Flags & SCF_POLL) {
-			while (wait_tulip(pCurHcb) != -1) {
-				if (tul_next_state(pCurHcb) == -1)
+		if (scb->flags & SCF_POLL) {
+			while (wait_tulip(host) != -1) {
+				if (initio_next_state(host) == -1)
 					break;
 			}
 		}
-	} else if (pCurScb->SCB_Opcode == BusDevRst) {
-		tul_select_atn_stop(pCurHcb, pCurScb);
-		pCurScb->SCB_NxtStat = 8;
-		if (pCurScb->SCB_Flags & SCF_POLL) {
-			while (wait_tulip(pCurHcb) != -1) {
-				if (tul_next_state(pCurHcb) == -1)
+	} else if (scb->opcode == BusDevRst) {
+		initio_select_atn_stop(host, scb);
+		scb->next_state = 8;
+		if (scb->flags & SCF_POLL) {
+			while (wait_tulip(host) != -1) {
+				if (initio_next_state(host) == -1)
 					break;
 			}
 		}
-	} else if (pCurScb->SCB_Opcode == AbortCmd) {
-		if (tul_abort_srb(pCurHcb, pCurScb->SCB_Srb) != 0) {
-
-
-			tul_unlink_pend_scb(pCurHcb, pCurScb);
-
-			tul_release_scb(pCurHcb, pCurScb);
+	} else if (scb->opcode == AbortCmd) {
+		if (initio_abort_srb(host, scb->srb) != 0) {
+			initio_unlink_pend_scb(host, scb);
+			initio_release_scb(host, scb);
 		} else {
-			pCurScb->SCB_Opcode = BusDevRst;
-			tul_select_atn_stop(pCurHcb, pCurScb);
-			pCurScb->SCB_NxtStat = 8;
+			scb->opcode = BusDevRst;
+			initio_select_atn_stop(host, scb);
+			scb->next_state = 8;
 		}
-
-/* 08/03/98 */
 	} else {
-		tul_unlink_pend_scb(pCurHcb, pCurScb);
-		pCurScb->SCB_HaStat = 0x16;	/* bad command */
-		tul_append_done_scb(pCurHcb, pCurScb);
+		initio_unlink_pend_scb(host, scb);
+		scb->hastat = 0x16;	/* bad command */
+		initio_append_done_scb(host, scb);
 	}
 	return;
 }
 
+/**
+ *	initio_next_state		-	Next SCSI state
+ *	@host: InitIO host we are processing
+ *
+ *	Progress the active command block along the state machine
+ *	until we hit a state which we must wait for activity to occur.
+ *
+ *	Returns zero or a negative code.
+ */
 
-/***************************************************************************/
-int tul_next_state(HCS * pCurHcb)
+static int initio_next_state(struct initio_host * host)
 {
 	int next;
 
-	next = pCurHcb->HCS_ActScb->SCB_NxtStat;
+	next = host->active->next_state;
 	for (;;) {
 		switch (next) {
 		case 1:
-			next = tul_state_1(pCurHcb);
+			next = initio_state_1(host);
 			break;
 		case 2:
-			next = tul_state_2(pCurHcb);
+			next = initio_state_2(host);
 			break;
 		case 3:
-			next = tul_state_3(pCurHcb);
+			next = initio_state_3(host);
 			break;
 		case 4:
-			next = tul_state_4(pCurHcb);
+			next = initio_state_4(host);
 			break;
 		case 5:
-			next = tul_state_5(pCurHcb);
+			next = initio_state_5(host);
 			break;
 		case 6:
-			next = tul_state_6(pCurHcb);
+			next = initio_state_6(host);
 			break;
 		case 7:
-			next = tul_state_7(pCurHcb);
+			next = initio_state_7(host);
 			break;
 		case 8:
-			return (tul_bus_device_reset(pCurHcb));
+			return initio_bus_device_reset(host);
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 		if (next <= 0)
 			return next;
@@ -1554,338 +1314,363 @@
 }
 
 
-/***************************************************************************/
-/* sTate after selection with attention & stop */
-int tul_state_1(HCS * pCurHcb)
+/**
+ *	initio_state_1		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	Perform SCSI state processing for Select/Attention/Stop
+ */
+
+static int initio_state_1(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 #if DEBUG_STATE
 	printk("-s1-");
 #endif
 
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_append_busy_scb(pCurHcb, pCurScb);
+	/* Move the SCB from pending to busy */
+	initio_unlink_pend_scb(host, scb);
+	initio_append_busy_scb(host, scb);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig );
 	/* ATN on */
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
+	if (host->phase == MSG_OUT) {
+		outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+		outb(scb->ident, host->addr + TUL_SFifo);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
-
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-
-		if (pCurScb->SCB_TagMsg) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+		if (scb->tagmsg) {
+			outb(scb->tagmsg, host->addr + TUL_SFifo);
+			outb(scb->tagid, host->addr + TUL_SFifo);
 		}
-		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
-
-			pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);	/* Extended msg length */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* Sync request */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* Start from 16 bits */
-		} else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
-
-			pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* extended msg length */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
+		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
+			active_tc->flags |= TCF_WDTR_DONE;
+			outb(MSG_EXTEND, host->addr + TUL_SFifo);
+			outb(2, host->addr + TUL_SFifo);	/* Extended msg length */
+			outb(3, host->addr + TUL_SFifo);	/* Sync request */
+			outb(1, host->addr + TUL_SFifo);	/* Start from 16 bits */
+		} else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
+			active_tc->flags |= TCF_SYNC_DONE;
+			outb(MSG_EXTEND, host->addr + TUL_SFifo);
+			outb(3, host->addr + TUL_SFifo);	/* extended msg length */
+			outb(1, host->addr + TUL_SFifo);	/* sync request */
+			outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+			outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */
 		}
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		if (wait_tulip(pCurHcb) == -1)
-			return (-1);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-	return (3);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+	/* Into before CDB xfer */
+	return 3;
 }
 
 
-/***************************************************************************/
-/* state after selection with attention */
-/* state after selection with attention3 */
-int tul_state_2(HCS * pCurHcb)
+/**
+ *	initio_state_2		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ * state after selection with attention
+ * state after selection with attention3
+ */
+
+static int initio_state_2(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 #if DEBUG_STATE
 	printk("-s2-");
 #endif
 
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_append_busy_scb(pCurHcb, pCurScb);
+	initio_unlink_pend_scb(host, scb);
+	initio_append_busy_scb(host, scb);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig);
 
-	if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
-		return (4);
-	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-	return (3);
+	if (host->jsstatus1 & TSS_CMD_PH_CMP)
+		return 4;
+
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+	/* Into before CDB xfer */
+	return 3;
 }
 
-/***************************************************************************/
-/* state before CDB xfer is done */
-int tul_state_3(HCS * pCurHcb)
+/**
+ *	initio_state_3		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ * state before CDB xfer is done
+ */
+
+static int initio_state_3(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 	int i;
 
 #if DEBUG_STATE
 	printk("-s3-");
 #endif
 	for (;;) {
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 		case CMD_OUT:	/* Command out phase            */
-			for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1)
-				return (-1);
-			if (pCurHcb->HCS_Phase == CMD_OUT) {
-				return (tul_bad_seq(pCurHcb));
-			}
-			return (4);
+			for (i = 0; i < (int) scb->cdblen; i++)
+				outb(scb->cdb[i], host->addr + TUL_SFifo);
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
+			if (host->phase == CMD_OUT)
+				return initio_bad_seq(host);
+			return 4;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 3;
-			if (tul_msgin(pCurHcb) == -1)
-				return (-1);
+			scb->next_state = 3;
+			if (initio_msgin(host) == -1)
+				return -1;
 			break;
 
 		case STATUS_IN:	/* Status phase                 */
-			if (tul_status_msg(pCurHcb) == -1)
-				return (-1);
+			if (initio_status_msg(host) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
-
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
-
+			if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+				outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
 			} else {
-				pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+				active_tc->flags |= TCF_SYNC_DONE;
 
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* ext. msg len */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
+				outb(MSG_EXTEND, host->addr + TUL_SFifo);
+				outb(3, host->addr + TUL_SFifo);	/* ext. msg len */
+				outb(1, host->addr + TUL_SFifo);	/* sync request */
+				outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+				outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
+				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+				outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);
 
 			}
 			break;
-
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
+/**
+ *	initio_state_4		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	SCSI state machine. State 4
+ */
 
-/***************************************************************************/
-int tul_state_4(HCS * pCurHcb)
+static int initio_state_4(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
 #if DEBUG_STATE
 	printk("-s4-");
 #endif
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
-		return (6);	/* Go to state 6                */
+	if ((scb->flags & SCF_DIR) == SCF_NO_XF) {
+		return 6;	/* Go to state 6 (After data) */
 	}
 	for (;;) {
-		if (pCurScb->SCB_BufLen == 0)
-			return (6);	/* Go to state 6                */
+		if (scb->buflen == 0)
+			return 6;
 
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 
 		case STATUS_IN:	/* Status phase                 */
-			if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {	/* if direction bit set then report data underrun */
-				pCurScb->SCB_HaStat = HOST_DO_DU;
-			}
-			if ((tul_status_msg(pCurHcb)) == -1)
-				return (-1);
+			if ((scb->flags & SCF_DIR) != 0)	/* if direction bit set then report data underrun */
+				scb->hastat = HOST_DO_DU;
+			if ((initio_status_msg(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 0x4;
-			if (tul_msgin(pCurHcb) == -1)
-				return (-1);
+			scb->next_state = 0x4;
+			if (initio_msgin(host) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-				pCurScb->SCB_BufLen = 0;
-				pCurScb->SCB_HaStat = HOST_DO_DU;
-				if (tul_msgout_ide(pCurHcb) == -1)
-					return (-1);
-				return (6);	/* Go to state 6                */
+			if (host->jsstatus0 & TSS_PAR_ERROR) {
+				scb->buflen = 0;
+				scb->hastat = HOST_DO_DU;
+				if (initio_msgout_ide(host) == -1)
+					return -1;
+				return 6;
 			} else {
-				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-				if (wait_tulip(pCurHcb) == -1)
-					return (-1);
+				outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+				if (wait_tulip(host) == -1)
+					return -1;
 			}
 			break;
 
 		case DATA_IN:	/* Data in phase                */
-			return (tul_xfer_data_in(pCurHcb));
+			return initio_xfer_data_in(host);
 
 		case DATA_OUT:	/* Data out phase               */
-			return (tul_xfer_data_out(pCurHcb));
+			return initio_xfer_data_out(host);
 
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
 
-/***************************************************************************/
-/* state after dma xfer done or phase change before xfer done */
-int tul_state_5(HCS * pCurHcb)
+/**
+ *	initio_state_5		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	State after dma xfer done or phase change before xfer done
+ */
+
+static int initio_state_5(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 	long cnt, xcnt;		/* cannot use unsigned !! code: if (xcnt < 0) */
 
 #if DEBUG_STATE
 	printk("-s5-");
 #endif
-/*------ get remaining count -------*/
+	/*------ get remaining count -------*/
+	cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;
 
-	cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
-
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
+	if (inb(host->addr + TUL_XCmd) & 0x20) {
 		/* ----------------------- DATA_IN ----------------------------- */
 		/* check scsi parity error */
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-			pCurScb->SCB_HaStat = HOST_DO_DU;
-		}
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
+		if (host->jsstatus0 & TSS_PAR_ERROR)
+			scb->hastat = HOST_DO_DU;
+		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
 			/* tell Hardware  scsi xfer has been terminated */
-			TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
+			outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);
 			/* wait until DMA xfer not pending */
-			while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
+			while (inb(host->addr + TUL_XStatus) & XPEND)
+				cpu_relax();
 		}
 	} else {
-/*-------- DATA OUT -----------*/
-		if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
-			if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
-				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
+		/*-------- DATA OUT -----------*/
+		if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {
+			if (host->active_tc->js_period & TSC_WIDE_SCSI)
+				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;
 			else
-				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
+				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);
 		}
-		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
-			TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
+		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+			outb(TAX_X_ABT, host->addr + TUL_XCmd);
 			/* wait Abort DMA xfer done */
-			while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+			while ((inb(host->addr + TUL_Int) & XABT) == 0)
+				cpu_relax();
 		}
-		if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1) {
-				return (-1);
-			}
+		if ((cnt == 1) && (host->phase == DATA_OUT)) {
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
 			cnt = 0;
 		} else {
-			if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+			if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)
+				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 		}
 	}
-
 	if (cnt == 0) {
-		pCurScb->SCB_BufLen = 0;
-		return (6);	/* Go to state 6                */
+		scb->buflen = 0;
+		return 6;	/* After Data */
 	}
 	/* Update active data pointer */
-	xcnt = (long) pCurScb->SCB_BufLen - cnt;	/* xcnt== bytes already xferred */
-	pCurScb->SCB_BufLen = (U32) cnt;	/* cnt == bytes left to be xferred */
-	if (pCurScb->SCB_Flags & SCF_SG) {
-		register SG *sgp;
-		ULONG i;
+	xcnt = (long) scb->buflen - cnt;	/* xcnt== bytes already xferred */
+	scb->buflen = (u32) cnt;		/* cnt == bytes left to be xferred */
+	if (scb->flags & SCF_SG) {
+		struct sg_entry *sgp;
+		unsigned long i;
 
-		sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
-		for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
-			xcnt -= (long) sgp->SG_Len;
+		sgp = &scb->sglist[scb->sgidx];
+		for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {
+			xcnt -= (long) sgp->len;
 			if (xcnt < 0) {		/* this sgp xfer half done */
-				xcnt += (long) sgp->SG_Len;	/* xcnt == bytes xferred in this sgp */
-				sgp->SG_Ptr += (U32) xcnt;	/* new ptr to be xfer */
-				sgp->SG_Len -= (U32) xcnt;	/* new len to be xfer */
-				pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
+				xcnt += (long) sgp->len;	/* xcnt == bytes xferred in this sgp */
+				sgp->data += (u32) xcnt;	/* new ptr to be xfer */
+				sgp->len -= (u32) xcnt;	/* new len to be xfer */
+				scb->bufptr += ((u32) (i - scb->sgidx) << 3);
 				/* new SG table ptr */
-				pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
+				scb->sglen = (u8) (scb->sgmax - i);
 				/* new SG table len */
-				pCurScb->SCB_SGIdx = (WORD) i;
+				scb->sgidx = (u16) i;
 				/* for next disc and come in this loop */
-				return (4);	/* Go to state 4                */
+				return 4;	/* Go to state 4                */
 			}
 			/* else (xcnt >= 0 , i.e. this sgp already xferred */
 		}		/* for */
-		return (6);	/* Go to state 6                */
+		return 6;	/* Go to state 6                */
 	} else {
-		pCurScb->SCB_BufPtr += (U32) xcnt;
+		scb->bufptr += (u32) xcnt;
 	}
-	return (4);		/* Go to state 4                */
+	return 4;		/* Go to state 4                */
 }
 
-/***************************************************************************/
-/* state after Data phase */
-int tul_state_6(HCS * pCurHcb)
+/**
+ *	initio_state_6		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ *	State after Data phase
+ */
+
+static int initio_state_6(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
 #if DEBUG_STATE
 	printk("-s6-");
 #endif
 	for (;;) {
-		switch (pCurHcb->HCS_Phase) {
+		switch (host->phase) {
 		case STATUS_IN:	/* Status phase                 */
-			if ((tul_status_msg(pCurHcb)) == -1)
-				return (-1);
+			if ((initio_status_msg(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_IN:	/* Message in phase             */
-			pCurScb->SCB_NxtStat = 6;
-			if ((tul_msgin(pCurHcb)) == -1)
-				return (-1);
+			scb->next_state = 6;
+			if ((initio_msgin(host)) == -1)
+				return -1;
 			break;
 
 		case MSG_OUT:	/* Message out phase            */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			if (wait_tulip(pCurHcb) == -1)
-				return (-1);
+			outb(MSG_NOP, host->addr + TUL_SFifo);		/* msg nop */
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			if (wait_tulip(host) == -1)
+				return -1;
 			break;
 
 		case DATA_IN:	/* Data in phase                */
-			return (tul_xpad_in(pCurHcb));
+			return initio_xpad_in(host);
 
 		case DATA_OUT:	/* Data out phase               */
-			return (tul_xpad_out(pCurHcb));
+			return initio_xpad_out(host);
 
 		default:
-			return (tul_bad_seq(pCurHcb));
+			return initio_bad_seq(host);
 		}
 	}
 }
 
-/***************************************************************************/
-int tul_state_7(HCS * pCurHcb)
+/**
+ *	initio_state_7		-	SCSI state machine
+ *	@host: InitIO host we are controlling
+ *
+ */
+
+int initio_state_7(struct initio_host * host)
 {
 	int cnt, i;
 
@@ -1893,1139 +1678,1029 @@
 	printk("-s7-");
 #endif
 	/* flush SCSI FIFO */
-	cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
+	cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;
 	if (cnt) {
 		for (i = 0; i < cnt; i++)
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+			inb(host->addr + TUL_SFifo);
 	}
-	switch (pCurHcb->HCS_Phase) {
+	switch (host->phase) {
 	case DATA_IN:		/* Data in phase                */
 	case DATA_OUT:		/* Data out phase               */
-		return (tul_bad_seq(pCurHcb));
+		return initio_bad_seq(host);
 	default:
-		return (6);	/* Go to state 6                */
+		return 6;	/* Go to state 6                */
 	}
 }
 
-/***************************************************************************/
-int tul_xfer_data_in(HCS * pCurHcb)
+/**
+ *	initio_xfer_data_in	-	Commence data input
+ *	@host: InitIO host in use
+ *
+ *	Commence a block of data transfer. The transfer itself will
+ *	be managed by the controller and we will get a completion (or
+ *	failure) interrupt.
+ */
+static int initio_xfer_data_in(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
-		return (6);	/* wrong direction */
-	}
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+	if ((scb->flags & SCF_DIR) == SCF_DOUT)
+		return 6;	/* wrong direction */
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);	/* 7/25/95 */
+	outl(scb->buflen, host->addr + TUL_SCnt0);
+	outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);	/* 7/25/95 */
 
-	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
+	if (scb->flags & SCF_SG) {	/* S/G xfer */
+		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_SG_IN, host->addr + TUL_XCmd);
 	} else {
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
+		outl(scb->buflen, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_X_IN, host->addr + TUL_XCmd);
 	}
-	pCurScb->SCB_NxtStat = 0x5;
-	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+	scb->next_state = 0x5;
+	return 0;		/* return to OS, wait xfer done , let jas_isr come in */
 }
 
+/**
+ *	initio_xfer_data_out	-	Commence data output
+ *	@host: InitIO host in use
+ *
+ *	Commence a block of data transfer. The transfer itself will
+ *	be managed by the controller and we will get a completion (or
+ *	failure) interrupt.
+ */
 
-/***************************************************************************/
-int tul_xfer_data_out(HCS * pCurHcb)
+static int initio_xfer_data_out(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
-		return (6);	/* wrong direction */
-	}
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
+	if ((scb->flags & SCF_DIR) == SCF_DIN)
+		return 6;	/* wrong direction */
 
-	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
+	outl(scb->buflen, host->addr + TUL_SCnt0);
+	outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);
+
+	if (scb->flags & SCF_SG) {	/* S/G xfer */
+		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_SG_OUT, host->addr + TUL_XCmd);
 	} else {
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
+		outl(scb->buflen, host->addr + TUL_XCntH);
+		outl(scb->bufptr, host->addr + TUL_XAddH);
+		outb(TAX_X_OUT, host->addr + TUL_XCmd);
 	}
 
-	pCurScb->SCB_NxtStat = 0x5;
-	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+	scb->next_state = 0x5;
+	return 0;		/* return to OS, wait xfer done , let jas_isr come in */
 }
 
-
-/***************************************************************************/
-int tul_xpad_in(HCS * pCurHcb)
+int initio_xpad_in(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
-		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
-	}
+	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+		scb->hastat = HOST_DO_DU;	/* over run             */
 	for (;;) {
-		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		if (active_tc->js_period & TSC_WIDE_SCSI)
+			outl(2, host->addr + TUL_SCnt0);
 		else
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+			outl(1, host->addr + TUL_SCnt0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1) {
-			return (-1);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		if (host->phase != DATA_IN) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			return 6;
 		}
-		if (pCurHcb->HCS_Phase != DATA_IN) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			return (6);
-		}
-		TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+		inb(host->addr + TUL_SFifo);
 	}
 }
 
-int tul_xpad_out(HCS * pCurHcb)
+int initio_xpad_out(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
 
-	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
-		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
-	}
+	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+		scb->hastat = HOST_DO_DU;	/* over run             */
 	for (;;) {
-		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		if (active_tc->js_period & TSC_WIDE_SCSI)
+			outl(2, host->addr + TUL_SCnt0);
 		else
-			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+			outl(1, host->addr + TUL_SCnt0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		if ((wait_tulip(pCurHcb)) == -1) {
-			return (-1);
-		}
-		if (pCurHcb->HCS_Phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			return (6);
+		outb(0, host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		if ((wait_tulip(host)) == -1)
+			return -1;
+		if (host->phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			return 6;
 		}
 	}
 }
 
-
-/***************************************************************************/
-int tul_status_msg(HCS * pCurHcb)
+int initio_status_msg(struct initio_host * host)
 {				/* status & MSG_IN */
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	BYTE msg;
+	struct scsi_ctrl_blk *scb = host->active;
+	u8 msg;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
-	if ((wait_tulip(pCurHcb)) == -1) {
-		return (-1);
-	}
+	outb(TSC_CMD_COMP, host->addr + TUL_SCmd);
+	if (wait_tulip(host) == -1)
+		return -1;
+
 	/* get status */
-	pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	scb->tastat = inb(host->addr + TUL_SFifo);
 
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
-		} else {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
-		}
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_OUT) {
+		if (host->jsstatus0 & TSS_PAR_ERROR)
+			outb(MSG_PARITY, host->addr + TUL_SFifo);
+		else
+			outb(MSG_NOP, host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	if (pCurHcb->HCS_Phase == MSG_IN) {
-		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
-			if ((tul_msgin_accept(pCurHcb)) == -1)
-				return (-1);
-			if (pCurHcb->HCS_Phase != MSG_OUT)
-				return (tul_bad_seq(pCurHcb));
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-			return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_IN) {
+		msg = inb(host->addr + TUL_SFifo);
+		if (host->jsstatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
+			if ((initio_msgin_accept(host)) == -1)
+				return -1;
+			if (host->phase != MSG_OUT)
+				return initio_bad_seq(host);
+			outb(MSG_PARITY, host->addr + TUL_SFifo);
+			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+			return wait_tulip(host);
 		}
 		if (msg == 0) {	/* Command complete             */
 
-			if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {	/* No link support              */
-				return (tul_bad_seq(pCurHcb));
-			}
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-			return tul_wait_done_disc(pCurHcb);
+			if ((scb->tastat & 0x18) == 0x10)	/* No link support              */
+				return initio_bad_seq(host);
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_done_disc(host);
 
 		}
-		if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
-			if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
-				return (tul_msgin_accept(pCurHcb));
+		if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) {
+			if ((scb->tastat & 0x18) == 0x10)
+				return initio_msgin_accept(host);
 		}
 	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
 
-/***************************************************************************/
 /* scsi bus free */
-int int_tul_busfree(HCS * pCurHcb)
+int int_initio_busfree(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	struct scsi_ctrl_blk *scb = host->active;
 
-	if (pCurScb != NULL) {
-		if (pCurScb->SCB_Status & SCB_SELECT) {		/* selection timeout */
-			tul_unlink_pend_scb(pCurHcb, pCurScb);
-			pCurScb->SCB_HaStat = HOST_SEL_TOUT;
-			tul_append_done_scb(pCurHcb, pCurScb);
+	if (scb != NULL) {
+		if (scb->status & SCB_SELECT) {		/* selection timeout */
+			initio_unlink_pend_scb(host, scb);
+			scb->hastat = HOST_SEL_TOUT;
+			initio_append_done_scb(host, scb);
 		} else {	/* Unexpected bus free          */
-			tul_unlink_busy_scb(pCurHcb, pCurScb);
-			pCurScb->SCB_HaStat = HOST_BUS_FREE;
-			tul_append_done_scb(pCurHcb, pCurScb);
+			initio_unlink_busy_scb(host, scb);
+			scb->hastat = HOST_BUS_FREE;
+			initio_append_done_scb(host, scb);
 		}
-		pCurHcb->HCS_ActScb = NULL;
-		pCurHcb->HCS_ActTcs = NULL;
+		host->active = NULL;
+		host->active_tc = NULL;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-	return (-1);
+	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO  */
+	outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect       */
+	return -1;
 }
 
 
-/***************************************************************************/
-/* scsi bus reset */
-static int int_tul_scsi_rst(HCS * pCurHcb)
+/**
+ *	int_initio_scsi_rst	-	SCSI reset occurred
+ *	@host: Host seeing the reset
+ *
+ *	A SCSI bus reset has occurred. Clean up any pending transfer
+ *	the hardware is doing by DMA and then abort all active and
+ *	disconnected commands. The mid layer should sort the rest out
+ *	for us
+ */
+
+static int int_initio_scsi_rst(struct initio_host * host)
 {
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 	int i;
 
 	/* if DMA xfer is pending, abort DMA xfer */
-	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+	if (inb(host->addr + TUL_XStatus) & 0x01) {
+		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
 		/* wait Abort DMA xfer done */
-		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		while ((inb(host->addr + TUL_Int) & 0x04) == 0)
+			cpu_relax();
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 	}
 	/* Abort all active & disconnected scb */
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
+	host->active = NULL;
+	host->active_tc = NULL;
 
 	/* clr sync nego. done flag */
-	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-	}
-	return (-1);
+	for (i = 0; i < host->max_tar; i++)
+		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	return -1;
 }
 
+/**
+ *	int_initio_scsi_resel	-	Reselection occured
+ *	@host: InitIO host adapter
+ *
+ *	A SCSI reselection event has been signalled and the interrupt
+ *	is now being processed. Work out which command block needs attention
+ *	and continue processing that command.
+ */
 
-/***************************************************************************/
-/* scsi reselection */
-int int_tul_resel(HCS * pCurHcb)
+int int_initio_resel(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
-	BYTE tag, msg = 0;
-	BYTE tar, lun;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
+	u8 tag, msg = 0;
+	u8 tar, lun;
 
-	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
-		if (pCurScb->SCB_Status & SCB_SELECT) {		/* if waiting for selection complete */
-			pCurScb->SCB_Status &= ~SCB_SELECT;
-		}
-		pCurHcb->HCS_ActScb = NULL;
+	if ((scb = host->active) != NULL) {
+		/* FIXME: Why check and not just clear ? */
+		if (scb->status & SCB_SELECT)		/* if waiting for selection complete */
+			scb->status &= ~SCB_SELECT;
+		host->active = NULL;
 	}
 	/* --------- get target id---------------------- */
-	tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
+	tar = inb(host->addr + TUL_SBusId);
 	/* ------ get LUN from Identify message----------- */
-	lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
+	lun = inb(host->addr + TUL_SIdent) & 0x0F;
 	/* 07/22/98 from 0x1F -> 0x0F */
-	pCurTcb = &pCurHcb->HCS_Tcs[tar];
-	pCurHcb->HCS_ActTcs = pCurTcb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
-
+	active_tc = &host->targets[tar];
+	host->active_tc = active_tc;
+	outb(active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(active_tc->js_period, host->addr + TUL_SPeriod);
 
 	/* ------------- tag queueing ? ------------------- */
-	if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
-		if (pCurHcb->HCS_Phase != MSG_IN)
+	if (active_tc->drv_flags & TCF_DRV_EN_TAG) {
+		if ((initio_msgin_accept(host)) == -1)
+			return -1;
+		if (host->phase != MSG_IN)
 			goto no_tag;
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag Message    */
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		msg = inb(host->addr + TUL_SFifo);	/* Read Tag Message    */
 
-		if ((msg < MSG_STAG) || (msg > MSG_OTAG))	/* Is simple Tag      */
+		if (msg < MSG_STAG || msg > MSG_OTAG)		/* Is simple Tag      */
 			goto no_tag;
 
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
+		if (initio_msgin_accept(host) == -1)
+			return -1;
 
-		if (pCurHcb->HCS_Phase != MSG_IN)
+		if (host->phase != MSG_IN)
 			goto no_tag;
 
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-		tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag ID       */
-		pCurScb = pCurHcb->HCS_Scb + tag;
-		if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
-			return tul_msgout_abort_tag(pCurHcb);
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		tag = inb(host->addr + TUL_SFifo);	/* Read Tag ID       */
+		scb = host->scb + tag;
+		if (scb->target != tar || scb->lun != lun) {
+			return initio_msgout_abort_tag(host);
 		}
-		if (pCurScb->SCB_Status != SCB_BUSY) {	/* 03/24/95             */
-			return tul_msgout_abort_tag(pCurHcb);
+		if (scb->status != SCB_BUSY) {	/* 03/24/95             */
+			return initio_msgout_abort_tag(host);
 		}
-		pCurHcb->HCS_ActScb = pCurScb;
-		if ((tul_msgin_accept(pCurHcb)) == -1)
-			return (-1);
+		host->active = scb;
+		if ((initio_msgin_accept(host)) == -1)
+			return -1;
 	} else {		/* No tag               */
 	      no_tag:
-		if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
-			return tul_msgout_abort_targ(pCurHcb);
+		if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {
+			return initio_msgout_abort_targ(host);
 		}
-		pCurHcb->HCS_ActScb = pCurScb;
-		if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
-			if ((tul_msgin_accept(pCurHcb)) == -1)
-				return (-1);
+		host->active = scb;
+		if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {
+			if ((initio_msgin_accept(host)) == -1)
+				return -1;
 		}
 	}
 	return 0;
 }
 
+/**
+ *	int_initio_bad_seq		-	out of phase
+ *	@host: InitIO host flagging event
+ *
+ *	We have ended up out of phase somehow. Reset the host controller
+ *	and throw all our toys out of the pram. Let the midlayer clean up
+ */
 
-/***************************************************************************/
-static int int_tul_bad_seq(HCS * pCurHcb)
+static int int_initio_bad_seq(struct initio_host * host)
 {				/* target wrong phase           */
-	SCB *pCurScb;
+	struct scsi_ctrl_blk *scb;
 	int i;
 
-	tul_reset_scsi(pCurHcb, 10);
+	initio_reset_scsi(host, 10);
 
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
-	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-	}
-	return (-1);
+	for (i = 0; i < host->max_tar; i++)
+		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	return -1;
 }
 
 
-/***************************************************************************/
-int tul_msgout_abort_targ(HCS * pCurHcb)
+/**
+ *	initio_msgout_abort_targ		-	abort a tag
+ *	@host: InitIO host
+ *
+ *	Abort when the target/lun does not match or when our SCB is not
+ *	busy. Used by untagged commands.
+ */
+
+static int initio_msgout_abort_targ(struct initio_host * host)
 {
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-	if (tul_msgin_accept(pCurHcb) == -1)
-		return (-1);
-	if (pCurHcb->HCS_Phase != MSG_OUT)
-		return (tul_bad_seq(pCurHcb));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+	if (initio_msgin_accept(host) == -1)
+		return -1;
+	if (host->phase != MSG_OUT)
+		return initio_bad_seq(host);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	outb(MSG_ABORT, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
 
-	return tul_wait_disc(pCurHcb);
+	return initio_wait_disc(host);
 }
 
-/***************************************************************************/
-int tul_msgout_abort_tag(HCS * pCurHcb)
+/**
+ *	initio_msgout_abort_tag		-	abort a tag
+ *	@host: InitIO host
+ *
+ *	Abort when the target/lun does not match or when our SCB is not
+ *	busy. Used for tagged commands.
+ */
+
+static int initio_msgout_abort_tag(struct initio_host * host)
 {
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-	if (tul_msgin_accept(pCurHcb) == -1)
-		return (-1);
-	if (pCurHcb->HCS_Phase != MSG_OUT)
-		return (tul_bad_seq(pCurHcb));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+	if (initio_msgin_accept(host) == -1)
+		return -1;
+	if (host->phase != MSG_OUT)
+		return initio_bad_seq(host);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	outb(MSG_ABORT_TAG, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
 
-	return tul_wait_disc(pCurHcb);
+	return initio_wait_disc(host);
 
 }
 
-/***************************************************************************/
-int tul_msgin(HCS * pCurHcb)
+/**
+ *	initio_msgin		-	Message in
+ *	@host: InitIO Host
+ *
+ *	Process incoming message
+ */
+static int initio_msgin(struct initio_host * host)
 {
-	TCS *pCurTcb;
+	struct target_control *active_tc;
 
 	for (;;) {
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
 
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if ((wait_tulip(pCurHcb)) == -1)
-			return (-1);
-
-		switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
+		switch (inb(host->addr + TUL_SFifo)) {
 		case MSG_DISC:	/* Disconnect msg */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-
-			return tul_wait_disc(pCurHcb);
-
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_disc(host);
 		case MSG_SDP:
 		case MSG_RESTORE:
 		case MSG_NOP:
-			tul_msgin_accept(pCurHcb);
+			initio_msgin_accept(host);
 			break;
-
 		case MSG_REJ:	/* Clear ATN first              */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
-			       (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
-			pCurTcb = pCurHcb->HCS_ActTcs;
-			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync nego */
-				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-			}
-			tul_msgin_accept(pCurHcb);
+			outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),
+				host->addr + TUL_SSignal);
+			active_tc = host->active_tc;
+			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)	/* do sync nego */
+				outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),
+					host->addr + TUL_SSignal);
+			initio_msgin_accept(host);
 			break;
-
 		case MSG_EXTEND:	/* extended msg */
-			tul_msgin_extend(pCurHcb);
+			initio_msgin_extend(host);
 			break;
-
 		case MSG_IGNOREWIDE:
-			tul_msgin_accept(pCurHcb);
+			initio_msgin_accept(host);
 			break;
-
-			/* get */
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-			if (wait_tulip(pCurHcb) == -1)
-				return -1;
-
-			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);	/* put pad  */
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get IGNORE field */
-			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get pad */
-
-			tul_msgin_accept(pCurHcb);
-			break;
-
 		case MSG_COMP:
-			{
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-				return tul_wait_done_disc(pCurHcb);
-			}
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+			return initio_wait_done_disc(host);
 		default:
-			tul_msgout_reject(pCurHcb);
+			initio_msgout_reject(host);
 			break;
 		}
-		if (pCurHcb->HCS_Phase != MSG_IN)
-			return (pCurHcb->HCS_Phase);
+		if (host->phase != MSG_IN)
+			return host->phase;
 	}
 	/* statement won't reach here */
 }
 
-
-
-
-/***************************************************************************/
-int tul_msgout_reject(HCS * pCurHcb)
+static int initio_msgout_reject(struct initio_host * host)
 {
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	if (initio_msgin_accept(host) == -1)
+		return -1;
 
-	if ((tul_msgin_accept(pCurHcb)) == -1)
-		return (-1);
-
-	if (pCurHcb->HCS_Phase == MSG_OUT) {
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);		/* Msg reject           */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+	if (host->phase == MSG_OUT) {
+		outb(MSG_REJ, host->addr + TUL_SFifo);		/* Msg reject           */
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	return (pCurHcb->HCS_Phase);
+	return host->phase;
 }
 
-
-
-/***************************************************************************/
-int tul_msgout_ide(HCS * pCurHcb)
+static int initio_msgout_ide(struct initio_host * host)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);		/* Initiator Detected Error */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-	return (wait_tulip(pCurHcb));
+	outb(MSG_IDE, host->addr + TUL_SFifo);		/* Initiator Detected Error */
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-
-/***************************************************************************/
-int tul_msgin_extend(HCS * pCurHcb)
+static int initio_msgin_extend(struct initio_host * host)
 {
-	BYTE len, idx;
+	u8 len, idx;
 
-	if (tul_msgin_accept(pCurHcb) != MSG_IN)
-		return (pCurHcb->HCS_Phase);
+	if (initio_msgin_accept(host) != MSG_IN)
+		return host->phase;
 
 	/* Get extended msg length      */
-	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-	if (wait_tulip(pCurHcb) == -1)
-		return (-1);
+	outl(1, host->addr + TUL_SCnt0);
+	outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+	if (wait_tulip(host) == -1)
+		return -1;
 
-	len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-	pCurHcb->HCS_Msg[0] = len;
+	len = inb(host->addr + TUL_SFifo);
+	host->msg[0] = len;
 	for (idx = 1; len != 0; len--) {
 
-		if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
-			return (pCurHcb->HCS_Phase);
-		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
-		if (wait_tulip(pCurHcb) == -1)
-			return (-1);
-		pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+		if ((initio_msgin_accept(host)) != MSG_IN)
+			return host->phase;
+		outl(1, host->addr + TUL_SCnt0);
+		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+		if (wait_tulip(host) == -1)
+			return -1;
+		host->msg[idx++] = inb(host->addr + TUL_SFifo);
 	}
-	if (pCurHcb->HCS_Msg[1] == 1) {		/* if it's synchronous data transfer request */
-		if (pCurHcb->HCS_Msg[0] != 3)	/* if length is not right */
-			return (tul_msgout_reject(pCurHcb));
-		if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
-			pCurHcb->HCS_Msg[3] = 0;
+	if (host->msg[1] == 1) {		/* if it's synchronous data transfer request */
+		u8 r;
+		if (host->msg[0] != 3)	/* if length is not right */
+			return initio_msgout_reject(host);
+		if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
+			host->msg[3] = 0;
 		} else {
-			if ((tul_msgin_sync(pCurHcb) == 0) &&
-			    (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
-				tul_sync_done(pCurHcb);
-				return (tul_msgin_accept(pCurHcb));
+			if (initio_msgin_sync(host) == 0 &&
+			    (host->active_tc->flags & TCF_SYNC_DONE)) {
+				initio_sync_done(host);
+				return initio_msgin_accept(host);
 			}
 		}
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-		if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
-			return (pCurHcb->HCS_Phase);
+		r = inb(host->addr + TUL_SSignal);
+		outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,
+			host->addr + TUL_SSignal);
+		if (initio_msgin_accept(host) != MSG_OUT)
+			return host->phase;
 		/* sync msg out */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
 
-		tul_sync_done(pCurHcb);
+		initio_sync_done(host);
 
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
-
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-		return (wait_tulip(pCurHcb));
+		outb(MSG_EXTEND, host->addr + TUL_SFifo);
+		outb(3, host->addr + TUL_SFifo);
+		outb(1, host->addr + TUL_SFifo);
+		outb(host->msg[2], host->addr + TUL_SFifo);
+		outb(host->msg[3], host->addr + TUL_SFifo);
+		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+		return wait_tulip(host);
 	}
-	if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
-		return (tul_msgout_reject(pCurHcb));
+	if (host->msg[0] != 2 || host->msg[1] != 3)
+		return initio_msgout_reject(host);
 	/* if it's WIDE DATA XFER REQ   */
-	if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
-		pCurHcb->HCS_Msg[2] = 0;
+	if (host->active_tc->flags & TCF_NO_WDTR) {
+		host->msg[2] = 0;
 	} else {
-		if (pCurHcb->HCS_Msg[2] > 2)	/* > 32 bits            */
-			return (tul_msgout_reject(pCurHcb));
-		if (pCurHcb->HCS_Msg[2] == 2) {		/* == 32                */
-			pCurHcb->HCS_Msg[2] = 1;
+		if (host->msg[2] > 2)	/* > 32 bits            */
+			return initio_msgout_reject(host);
+		if (host->msg[2] == 2) {		/* == 32                */
+			host->msg[2] = 1;
 		} else {
-			if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
-				wdtr_done(pCurHcb);
-				if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
-					TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-				return (tul_msgin_accept(pCurHcb));
+			if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {
+				wdtr_done(host);
+				if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
+					outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+				return initio_msgin_accept(host);
 			}
 		}
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
 
-	if (tul_msgin_accept(pCurHcb) != MSG_OUT)
-		return (pCurHcb->HCS_Phase);
+	if (initio_msgin_accept(host) != MSG_OUT)
+		return host->phase;
 	/* WDTR msg out                 */
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-	return (wait_tulip(pCurHcb));
+	outb(MSG_EXTEND, host->addr + TUL_SFifo);
+	outb(2, host->addr + TUL_SFifo);
+	outb(3, host->addr + TUL_SFifo);
+	outb(host->msg[2], host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-/***************************************************************************/
-int tul_msgin_sync(HCS * pCurHcb)
+static int initio_msgin_sync(struct initio_host * host)
 {
 	char default_period;
 
-	default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
-	if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
-		pCurHcb->HCS_Msg[3] = MAX_OFFSET;
-		if (pCurHcb->HCS_Msg[2] < default_period) {
-			pCurHcb->HCS_Msg[2] = default_period;
+	default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];
+	if (host->msg[3] > MAX_OFFSET) {
+		host->msg[3] = MAX_OFFSET;
+		if (host->msg[2] < default_period) {
+			host->msg[2] = default_period;
 			return 1;
 		}
-		if (pCurHcb->HCS_Msg[2] >= 59) {	/* Change to async              */
-			pCurHcb->HCS_Msg[3] = 0;
-		}
+		if (host->msg[2] >= 59)	/* Change to async              */
+			host->msg[3] = 0;
 		return 1;
 	}
 	/* offset requests asynchronous transfers ? */
-	if (pCurHcb->HCS_Msg[3] == 0) {
+	if (host->msg[3] == 0) {
 		return 0;
 	}
-	if (pCurHcb->HCS_Msg[2] < default_period) {
-		pCurHcb->HCS_Msg[2] = default_period;
+	if (host->msg[2] < default_period) {
+		host->msg[2] = default_period;
 		return 1;
 	}
-	if (pCurHcb->HCS_Msg[2] >= 59) {
-		pCurHcb->HCS_Msg[3] = 0;
+	if (host->msg[2] >= 59) {
+		host->msg[3] = 0;
 		return 1;
 	}
 	return 0;
 }
 
-
-/***************************************************************************/
-int wdtr_done(HCS * pCurHcb)
+static int wdtr_done(struct initio_host * host)
 {
-	pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
-	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
+	host->active_tc->flags &= ~TCF_SYNC_DONE;
+	host->active_tc->flags |= TCF_WDTR_DONE;
 
-	pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
-	if (pCurHcb->HCS_Msg[2]) {	/* if 16 bit */
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
-	}
-	pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+	host->active_tc->js_period = 0;
+	if (host->msg[2])	/* if 16 bit */
+		host->active_tc->js_period |= TSC_WIDE_SCSI;
+	host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;
+	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
 
 	return 1;
 }
 
-/***************************************************************************/
-int tul_sync_done(HCS * pCurHcb)
+static int initio_sync_done(struct initio_host * host)
 {
 	int i;
 
-	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
+	host->active_tc->flags |= TCF_SYNC_DONE;
 
-	if (pCurHcb->HCS_Msg[3]) {
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
+	if (host->msg[3]) {
+		host->active_tc->js_period |= host->msg[3];
 		for (i = 0; i < 8; i++) {
-			if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])	/* pick the big one */
+			if (initio_rate_tbl[i] >= host->msg[2])	/* pick the big one */
 				break;
 		}
-		pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
-		pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
+		host->active_tc->js_period |= (i << 4);
+		host->active_tc->sconfig0 |= TSC_ALT_PERIOD;
 	}
-	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
 
-	return (-1);
+	return -1;
 }
 
 
-int tul_post_scsi_rst(HCS * pCurHcb)
+static int initio_post_scsi_rst(struct initio_host * host)
 {
-	SCB *pCurScb;
-	TCS *pCurTcb;
+	struct scsi_ctrl_blk *scb;
+	struct target_control *active_tc;
 	int i;
 
-	pCurHcb->HCS_ActScb = NULL;
-	pCurHcb->HCS_ActTcs = NULL;
-	pCurHcb->HCS_Flags = 0;
+	host->active = NULL;
+	host->active_tc = NULL;
+	host->flags = 0;
 
-	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
-		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-		tul_append_done_scb(pCurHcb, pCurScb);
+	while ((scb = initio_pop_busy_scb(host)) != NULL) {
+		scb->hastat = HOST_BAD_PHAS;
+		initio_append_done_scb(host, scb);
 	}
 	/* clear sync done flag         */
-	pCurTcb = &pCurHcb->HCS_Tcs[0];
-	for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
-		pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	active_tc = &host->targets[0];
+	for (i = 0; i < host->max_tar; active_tc++, i++) {
+		active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
 		/* Initialize the sync. xfer register values to an asyn xfer */
-		pCurTcb->TCS_JS_Period = 0;
-		pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
-		pCurHcb->HCS_ActTags[0] = 0;	/* 07/22/98 */
-		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;	/* 07/22/98 */
+		active_tc->js_period = 0;
+		active_tc->sconfig0 = host->sconf1;
+		host->act_tags[0] = 0;	/* 07/22/98 */
+		host->targets[i].flags &= ~TCF_BUSY;	/* 07/22/98 */
 	}			/* for */
 
-	return (-1);
+	return -1;
 }
 
-/***************************************************************************/
-void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x1;
-	pCurHcb->HCS_ActScb = pCurScb;
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
-	return;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x1;
+	host->active = scb;
+	host->active_tc = &host->targets[scb->target];
+	outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);
 }
 
 
-/***************************************************************************/
-void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
 	int i;
 
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x2;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x2;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	pCurHcb->HCS_ActScb = pCurScb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
-	return;
+	outb(scb->ident, host->addr + TUL_SFifo);
+	for (i = 0; i < (int) scb->cdblen; i++)
+		outb(scb->cdb[i], host->addr + TUL_SFifo);
+	host->active_tc = &host->targets[scb->target];
+	host->active = scb;
+	outb(TSC_SEL_ATN, host->addr + TUL_SCmd);
 }
 
-/***************************************************************************/
-void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)
 {
 	int i;
 
-	pCurScb->SCB_Status |= SCB_SELECT;
-	pCurScb->SCB_NxtStat = 0x2;
+	scb->status |= SCB_SELECT;
+	scb->next_state = 0x2;
 
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
-	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
-		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
-	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-	pCurHcb->HCS_ActScb = pCurScb;
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
-	return;
+	outb(scb->ident, host->addr + TUL_SFifo);
+	outb(scb->tagmsg, host->addr + TUL_SFifo);
+	outb(scb->tagid, host->addr + TUL_SFifo);
+	for (i = 0; i < scb->cdblen; i++)
+		outb(scb->cdb[i], host->addr + TUL_SFifo);
+	host->active_tc = &host->targets[scb->target];
+	host->active = scb;
+	outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);
 }
 
-/***************************************************************************/
-/* SCSI Bus Device Reset */
-int tul_bus_device_reset(HCS * pCurHcb)
+/**
+ *	initio_bus_device_reset	-	 SCSI Bus Device Reset
+ *	@host: InitIO host to reset
+ *
+ *	Perform a device reset and abort all pending SCBs for the
+ *	victim device
+ */
+int initio_bus_device_reset(struct initio_host * host)
 {
-	SCB *pCurScb = pCurHcb->HCS_ActScb;
-	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-	SCB *pTmpScb, *pPrevScb;
-	BYTE tar;
+	struct scsi_ctrl_blk *scb = host->active;
+	struct target_control *active_tc = host->active_tc;
+	struct scsi_ctrl_blk *tmp, *prev;
+	u8 tar;
 
-	if (pCurHcb->HCS_Phase != MSG_OUT) {
-		return (int_tul_bad_seq(pCurHcb));	/* Unexpected phase             */
-	}
-	tul_unlink_pend_scb(pCurHcb, pCurScb);
-	tul_release_scb(pCurHcb, pCurScb);
+	if (host->phase != MSG_OUT)
+		return int_initio_bad_seq(host);	/* Unexpected phase */
+
+	initio_unlink_pend_scb(host, scb);
+	initio_release_scb(host, scb);
 
 
-	tar = pCurScb->SCB_Target;	/* target                       */
-	pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
+	tar = scb->target;	/* target                       */
+	active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
 	/* clr sync. nego & WDTR flags  07/22/98 */
 
 	/* abort all SCB with same target */
-	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
-	while (pTmpScb != NULL) {
-
-		if (pTmpScb->SCB_Target == tar) {
+	prev = tmp = host->first_busy;	/* Check Busy queue */
+	while (tmp != NULL) {
+		if (tmp->target == tar) {
 			/* unlink it */
-			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
-				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
-					pCurHcb->HCS_LastBusy = NULL;
+			if (tmp == host->first_busy) {
+				if ((host->first_busy = tmp->next) == NULL)
+					host->last_busy = NULL;
 			} else {
-				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
-				if (pTmpScb == pCurHcb->HCS_LastBusy)
-					pCurHcb->HCS_LastBusy = pPrevScb;
+				prev->next = tmp->next;
+				if (tmp == host->last_busy)
+					host->last_busy = prev;
 			}
-			pTmpScb->SCB_HaStat = HOST_ABORTED;
-			tul_append_done_scb(pCurHcb, pTmpScb);
+			tmp->hastat = HOST_ABORTED;
+			initio_append_done_scb(host, tmp);
 		}
 		/* Previous haven't change      */
 		else {
-			pPrevScb = pTmpScb;
+			prev = tmp;
 		}
-		pTmpScb = pTmpScb->SCB_NxtScb;
+		tmp = tmp->next;
 	}
-
-	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-
-	return tul_wait_disc(pCurHcb);
+	outb(MSG_DEVRST, host->addr + TUL_SFifo);
+	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+	return initio_wait_disc(host);
 
 }
 
-/***************************************************************************/
-int tul_msgin_accept(HCS * pCurHcb)
+static int initio_msgin_accept(struct initio_host * host)
 {
-	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
-	return (wait_tulip(pCurHcb));
+	outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+	return wait_tulip(host);
 }
 
-/***************************************************************************/
-int wait_tulip(HCS * pCurHcb)
+static int wait_tulip(struct initio_host * host)
 {
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+		 & TSS_INT_PENDING))
+			cpu_relax();
 
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-	pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
-	pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+	host->jsint = inb(host->addr + TUL_SInt);
+	host->phase = host->jsstatus0 & TSS_PH_MASK;
+	host->jsstatus1 = inb(host->addr + TUL_SStatus1);
 
-	if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_resel(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {	/* if selected/reselected timeout interrupt */
-		return (int_tul_busfree(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
-	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-			tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
-			pCurHcb->HCS_ActScb->SCB_HaStat = 0;
-			tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
-			pCurHcb->HCS_ActScb = NULL;
-			pCurHcb->HCS_ActTcs = NULL;
-			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
-			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-			return (-1);
+	if (host->jsint & TSS_RESEL_INT)	/* if SCSI bus reset detected */
+		return int_initio_resel(host);
+	if (host->jsint & TSS_SEL_TIMEOUT)	/* if selected/reselected timeout interrupt */
+		return int_initio_busfree(host);
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected   */
+		return int_initio_scsi_rst(host);
+
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */
+		if (host->flags & HCF_EXPECT_DONE_DISC) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+			initio_unlink_busy_scb(host, host->active);
+			host->active->hastat = 0;
+			initio_append_done_scb(host, host->active);
+			host->active = NULL;
+			host->active_tc = NULL;
+			host->flags &= ~HCF_EXPECT_DONE_DISC;
+			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+			return -1;
 		}
-		if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-			pCurHcb->HCS_ActScb = NULL;
-			pCurHcb->HCS_ActTcs = NULL;
-			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
-			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-			return (-1);
+		if (host->flags & HCF_EXPECT_DISC) {
+			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+			host->active = NULL;
+			host->active_tc = NULL;
+			host->flags &= ~HCF_EXPECT_DISC;
+			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+			return -1;
 		}
-		return (int_tul_busfree(pCurHcb));
+		return int_initio_busfree(host);
 	}
-	if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
-		return (pCurHcb->HCS_Phase);
-	}
-	return (pCurHcb->HCS_Phase);
+	/* The old code really does the below. Can probably be removed */
+	if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))
+		return host->phase;
+	return host->phase;
 }
-/***************************************************************************/
-int tul_wait_disc(HCS * pCurHcb)
+
+static int initio_wait_disc(struct initio_host * host)
 {
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))
+		cpu_relax();
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	host->jsint = inb(host->addr + TUL_SInt);
 
-
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */
+		return int_initio_scsi_rst(host);
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */
+		host->active = NULL;
+		return -1;
 	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-		pCurHcb->HCS_ActScb = NULL;
-		return (-1);
-	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
-/***************************************************************************/
-int tul_wait_done_disc(HCS * pCurHcb)
+static int initio_wait_done_disc(struct initio_host * host)
 {
+	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+		 & TSS_INT_PENDING))
+		 cpu_relax();
 
+	host->jsint = inb(host->addr + TUL_SInt);
 
-	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
-		 & TSS_INT_PENDING));
+	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */
+		return int_initio_scsi_rst(host);
+	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */
+		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO */
+		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);		/* Enable HW reselect */
+		initio_unlink_busy_scb(host, host->active);
 
-	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-
-
-	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
-		return (int_tul_scsi_rst(pCurHcb));
+		initio_append_done_scb(host, host->active);
+		host->active = NULL;
+		return -1;
 	}
-	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
-		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
-		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
-		tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
-
-		tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
-		pCurHcb->HCS_ActScb = NULL;
-		return (-1);
-	}
-	return (tul_bad_seq(pCurHcb));
+	return initio_bad_seq(host);
 }
 
+/**
+ *	i91u_intr		-	IRQ handler
+ *	@irqno: IRQ number
+ *	@dev_id: IRQ identifier
+ *
+ *	Take the relevant locks and then invoke the actual isr processing
+ *	code under the lock.
+ */
+
 static irqreturn_t i91u_intr(int irqno, void *dev_id)
 {
 	struct Scsi_Host *dev = dev_id;
 	unsigned long flags;
+	int r;
 	
 	spin_lock_irqsave(dev->host_lock, flags);
-	tul_isr((HCS *)dev->base);
+	r = initio_isr((struct initio_host *)dev->hostdata);
 	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
+	if (r)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
 }
 
-static int tul_NewReturnNumberOfAdapters(void)
-{
-	struct pci_dev *pDev = NULL;	/* Start from none              */
-	int iAdapters = 0;
-	long dRegValue;
-	WORD wBIOS;
-	int i = 0;
 
-	init_i91uAdapter_table();
+/**
+ *	initio_build_scb		-	Build the mappings and SCB
+ *	@host: InitIO host taking the command
+ *	@cblk: Firmware command block
+ *	@cmnd: SCSI midlayer command block
+ *
+ *	Translate the abstract SCSI command into a firmware command block
+ *	suitable for feeding to the InitIO host controller. This also requires
+ *	we build the scatter gather lists and ensure they are mapped properly.
+ */
 
-	for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
-	{
-		while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) {
-			if (pci_enable_device(pDev))
-				continue;
-			pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-			wBIOS = (UWORD) (dRegValue & 0xFF);
-			if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-				dRegValue = 0;
-			wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-			if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
-				printk(KERN_WARNING 
-				       "i91u: Could not set 32 bit DMA mask\n");
-				continue;
-			}
-
-			if (Addi91u_into_Adapter_table(wBIOS,
-							(pDev->resource[0].start),
-						       	pDev->irq,
-						       	pDev->bus->number,
-					       		(pDev->devfn >> 3)
-		    		) == 0)
-				iAdapters++;
-		}
-	}
-
-	return (iAdapters);
-}
-
-static int i91u_detect(struct scsi_host_template * tpnt)
-{
-	HCS *pHCB;
-	struct Scsi_Host *hreg;
-	unsigned long i;	/* 01/14/98                     */
-	int ok = 0, iAdapters;
-	ULONG dBiosAdr;
-	BYTE *pbBiosAdr;
-
-	/* Get total number of adapters in the motherboard */
-	iAdapters = tul_NewReturnNumberOfAdapters();
-	if (iAdapters == 0)	/* If no tulip founded, return */
-		return (0);
-
-	tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
-	/* Update actually channel number */
-	if (tul_tag_enable) {	/* 1.01i                  */
-		tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
-	} else {
-		tul_num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */
-	}			/* Update actually SCBs per adapter */
-
-	/* Get total memory needed for HCS */
-	i = tul_num_ch * sizeof(HCS);
-	memset((unsigned char *) &tul_hcs[0], 0, i);	/* Initialize tul_hcs 0 */
-	/* Get total memory needed for SCB */
-
-	for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
-		i = tul_num_ch * tul_num_scb * sizeof(SCB);
-		if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
-			break;
-	}
-	if (tul_scb == NULL) {
-		printk("i91u: SCB memory allocation error\n");
-		return (0);
-	}
-	memset((unsigned char *) tul_scb, 0, i);
-
-	for (i = 0, pHCB = &tul_hcs[0];		/* Get pointer for control block */
-	     i < tul_num_ch;
-	     i++, pHCB++) {
-		get_tulipPCIConfig(pHCB, i);
-
-		dBiosAdr = pHCB->HCS_BIOS;
-		dBiosAdr = (dBiosAdr << 4);
-
-		pbBiosAdr = phys_to_virt(dBiosAdr);
-
-		init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
-		request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ 
-
-		pHCB->HCS_Index = i;	/* 7/29/98 */
-		hreg = scsi_register(tpnt, sizeof(HCS));
-		if(hreg == NULL) {
-			release_region(pHCB->HCS_Base, 256);
-			return 0;
-		}
-		hreg->io_port = pHCB->HCS_Base;
-		hreg->n_io_port = 0xff;
-		hreg->can_queue = tul_num_scb;	/* 03/05/98                      */
-		hreg->unique_id = pHCB->HCS_Base;
-		hreg->max_id = pHCB->HCS_MaxTar;
-		hreg->max_lun = 32;	/* 10/21/97                     */
-		hreg->irq = pHCB->HCS_Intr;
-		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
-		hreg->base = (unsigned long)pHCB;
-		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
-
-		/* Initial tulip chip           */
-		ok = request_irq(pHCB->HCS_Intr, i91u_intr, IRQF_DISABLED | IRQF_SHARED, "i91u", hreg);
-		if (ok < 0) {
-			printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr);
-			return 0;
-		}
-	}
-
-	tpnt->this_id = -1;
-	tpnt->can_queue = 1;
-
-	return 1;
-}
-
-static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, struct scsi_cmnd * SCpnt)
+static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)
 {				/* Create corresponding SCB     */
-	struct scatterlist *pSrbSG;
-	SG *pSG;		/* Pointer to SG list           */
-	int i;
-	long TotalLen;
+	struct scatterlist *sglist;
+	struct sg_entry *sg;		/* Pointer to SG list           */
+	int i, nseg;
+	long total_len;
 	dma_addr_t dma_addr;
 
-	pSCB->SCB_Post = i91uSCBPost;	/* i91u's callback routine      */
-	pSCB->SCB_Srb = SCpnt;
-	pSCB->SCB_Opcode = ExecSCSI;
-	pSCB->SCB_Flags = SCF_POST;	/* After SCSI done, call post routine */
-	pSCB->SCB_Target = SCpnt->device->id;
-	pSCB->SCB_Lun = SCpnt->device->lun;
-	pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
+	/* Fill in the command headers */
+	cblk->post = i91uSCBPost;	/* i91u's callback routine      */
+	cblk->srb = cmnd;
+	cblk->opcode = ExecSCSI;
+	cblk->flags = SCF_POST;	/* After SCSI done, call post routine */
+	cblk->target = cmnd->device->id;
+	cblk->lun = cmnd->device->lun;
+	cblk->ident = cmnd->device->lun | DISC_ALLOW;
 
-	pSCB->SCB_Flags |= SCF_SENSE;	/* Turn on auto request sense   */
-	dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->sense_buffer,
+	cblk->flags |= SCF_SENSE;	/* Turn on auto request sense   */
+
+	/* Map the sense buffer into bus memory */
+	dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
 				  SENSE_SIZE, DMA_FROM_DEVICE);
-	pSCB->SCB_SensePtr = cpu_to_le32((u32)dma_addr);
-	pSCB->SCB_SenseLen = cpu_to_le32(SENSE_SIZE);
-	SCpnt->SCp.ptr = (char *)(unsigned long)dma_addr;
+	cblk->senseptr = cpu_to_le32((u32)dma_addr);
+	cblk->senselen = cpu_to_le32(SENSE_SIZE);
+	cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
+	cblk->cdblen = cmnd->cmd_len;
 
-	pSCB->SCB_CDBLen = SCpnt->cmd_len;
-	pSCB->SCB_HaStat = 0;
-	pSCB->SCB_TaStat = 0;
-	memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
+	/* Clear the returned status */
+	cblk->hastat = 0;
+	cblk->tastat = 0;
+	/* Command the command */
+	memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
 
-	if (SCpnt->device->tagged_supported) {	/* Tag Support                  */
-		pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
+	/* Set up tags */
+	if (cmnd->device->tagged_supported) {	/* Tag Support                  */
+		cblk->tagmsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
 	} else {
-		pSCB->SCB_TagMsg = 0;	/* No tag support               */
+		cblk->tagmsg = 0;	/* No tag support               */
 	}
+
 	/* todo handle map_sg error */
-	if (SCpnt->use_sg) {
-		dma_addr = dma_map_single(&pHCB->pci_dev->dev, &pSCB->SCB_SGList[0],
-					  sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
+	nseg = scsi_dma_map(cmnd);
+	BUG_ON(nseg < 0);
+	if (nseg) {
+		dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
+					  sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
 					  DMA_BIDIRECTIONAL);
-		pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
-		SCpnt->SCp.dma_handle = dma_addr;
+		cblk->bufptr = cpu_to_le32((u32)dma_addr);
+		cmnd->SCp.dma_handle = dma_addr;
 
-		pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
-		pSCB->SCB_SGLen = dma_map_sg(&pHCB->pci_dev->dev, pSrbSG,
-					     SCpnt->use_sg, SCpnt->sc_data_direction);
 
-		pSCB->SCB_Flags |= SCF_SG;	/* Turn on SG list flag       */
-		for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];	/* 1.01g */
-		     i < pSCB->SCB_SGLen; i++, pSG++, pSrbSG++) {
-			pSG->SG_Ptr = cpu_to_le32((u32)sg_dma_address(pSrbSG));
-			TotalLen += pSG->SG_Len = cpu_to_le32((u32)sg_dma_len(pSrbSG));
+		cblk->flags |= SCF_SG;	/* Turn on SG list flag       */
+		total_len = 0;
+		sg = &cblk->sglist[0];
+		scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
+			sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
+			total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
 		}
 
-		pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
-		    TotalLen : SCpnt->request_bufflen;
-	} else if (SCpnt->request_bufflen) {		/* Non SG */
-		dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->request_buffer,
-					  SCpnt->request_bufflen,
-					  SCpnt->sc_data_direction);
-		SCpnt->SCp.dma_handle = dma_addr;
-		pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
-		pSCB->SCB_BufLen = cpu_to_le32((u32)SCpnt->request_bufflen);
-		pSCB->SCB_SGLen = 0;
-	} else {
-		pSCB->SCB_BufLen = 0;
-		pSCB->SCB_SGLen = 0;
+		cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?
+			total_len : scsi_bufflen(cmnd);
+	} else {	/* No data transfer required */
+		cblk->buflen = 0;
+		cblk->sglen = 0;
 	}
 }
 
+/**
+ *	i91u_queuecommand	-	Queue a new command if possible
+ *	@cmd: SCSI command block from the mid layer
+ *	@done: Completion handler
+ *
+ *	Attempts to queue a new command with the host adapter. Will return
+ *	zero if successful or indicate a host busy condition if not (which
+ *	will cause the mid layer to call us again later with the command)
+ */
+
 static int i91u_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 {
-	HCS *pHCB = (HCS *) cmd->device->host->base;
-	register SCB *pSCB;
+	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
+	struct scsi_ctrl_blk *cmnd;
 
 	cmd->scsi_done = done;
 
-	pSCB = tul_alloc_scb(pHCB);
-	if (!pSCB)
+	cmnd = initio_alloc_scb(host);
+	if (!cmnd)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	i91uBuildSCB(pHCB, pSCB, cmd);
-	tul_exec_scb(pHCB, pSCB);
+	initio_build_scb(host, cmnd, cmd);
+	initio_exec_scb(host, cmnd);
 	return 0;
 }
 
-#if 0 /* no new EH yet */
-/*
- *  Abort a queued command
- *  (commands that are on the bus can't be aborted easily)
+/**
+ *	i91u_bus_reset		-	reset the SCSI bus
+ *	@cmnd: Command block we want to trigger the reset for
+ *
+ *	Initiate a SCSI bus reset sequence
  */
-static int i91u_abort(struct scsi_cmnd * SCpnt)
+
+static int i91u_bus_reset(struct scsi_cmnd * cmnd)
 {
-	HCS *pHCB;
+	struct initio_host *host;
 
-	pHCB = (HCS *) SCpnt->device->host->base;
-	return tul_abort_srb(pHCB, SCpnt);
-}
+	host = (struct initio_host *) cmnd->device->host->hostdata;
 
-/*
- *  Reset registers, reset a hanging bus and
- *  kill active and disconnected commands for target w/o soft reset
- */
-static int i91u_reset(struct scsi_cmnd * SCpnt, unsigned int reset_flags)
-{				/* I need Host Control Block Information */
-	HCS *pHCB;
-
-	pHCB = (HCS *) SCpnt->device->host->base;
-
-	if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
-		return tul_reset_scsi_bus(pHCB);
-	else
-		return tul_device_reset(pHCB, SCpnt, SCpnt->device->id, reset_flags);
-}
-#endif
-
-static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
-{
-	HCS *pHCB;
-
-	pHCB = (HCS *) SCpnt->device->host->base;
-
-	spin_lock_irq(SCpnt->device->host->host_lock);
-	tul_reset_scsi(pHCB, 0);
-	spin_unlock_irq(SCpnt->device->host->host_lock);
+	spin_lock_irq(cmnd->device->host->host_lock);
+	initio_reset_scsi(host, 0);
+	spin_unlock_irq(cmnd->device->host->host_lock);
 
 	return SUCCESS;
 }
 
-/*
- * Return the "logical geometry"
+/**
+ *	i91u_biospararm			-	return the "logical geometry
+ *	@sdev: SCSI device
+ *	@dev; Matching block device
+ *	@capacity: Sector size of drive
+ *	@info_array: Return space for BIOS geometry
+ *
+ *	Map the device geometry in a manner compatible with the host
+ *	controller BIOS behaviour.
+ *
+ *	FIXME: limited to 2^32 sector devices.
  */
+
 static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,
 		sector_t capacity, int *info_array)
 {
-	HCS *pHcb;		/* Point to Host adapter control block */
-	TCS *pTcb;
+	struct initio_host *host;		/* Point to Host adapter control block */
+	struct target_control *tc;
 
-	pHcb = (HCS *) sdev->host->base;
-	pTcb = &pHcb->HCS_Tcs[sdev->id];
+	host = (struct initio_host *) sdev->host->hostdata;
+	tc = &host->targets[sdev->id];
 
-	if (pTcb->TCS_DrvHead) {
-		info_array[0] = pTcb->TCS_DrvHead;
-		info_array[1] = pTcb->TCS_DrvSector;
-		info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
+	if (tc->heads) {
+		info_array[0] = tc->heads;
+		info_array[1] = tc->sectors;
+		info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;
 	} else {
-		if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
+		if (tc->drv_flags & TCF_DRV_255_63) {
 			info_array[0] = 255;
 			info_array[1] = 63;
 			info_array[2] = (unsigned long)capacity / 255 / 63;
@@ -3047,7 +2722,16 @@
 	return 0;
 }
 
-static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
+/**
+ *	i91u_unmap_scb		-	Unmap a command
+ *	@pci_dev: PCI device the command is for
+ *	@cmnd: The command itself
+ *
+ *	Unmap any PCI mapping/IOMMU resources allocated when the command
+ *	was mapped originally as part of initio_build_scb
+ */
+
+static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
 {
 	/* auto sense buffer */
 	if (cmnd->SCp.ptr) {
@@ -3058,65 +2742,63 @@
 	}
 
 	/* request buffer */
-	if (cmnd->use_sg) {
+	if (scsi_sg_count(cmnd)) {
 		dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
-				 sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
+				 sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
 				 DMA_BIDIRECTIONAL);
 
-		dma_unmap_sg(&pci_dev->dev, cmnd->request_buffer,
-			     cmnd->use_sg,
-			     cmnd->sc_data_direction);
-	} else if (cmnd->request_bufflen) {
-		dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
-				 cmnd->request_bufflen,
-				 cmnd->sc_data_direction);
+		scsi_dma_unmap(cmnd);
 	}
 }
 
-/*****************************************************************************
- Function name  : i91uSCBPost
- Description    : This is callback routine be called when tulip finish one
-			SCSI command.
- Input          : pHCB  -       Pointer to host adapter control block.
-		  pSCB  -       Pointer to SCSI control block.
- Output         : None.
- Return         : None.
-*****************************************************************************/
-static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
+/**
+ *	i91uSCBPost		-	SCSI callback
+ *	@host: Pointer to host adapter control block.
+ *	@cmnd: Pointer to SCSI control block.
+ *
+ *	This is callback routine be called when tulip finish one
+ *	SCSI command.
+ */
+
+static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)
 {
-	struct scsi_cmnd *pSRB;	/* Pointer to SCSI request block */
-	HCS *pHCB;
-	SCB *pSCB;
+	struct scsi_cmnd *cmnd;	/* Pointer to SCSI request block */
+	struct initio_host *host;
+	struct scsi_ctrl_blk *cblk;
 
-	pHCB = (HCS *) pHcb;
-	pSCB = (SCB *) pScb;
-	if ((pSRB = pSCB->SCB_Srb) == 0) {
-		printk("i91uSCBPost: SRB pointer is empty\n");
-
-		tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+	host = (struct initio_host *) host_mem;
+	cblk = (struct scsi_ctrl_blk *) cblk_mem;
+	if ((cmnd = cblk->srb) == NULL) {
+		printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");
+		WARN_ON(1);
+		initio_release_scb(host, cblk);	/* Release SCB for current channel */
 		return;
 	}
-	switch (pSCB->SCB_HaStat) {
+
+	/*
+	 *	Remap the firmware error status into a mid layer one
+	 */
+	switch (cblk->hastat) {
 	case 0x0:
 	case 0xa:		/* Linked command complete without error and linked normally */
 	case 0xb:		/* Linked command complete without error interrupt generated */
-		pSCB->SCB_HaStat = 0;
+		cblk->hastat = 0;
 		break;
 
 	case 0x11:		/* Selection time out-The initiator selection or target
 				   reselection was not complete within the SCSI Time out period */
-		pSCB->SCB_HaStat = DID_TIME_OUT;
+		cblk->hastat = DID_TIME_OUT;
 		break;
 
 	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus
 				   phase sequence was requested by the target. The host adapter
 				   will generate a SCSI Reset Condition, notifying the host with
 				   a SCRD interrupt */
-		pSCB->SCB_HaStat = DID_RESET;
+		cblk->hastat = DID_RESET;
 		break;
 
 	case 0x1a:		/* SCB Aborted. 07/21/98 */
-		pSCB->SCB_HaStat = DID_ABORT;
+		cblk->hastat = DID_ABORT;
 		break;
 
 	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data
@@ -3126,49 +2808,196 @@
 	case 0x16:		/* Invalid SCB Operation Code. */
 
 	default:
-		printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
-		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */
+		printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);
+		cblk->hastat = DID_ERROR;	/* Couldn't find any better */
 		break;
 	}
 
-	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
+	cmnd->result = cblk->tastat | (cblk->hastat << 16);
+	WARN_ON(cmnd == NULL);
+	i91u_unmap_scb(host->pci_dev, cmnd);
+	cmnd->scsi_done(cmnd);	/* Notify system DONE           */
+	initio_release_scb(host, cblk);	/* Release SCB for current channel */
+}
 
-	if (pSRB == NULL) {
-		printk("pSRB is NULL\n");
+static struct scsi_host_template initio_template = {
+	.proc_name		= "INI9100U",
+	.name			= "Initio INI-9X00U/UW SCSI device driver",
+	.queuecommand		= i91u_queuecommand,
+	.eh_bus_reset_handler	= i91u_bus_reset,
+	.bios_param		= i91u_biosparam,
+	.can_queue		= MAX_TARGETS * i91u_MAXQUEUE,
+	.this_id		= 1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 1,
+	.use_clustering		= ENABLE_CLUSTERING,
+};
+
+static int initio_probe_one(struct pci_dev *pdev,
+	const struct pci_device_id *id)
+{
+	struct Scsi_Host *shost;
+	struct initio_host *host;
+	u32 reg;
+	u16 bios_seg;
+	struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;
+	int num_scb, i, error;
+
+	error = pci_enable_device(pdev);
+	if (error)
+		return error;
+
+	pci_read_config_dword(pdev, 0x44, (u32 *) & reg);
+	bios_seg = (u16) (reg & 0xFF);
+	if (((reg & 0xFF00) >> 8) == 0xFF)
+		reg = 0;
+	bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));
+
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		printk(KERN_WARNING  "i91u: Could not set 32 bit DMA mask\n");
+		error = -ENODEV;
+		goto out_disable_device;
+	}
+	shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));
+	if (!shost) {
+		printk(KERN_WARNING "initio: Could not allocate host structure.\n");
+		error = -ENOMEM;
+		goto out_disable_device;
+	}
+	host = (struct initio_host *)shost->hostdata;
+	memset(host, 0, sizeof(struct initio_host));
+
+	if (!request_region(host->addr, 256, "i91u")) {
+		printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);
+		error = -ENODEV;
+		goto out_host_put;
 	}
 
-	i91u_unmap_cmnd(pHCB->pci_dev, pSRB);
-	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
+	if (initio_tag_enable)	/* 1.01i */
+		num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+	else
+		num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */
 
-	tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
-}
+	for (; num_scb >= MAX_TARGETS + 3; num_scb--) {
+		i = num_scb * sizeof(struct scsi_ctrl_blk);
+		if ((scb = kzalloc(i, GFP_DMA)) != NULL)
+			break;
+	}
 
-/*
- * Release ressources
- */
-static int i91u_release(struct Scsi_Host *hreg)
-{
-	free_irq(hreg->irq, hreg);
-	release_region(hreg->io_port, 256);
+	if (!scb) {
+		printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");
+		error = -ENOMEM;
+		goto out_release_region;
+	}
+
+	host->num_scbs = num_scb;
+	host->scb = scb;
+	host->next_pending = scb;
+	host->next_avail = scb;
+	for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {
+		tmp->tagid = i;
+		if (i != 0)
+			prev->next = tmp;
+		prev = tmp;
+	}
+	prev->next = NULL;
+	host->scb_end = tmp;
+	host->first_avail = scb;
+	host->last_avail = prev;
+
+	initio_init(host, phys_to_virt(bios_seg << 4));
+
+	host->jsstatus0 = 0;
+
+	shost->io_port = host->addr;
+	shost->n_io_port = 0xff;
+	shost->can_queue = num_scb;		/* 03/05/98                      */
+	shost->unique_id = host->addr;
+	shost->max_id = host->max_tar;
+	shost->max_lun = 32;	/* 10/21/97                     */
+	shost->irq = pdev->irq;
+	shost->this_id = host->scsi_id;	/* Assign HCS index           */
+	shost->base = host->addr;
+	shost->sg_tablesize = TOTAL_SG_ENTRY;
+
+	error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost);
+	if (error < 0) {
+		printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);
+		goto out_free_scbs;
+	}
+
+	pci_set_drvdata(pdev, shost);
+	host->pci_dev = pdev;
+
+	error = scsi_add_host(shost, &pdev->dev);
+	if (error)
+		goto out_free_irq;
+	scsi_scan_host(shost);
 	return 0;
+out_free_irq:
+	free_irq(pdev->irq, shost);
+out_free_scbs:
+	kfree(host->scb);
+out_release_region:
+	release_region(host->addr, 256);
+out_host_put:
+	scsi_host_put(shost);
+out_disable_device:
+	pci_disable_device(pdev);
+	return error;
 }
-MODULE_LICENSE("Dual BSD/GPL");
 
-static struct scsi_host_template driver_template = {
-	.proc_name	= "INI9100U",
-	.name		= i91u_REVID,
-	.detect		= i91u_detect,
-	.release	= i91u_release,
-	.queuecommand	= i91u_queuecommand,
-//	.abort		= i91u_abort,
-//	.reset		= i91u_reset,
-	.eh_bus_reset_handler = i91u_bus_reset,
-	.bios_param	= i91u_biosparam,
-	.can_queue	= 1,
-	.this_id	= 1,
-	.sg_tablesize	= SG_ALL,
-	.cmd_per_lun 	= 1,
-	.use_clustering	= ENABLE_CLUSTERING,
+/**
+ *	initio_remove_one	-	control shutdown
+ *	@pdev:	PCI device being released
+ *
+ *	Release the resources assigned to this adapter after it has
+ *	finished being used.
+ */
+
+static void initio_remove_one(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct initio_host *s = (struct initio_host *)host->hostdata;
+	scsi_remove_host(host);
+	free_irq(pdev->irq, host);
+	release_region(s->addr, 256);
+	scsi_host_put(host);
+	pci_disable_device(pdev);
+}
+
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id initio_pci_tbl[] = {
+	{PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
 };
-#include "scsi_module.c"
+MODULE_DEVICE_TABLE(pci, initio_pci_tbl);
 
+static struct pci_driver initio_pci_driver = {
+	.name		= "initio",
+	.id_table	= initio_pci_tbl,
+	.probe		= initio_probe_one,
+	.remove		= __devexit_p(initio_remove_one),
+};
+
+static int __init initio_init_driver(void)
+{
+	return pci_register_driver(&initio_pci_driver);
+}
+
+static void __exit initio_exit_driver(void)
+{
+	pci_unregister_driver(&initio_pci_driver);
+}
+
+MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
+MODULE_AUTHOR("Initio Corporation");
+MODULE_LICENSE("GPL");
+
+module_init(initio_init_driver);
+module_exit(initio_exit_driver);
diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h
index acb67a4..cb48efa 100644
--- a/drivers/scsi/initio.h
+++ b/drivers/scsi/initio.h
@@ -4,6 +4,8 @@
  * Copyright (c) 1994-1998 Initio Corporation
  * All rights reserved.
  *
+ * Cleanups (c) Copyright 2007 Red Hat <alan@redhat.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -18,27 +20,6 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * --------------------------------------------------------------------------
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of 
- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,17 +37,6 @@
 
 #include <linux/types.h>
 
-#define ULONG   unsigned long
-#define USHORT  unsigned short
-#define UCHAR   unsigned char
-#define BYTE    unsigned char
-#define WORD    unsigned short
-#define DWORD   unsigned long
-#define UBYTE   unsigned char
-#define UWORD   unsigned short
-#define UDWORD  unsigned long
-#define U32     u32
-
 #define TOTAL_SG_ENTRY		32
 #define MAX_SUPPORTED_ADAPTERS  8
 #define MAX_OFFSET		15
@@ -368,55 +338,55 @@
 /************************************************************************/
 /*              Scatter-Gather Element Structure                        */
 /************************************************************************/
-typedef struct SG_Struc {
-	U32 SG_Ptr;		/* Data Pointer */
-	U32 SG_Len;		/* Data Length */
-} SG;
+struct sg_entry {
+	u32 data;		/* Data Pointer */
+	u32 len;		/* Data Length */
+};
 
 /***********************************************************************
 		SCSI Control Block
 ************************************************************************/
-typedef struct Scsi_Ctrl_Blk {
-	struct Scsi_Ctrl_Blk *SCB_NxtScb;
-	UBYTE SCB_Status;	/*4 */
-	UBYTE SCB_NxtStat;	/*5 */
-	UBYTE SCB_Mode;		/*6 */
-	UBYTE SCB_Msgin;	/*7 SCB_Res0 */
-	UWORD SCB_SGIdx;	/*8 */
-	UWORD SCB_SGMax;	/*A */
+struct scsi_ctrl_blk {
+	struct scsi_ctrl_blk *next;
+	u8 status;	/*4 */
+	u8 next_state;	/*5 */
+	u8 mode;		/*6 */
+	u8 msgin;	/*7 SCB_Res0 */
+	u16 sgidx;	/*8 */
+	u16 sgmax;	/*A */
 #ifdef ALPHA
-	U32 SCB_Reserved[2];	/*C */
+	u32 reserved[2];	/*C */
 #else
-	U32 SCB_Reserved[3];	/*C */
+	u32 reserved[3];	/*C */
 #endif
 
-	U32 SCB_XferLen;	/*18 Current xfer len           */
-	U32 SCB_TotXLen;	/*1C Total xfer len             */
-	U32 SCB_PAddr;		/*20 SCB phy. Addr. */
+	u32 xferlen;	/*18 Current xfer len           */
+	u32 totxlen;	/*1C Total xfer len             */
+	u32 paddr;		/*20 SCB phy. Addr. */
 
-	UBYTE SCB_Opcode;	/*24 SCB command code */
-	UBYTE SCB_Flags;	/*25 SCB Flags */
-	UBYTE SCB_Target;	/*26 Target Id */
-	UBYTE SCB_Lun;		/*27 Lun */
-	U32 SCB_BufPtr;		/*28 Data Buffer Pointer */
-	U32 SCB_BufLen;		/*2C Data Allocation Length */
-	UBYTE SCB_SGLen;	/*30 SG list # */
-	UBYTE SCB_SenseLen;	/*31 Sense Allocation Length */
-	UBYTE SCB_HaStat;	/*32 */
-	UBYTE SCB_TaStat;	/*33 */
-	UBYTE SCB_CDBLen;	/*34 CDB Length */
-	UBYTE SCB_Ident;	/*35 Identify */
-	UBYTE SCB_TagMsg;	/*36 Tag Message */
-	UBYTE SCB_TagId;	/*37 Queue Tag */
-	UBYTE SCB_CDB[12];	/*38 */
-	U32 SCB_SGPAddr;	/*44 SG List/Sense Buf phy. Addr. */
-	U32 SCB_SensePtr;	/*48 Sense data pointer */
-	void (*SCB_Post) (BYTE *, BYTE *);	/*4C POST routine */
-	struct scsi_cmnd *SCB_Srb;	/*50 SRB Pointer */
-	SG SCB_SGList[TOTAL_SG_ENTRY];	/*54 Start of SG list */
-} SCB;
+	u8 opcode;	/*24 SCB command code */
+	u8 flags;	/*25 SCB Flags */
+	u8 target;	/*26 Target Id */
+	u8 lun;		/*27 Lun */
+	u32 bufptr;		/*28 Data Buffer Pointer */
+	u32 buflen;		/*2C Data Allocation Length */
+	u8 sglen;	/*30 SG list # */
+	u8 senselen;	/*31 Sense Allocation Length */
+	u8 hastat;	/*32 */
+	u8 tastat;	/*33 */
+	u8 cdblen;	/*34 CDB Length */
+	u8 ident;	/*35 Identify */
+	u8 tagmsg;	/*36 Tag Message */
+	u8 tagid;	/*37 Queue Tag */
+	u8 cdb[12];	/*38 */
+	u32 sgpaddr;	/*44 SG List/Sense Buf phy. Addr. */
+	u32 senseptr;	/*48 Sense data pointer */
+	void (*post) (u8 *, u8 *);	/*4C POST routine */
+	struct scsi_cmnd *srb;	/*50 SRB Pointer */
+	struct sg_entry sglist[TOTAL_SG_ENTRY];	/*54 Start of SG list */
+};
 
-/* Bit Definition for SCB_Status */
+/* Bit Definition for status */
 #define SCB_RENT        0x01
 #define SCB_PEND        0x02
 #define SCB_CONTIG      0x04	/* Contigent Allegiance */
@@ -425,17 +395,17 @@
 #define SCB_DONE        0x20
 
 
-/* Opcodes of SCB_Opcode */
+/* Opcodes for opcode */
 #define ExecSCSI        0x1
 #define BusDevRst       0x2
 #define AbortCmd        0x3
 
 
-/* Bit Definition for SCB_Mode */
+/* Bit Definition for mode */
 #define SCM_RSENS       0x01	/* request sense mode */
 
 
-/* Bit Definition for SCB_Flags */
+/* Bit Definition for flags */
 #define SCF_DONE        0x01
 #define SCF_POST        0x02
 #define SCF_SENSE       0x04
@@ -492,15 +462,14 @@
 		Target Device Control Structure
 **********************************************************************/
 
-typedef struct Tar_Ctrl_Struc {
-	UWORD TCS_Flags;	/* 0 */
-	UBYTE TCS_JS_Period;	/* 2 */
-	UBYTE TCS_SConfig0;	/* 3 */
-
-	UWORD TCS_DrvFlags;	/* 4 */
-	UBYTE TCS_DrvHead;	/* 6 */
-	UBYTE TCS_DrvSector;	/* 7 */
-} TCS;
+struct target_control {
+	u16 flags;
+	u8 js_period;
+	u8 sconfig0;
+	u16 drv_flags;
+	u8 heads;
+	u8 sectors;
+};
 
 /***********************************************************************
 		Target Device Control Structure
@@ -523,62 +492,53 @@
 #define TCF_DRV_EN_TAG          0x0800
 #define TCF_DRV_255_63          0x0400
 
-typedef struct I91u_Adpt_Struc {
-	UWORD ADPT_BIOS;	/* 0 */
-	UWORD ADPT_BASE;	/* 1 */
-	UBYTE ADPT_Bus;		/* 2 */
-	UBYTE ADPT_Device;	/* 3 */
-	UBYTE ADPT_INTR;	/* 4 */
-} INI_ADPT_STRUCT;
-
-
 /***********************************************************************
 	      Host Adapter Control Structure
 ************************************************************************/
-typedef struct Ha_Ctrl_Struc {
-	UWORD HCS_Base;		/* 00 */
-	UWORD HCS_BIOS;		/* 02 */
-	UBYTE HCS_Intr;		/* 04 */
-	UBYTE HCS_SCSI_ID;	/* 05 */
-	UBYTE HCS_MaxTar;	/* 06 */
-	UBYTE HCS_NumScbs;	/* 07 */
+struct initio_host {
+	u16 addr;		/* 00 */
+	u16 bios_addr;		/* 02 */
+	u8 irq;			/* 04 */
+	u8 scsi_id;		/* 05 */
+	u8 max_tar;		/* 06 */
+	u8 num_scbs;		/* 07 */
 
-	UBYTE HCS_Flags;	/* 08 */
-	UBYTE HCS_Index;	/* 09 */
-	UBYTE HCS_HaId;		/* 0A */
-	UBYTE HCS_Config;	/* 0B */
-	UWORD HCS_IdMask;	/* 0C */
-	UBYTE HCS_Semaph;	/* 0E */
-	UBYTE HCS_Phase;	/* 0F */
-	UBYTE HCS_JSStatus0;	/* 10 */
-	UBYTE HCS_JSInt;	/* 11 */
-	UBYTE HCS_JSStatus1;	/* 12 */
-	UBYTE HCS_SConf1;	/* 13 */
+	u8 flags;		/* 08 */
+	u8 index;		/* 09 */
+	u8 ha_id;		/* 0A */
+	u8 config;		/* 0B */
+	u16 idmask;		/* 0C */
+	u8 semaph;		/* 0E */
+	u8 phase;		/* 0F */
+	u8 jsstatus0;		/* 10 */
+	u8 jsint;		/* 11 */
+	u8 jsstatus1;		/* 12 */
+	u8 sconf1;		/* 13 */
 
-	UBYTE HCS_Msg[8];	/* 14 */
-	SCB *HCS_NxtAvail;	/* 1C */
-	SCB *HCS_Scb;		/* 20 */
-	SCB *HCS_ScbEnd;	/* 24 */
-	SCB *HCS_NxtPend;	/* 28 */
-	SCB *HCS_NxtContig;	/* 2C */
-	SCB *HCS_ActScb;	/* 30 */
-	TCS *HCS_ActTcs;	/* 34 */
+	u8 msg[8];		/* 14 */
+	struct scsi_ctrl_blk *next_avail;	/* 1C */
+	struct scsi_ctrl_blk *scb;		/* 20 */
+	struct scsi_ctrl_blk *scb_end;		/* 24 */ /*UNUSED*/
+	struct scsi_ctrl_blk *next_pending;	/* 28 */
+	struct scsi_ctrl_blk *next_contig;	/* 2C */ /*UNUSED*/
+	struct scsi_ctrl_blk *active;		/* 30 */
+	struct target_control *active_tc;	/* 34 */
 
-	SCB *HCS_FirstAvail;	/* 38 */
-	SCB *HCS_LastAvail;	/* 3C */
-	SCB *HCS_FirstPend;	/* 40 */
-	SCB *HCS_LastPend;	/* 44 */
-	SCB *HCS_FirstBusy;	/* 48 */
-	SCB *HCS_LastBusy;	/* 4C */
-	SCB *HCS_FirstDone;	/* 50 */
-	SCB *HCS_LastDone;	/* 54 */
-	UBYTE HCS_MaxTags[16];	/* 58 */
-	UBYTE HCS_ActTags[16];	/* 68 */
-	TCS HCS_Tcs[MAX_TARGETS];	/* 78 */
-	spinlock_t HCS_AvailLock;
-	spinlock_t HCS_SemaphLock;
+	struct scsi_ctrl_blk *first_avail;	/* 38 */
+	struct scsi_ctrl_blk *last_avail;	/* 3C */
+	struct scsi_ctrl_blk *first_pending;	/* 40 */
+	struct scsi_ctrl_blk *last_pending;	/* 44 */
+	struct scsi_ctrl_blk *first_busy;	/* 48 */
+	struct scsi_ctrl_blk *last_busy;	/* 4C */
+	struct scsi_ctrl_blk *first_done;	/* 50 */
+	struct scsi_ctrl_blk *last_done;	/* 54 */
+	u8 max_tags[16];	/* 58 */
+	u8 act_tags[16];	/* 68 */
+	struct target_control targets[MAX_TARGETS];	/* 78 */
+	spinlock_t avail_lock;
+	spinlock_t semaph_lock;
 	struct pci_dev *pci_dev;
-} HCS;
+};
 
 /* Bit Definition for HCB_Config */
 #define HCC_SCSI_RESET          0x01
@@ -599,47 +559,47 @@
 *******************************************************************/
 
 typedef struct _NVRAM_SCSI {	/* SCSI channel configuration   */
-	UCHAR NVM_ChSCSIID;	/* 0Ch -> Channel SCSI ID       */
-	UCHAR NVM_ChConfig1;	/* 0Dh -> Channel config 1      */
-	UCHAR NVM_ChConfig2;	/* 0Eh -> Channel config 2      */
-	UCHAR NVM_NumOfTarg;	/* 0Fh -> Number of SCSI target */
+	u8 NVM_ChSCSIID;	/* 0Ch -> Channel SCSI ID       */
+	u8 NVM_ChConfig1;	/* 0Dh -> Channel config 1      */
+	u8 NVM_ChConfig2;	/* 0Eh -> Channel config 2      */
+	u8 NVM_NumOfTarg;	/* 0Fh -> Number of SCSI target */
 	/* SCSI target configuration    */
-	UCHAR NVM_Targ0Config;	/* 10h -> Target 0 configuration */
-	UCHAR NVM_Targ1Config;	/* 11h -> Target 1 configuration */
-	UCHAR NVM_Targ2Config;	/* 12h -> Target 2 configuration */
-	UCHAR NVM_Targ3Config;	/* 13h -> Target 3 configuration */
-	UCHAR NVM_Targ4Config;	/* 14h -> Target 4 configuration */
-	UCHAR NVM_Targ5Config;	/* 15h -> Target 5 configuration */
-	UCHAR NVM_Targ6Config;	/* 16h -> Target 6 configuration */
-	UCHAR NVM_Targ7Config;	/* 17h -> Target 7 configuration */
-	UCHAR NVM_Targ8Config;	/* 18h -> Target 8 configuration */
-	UCHAR NVM_Targ9Config;	/* 19h -> Target 9 configuration */
-	UCHAR NVM_TargAConfig;	/* 1Ah -> Target A configuration */
-	UCHAR NVM_TargBConfig;	/* 1Bh -> Target B configuration */
-	UCHAR NVM_TargCConfig;	/* 1Ch -> Target C configuration */
-	UCHAR NVM_TargDConfig;	/* 1Dh -> Target D configuration */
-	UCHAR NVM_TargEConfig;	/* 1Eh -> Target E configuration */
-	UCHAR NVM_TargFConfig;	/* 1Fh -> Target F configuration */
+	u8 NVM_Targ0Config;	/* 10h -> Target 0 configuration */
+	u8 NVM_Targ1Config;	/* 11h -> Target 1 configuration */
+	u8 NVM_Targ2Config;	/* 12h -> Target 2 configuration */
+	u8 NVM_Targ3Config;	/* 13h -> Target 3 configuration */
+	u8 NVM_Targ4Config;	/* 14h -> Target 4 configuration */
+	u8 NVM_Targ5Config;	/* 15h -> Target 5 configuration */
+	u8 NVM_Targ6Config;	/* 16h -> Target 6 configuration */
+	u8 NVM_Targ7Config;	/* 17h -> Target 7 configuration */
+	u8 NVM_Targ8Config;	/* 18h -> Target 8 configuration */
+	u8 NVM_Targ9Config;	/* 19h -> Target 9 configuration */
+	u8 NVM_TargAConfig;	/* 1Ah -> Target A configuration */
+	u8 NVM_TargBConfig;	/* 1Bh -> Target B configuration */
+	u8 NVM_TargCConfig;	/* 1Ch -> Target C configuration */
+	u8 NVM_TargDConfig;	/* 1Dh -> Target D configuration */
+	u8 NVM_TargEConfig;	/* 1Eh -> Target E configuration */
+	u8 NVM_TargFConfig;	/* 1Fh -> Target F configuration */
 } NVRAM_SCSI;
 
 typedef struct _NVRAM {
 /*----------header ---------------*/
-	USHORT NVM_Signature;	/* 0,1: Signature */
-	UCHAR NVM_Size;		/* 2:   Size of data structure */
-	UCHAR NVM_Revision;	/* 3:   Revision of data structure */
+	u16 NVM_Signature;	/* 0,1: Signature */
+	u8 NVM_Size;		/* 2:   Size of data structure */
+	u8 NVM_Revision;	/* 3:   Revision of data structure */
 	/* ----Host Adapter Structure ---- */
-	UCHAR NVM_ModelByte0;	/* 4:   Model number (byte 0) */
-	UCHAR NVM_ModelByte1;	/* 5:   Model number (byte 1) */
-	UCHAR NVM_ModelInfo;	/* 6:   Model information         */
-	UCHAR NVM_NumOfCh;	/* 7:   Number of SCSI channel */
-	UCHAR NVM_BIOSConfig1;	/* 8:   BIOS configuration 1  */
-	UCHAR NVM_BIOSConfig2;	/* 9:   BIOS configuration 2  */
-	UCHAR NVM_HAConfig1;	/* A:   Hoat adapter configuration 1 */
-	UCHAR NVM_HAConfig2;	/* B:   Hoat adapter configuration 2 */
+	u8 NVM_ModelByte0;	/* 4:   Model number (byte 0) */
+	u8 NVM_ModelByte1;	/* 5:   Model number (byte 1) */
+	u8 NVM_ModelInfo;	/* 6:   Model information         */
+	u8 NVM_NumOfCh;	/* 7:   Number of SCSI channel */
+	u8 NVM_BIOSConfig1;	/* 8:   BIOS configuration 1  */
+	u8 NVM_BIOSConfig2;	/* 9:   BIOS configuration 2  */
+	u8 NVM_HAConfig1;	/* A:   Hoat adapter configuration 1 */
+	u8 NVM_HAConfig2;	/* B:   Hoat adapter configuration 2 */
 	NVRAM_SCSI NVM_SCSIInfo[2];
-	UCHAR NVM_reserved[10];
+	u8 NVM_reserved[10];
 	/* ---------- CheckSum ----------       */
-	USHORT NVM_CheckSum;	/* 0x3E, 0x3F: Checksum of NVRam        */
+	u16 NVM_CheckSum;	/* 0x3E, 0x3F: Checksum of NVRam        */
 } NVRAM, *PNVRAM;
 
 /* Bios Configuration for nvram->BIOSConfig1                            */
@@ -681,19 +641,6 @@
 #define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
 #define SCSICMD_RequestSense    0x03
 
-typedef struct _HCSinfo {
-	ULONG base;
-	UCHAR vec;
-	UCHAR bios;		/* High byte of BIOS address */
-	USHORT BaseAndBios;	/* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
-} HCSINFO;
-
-#define TUL_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)(x+y)) ))
-#define TUL_RDLONG(x,y)         (ULONG)(inl((int)((ULONG)(x+y)) ))
-#define TUL_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
-#define TUL_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
-#define TUL_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
-
 #define SCSI_ABORT_SNOOZE 0
 #define SCSI_ABORT_SUCCESS 1
 #define SCSI_ABORT_PENDING 2
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fa6ff29..072f577 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -540,32 +540,6 @@
 }
 
 /**
- * ipr_unmap_sglist - Unmap scatterlist if mapped
- * @ioa_cfg:	ioa config struct
- * @ipr_cmd:	ipr command struct
- *
- * Return value:
- * 	nothing
- **/
-static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg,
-			     struct ipr_cmnd *ipr_cmd)
-{
-	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-
-	if (ipr_cmd->dma_use_sg) {
-		if (scsi_cmd->use_sg > 0) {
-			pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer,
-				     scsi_cmd->use_sg,
-				     scsi_cmd->sc_data_direction);
-		} else {
-			pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle,
-					 scsi_cmd->request_bufflen,
-					 scsi_cmd->sc_data_direction);
-		}
-	}
-}
-
-/**
  * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
  * @ioa_cfg:	ioa config struct
  * @clr_ints:     interrupts to clear
@@ -677,7 +651,7 @@
 
 	scsi_cmd->result |= (DID_ERROR << 16);
 
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	scsi_cmd->scsi_done(scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 }
@@ -4292,93 +4266,55 @@
 static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
 			   struct ipr_cmnd *ipr_cmd)
 {
-	int i;
-	struct scatterlist *sglist;
+	int i, nseg;
+	struct scatterlist *sg;
 	u32 length;
 	u32 ioadl_flags = 0;
 	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
 	struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
 
-	length = scsi_cmd->request_bufflen;
-
-	if (length == 0)
+	length = scsi_bufflen(scsi_cmd);
+	if (!length)
 		return 0;
 
-	if (scsi_cmd->use_sg) {
-		ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev,
-						 scsi_cmd->request_buffer,
-						 scsi_cmd->use_sg,
-						 scsi_cmd->sc_data_direction);
-
-		if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-			ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-			ioarcb->write_data_transfer_length = cpu_to_be32(length);
-			ioarcb->write_ioadl_len =
-				cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-		} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_READ;
-			ioarcb->read_data_transfer_length = cpu_to_be32(length);
-			ioarcb->read_ioadl_len =
-				cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-		}
-
-		sglist = scsi_cmd->request_buffer;
-
-		if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
-			ioadl = ioarcb->add_data.u.ioadl;
-			ioarcb->write_ioadl_addr =
-				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-					    offsetof(struct ipr_ioarcb, add_data));
-			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-		}
-
-		for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
-			ioadl[i].flags_and_data_len =
-				cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
-			ioadl[i].address =
-				cpu_to_be32(sg_dma_address(&sglist[i]));
-		}
-
-		if (likely(ipr_cmd->dma_use_sg)) {
-			ioadl[i-1].flags_and_data_len |=
-				cpu_to_be32(IPR_IOADL_FLAGS_LAST);
-			return 0;
-		} else
-			dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
-	} else {
-		if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-			ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-			ioarcb->write_data_transfer_length = cpu_to_be32(length);
-			ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-		} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-			ioadl_flags = IPR_IOADL_FLAGS_READ;
-			ioarcb->read_data_transfer_length = cpu_to_be32(length);
-			ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-		}
-
-		ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev,
-						     scsi_cmd->request_buffer, length,
-						     scsi_cmd->sc_data_direction);
-
-		if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
-			ioadl = ioarcb->add_data.u.ioadl;
-			ioarcb->write_ioadl_addr =
-				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-					    offsetof(struct ipr_ioarcb, add_data));
-			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-			ipr_cmd->dma_use_sg = 1;
-			ioadl[0].flags_and_data_len =
-				cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
-			ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle);
-			return 0;
-		} else
-			dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n");
+	nseg = scsi_dma_map(scsi_cmd);
+	if (nseg < 0) {
+		dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+		return -1;
 	}
 
-	return -1;
+	ipr_cmd->dma_use_sg = nseg;
+
+	if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_WRITE;
+		ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
+		ioarcb->write_data_transfer_length = cpu_to_be32(length);
+		ioarcb->write_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	} else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_READ;
+		ioarcb->read_data_transfer_length = cpu_to_be32(length);
+		ioarcb->read_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	}
+
+	if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+		ioadl = ioarcb->add_data.u.ioadl;
+		ioarcb->write_ioadl_addr =
+			cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+				    offsetof(struct ipr_ioarcb, add_data));
+		ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+	}
+
+	scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) {
+		ioadl[i].flags_and_data_len =
+			cpu_to_be32(ioadl_flags | sg_dma_len(sg));
+		ioadl[i].address = cpu_to_be32(sg_dma_address(sg));
+	}
+
+	ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
+	return 0;
 }
 
 /**
@@ -4441,7 +4377,7 @@
 			res->needs_sync_complete = 1;
 		res->in_erp = 0;
 	}
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 	scsi_cmd->scsi_done(scsi_cmd);
 }
@@ -4819,7 +4755,7 @@
 		break;
 	}
 
-	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 	scsi_cmd->scsi_done(scsi_cmd);
 }
@@ -4840,10 +4776,10 @@
 	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 	u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
-	scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len);
+	scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
 
 	if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
-		ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+		scsi_dma_unmap(ipr_cmd->scsi_cmd);
 		list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 		scsi_cmd->scsi_done(scsi_cmd);
 	} else
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 8b704f7..84f4f5d 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -211,19 +211,6 @@
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include <linux/blk.h>
-#include "sd.h"
-#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
-#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#ifndef __devexit_p
-#define __devexit_p(x) x
-#endif
-#else
-#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
-#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
-#endif
-
 #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
                          DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
                          PCI_DMA_BIDIRECTIONAL : \
@@ -381,24 +368,13 @@
 	.eh_abort_handler	= ips_eh_abort,
 	.eh_host_reset_handler	= ips_eh_reset,
 	.proc_name		= "ips",
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
 	.proc_info		= ips_proc_info,
 	.slave_configure	= ips_slave_configure,
-#else
-	.proc_info		= ips_proc24_info,
-	.select_queue_depths	= ips_select_queue_depth,
-#endif
 	.bios_param		= ips_biosparam,
 	.this_id		= -1,
 	.sg_tablesize		= IPS_MAX_SG,
 	.cmd_per_lun		= 3,
 	.use_clustering		= ENABLE_CLUSTERING,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	.use_new_eh_code	= 1,
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-    .highmem_io          = 1,   
-#endif
 };
 
 
@@ -731,7 +707,7 @@
 	/* free IRQ */
 	free_irq(ha->irq, ha);
 
-	IPS_REMOVE_HOST(sh);
+	scsi_remove_host(sh);
 	scsi_host_put(sh);
 
 	ips_released_controllers++;
@@ -813,7 +789,6 @@
 	ips_ha_t *ha;
 	ips_copp_wait_item_t *item;
 	int ret;
-	unsigned long cpu_flags;
 	struct Scsi_Host *host;
 
 	METHOD_TRACE("ips_eh_abort", 1);
@@ -830,7 +805,7 @@
 	if (!ha->active)
 		return (FAILED);
 
-	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+	spin_lock(host->host_lock);
 
 	/* See if the command is on the copp queue */
 	item = ha->copp_waitlist.head;
@@ -851,7 +826,7 @@
 		ret = (FAILED);
 	}
 
-	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+	spin_unlock(host->host_lock);
 	return ret;
 }
 
@@ -1176,18 +1151,10 @@
 /*   Set bios geometry for the controller                                   */
 /*                                                                          */
 /****************************************************************************/
-static int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ips_biosparam(Disk * disk, kdev_t dev, int geom[])
-{
-	ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
-	unsigned long capacity = disk->capacity;
-#else
-ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-	      sector_t capacity, int geom[])
+static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+			 sector_t capacity, int geom[])
 {
 	ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
-#endif
 	int heads;
 	int sectors;
 	int cylinders;
@@ -1225,70 +1192,6 @@
 	return (0);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* ips_proc24_info is a wrapper around ips_proc_info *
- * for compatibility with the 2.4 scsi parameters    */
-static int
-ips_proc24_info(char *buffer, char **start, off_t offset, int length,
-		              int hostno, int func)
-{
-	int i;
-
-	for (i = 0; i < ips_next_controller; i++) {
-		if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
-			return ips_proc_info(ips_sh[i], buffer, start,
-					     offset, length, func);
-		}
-	}
-	return -EINVAL;	
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_select_queue_depth                                     */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Select queue depths for the devices on the contoller                   */
-/*                                                                          */
-/****************************************************************************/
-static void
-ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs)
-{
-	struct scsi_device *device;
-	ips_ha_t *ha;
-	int count = 0;
-	int min;
-
-	ha = IPS_HA(host);
-	min = ha->max_cmds / 4;
-
-	for (device = scsi_devs; device; device = device->next) {
-		if (device->host == host) {
-			if ((device->channel == 0) && (device->type == 0))
-				count++;
-		}
-	}
-
-	for (device = scsi_devs; device; device = device->next) {
-		if (device->host == host) {
-			if ((device->channel == 0) && (device->type == 0)) {
-				device->queue_depth =
-				    (ha->max_cmds - 1) / count;
-				if (device->queue_depth < min)
-					device->queue_depth = min;
-			} else {
-				device->queue_depth = 2;
-			}
-
-			if (device->queue_depth < 2)
-				device->queue_depth = 2;
-		}
-	}
-}
-
-#else
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_slave_configure                                        */
@@ -1316,7 +1219,6 @@
 	SDptr->skip_ms_page_3f = 1;
 	return 0;
 }
-#endif
 
 /****************************************************************************/
 /*                                                                          */
@@ -1331,7 +1233,6 @@
 do_ipsintr(int irq, void *dev_id)
 {
 	ips_ha_t *ha;
-	unsigned long cpu_flags;
 	struct Scsi_Host *host;
 	int irqstatus;
 
@@ -1347,16 +1248,16 @@
 		return IRQ_HANDLED;
 	}
 
-	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+	spin_lock(host->host_lock);
 
 	if (!ha->active) {
-		IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+		spin_unlock(host->host_lock);
 		return IRQ_HANDLED;
 	}
 
 	irqstatus = (*ha->func.intr) (ha);
 
-	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+	spin_unlock(host->host_lock);
 
 	/* start the next command */
 	ips_next(ha, IPS_INTR_ON);
@@ -2730,7 +2631,6 @@
 	struct scsi_cmnd *q;
 	ips_copp_wait_item_t *item;
 	int ret;
-	unsigned long cpu_flags = 0;
 	struct Scsi_Host *host;
 	METHOD_TRACE("ips_next", 1);
 
@@ -2742,7 +2642,7 @@
 	 * this command won't time out
 	 */
 	if (intr == IPS_INTR_ON)
-		IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+		spin_lock(host->host_lock);
 
 	if ((ha->subsys->param[3] & 0x300000)
 	    && (ha->scb_activelist.count == 0)) {
@@ -2769,14 +2669,14 @@
 		item = ips_removeq_copp_head(&ha->copp_waitlist);
 		ha->num_ioctl++;
 		if (intr == IPS_INTR_ON)
-			IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+			spin_unlock(host->host_lock);
 		scb->scsi_cmd = item->scsi_cmd;
 		kfree(item);
 
 		ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
 
 		if (intr == IPS_INTR_ON)
-			IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+			spin_lock(host->host_lock);
 		switch (ret) {
 		case IPS_FAILURE:
 			if (scb->scsi_cmd) {
@@ -2846,7 +2746,7 @@
 		SC = ips_removeq_wait(&ha->scb_waitlist, q);
 
 		if (intr == IPS_INTR_ON)
-			IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);	/* Unlock HA after command is taken off queue */
+			spin_unlock(host->host_lock);	/* Unlock HA after command is taken off queue */
 
 		SC->result = DID_OK;
 		SC->host_scribble = NULL;
@@ -2919,7 +2819,7 @@
 			scb->dcdb.transfer_length = 0;
 		}
 		if (intr == IPS_INTR_ON)
-			IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+			spin_lock(host->host_lock);
 
 		ret = ips_send_cmd(ha, scb);
 
@@ -2958,7 +2858,7 @@
 	}			/* end while */
 
 	if (intr == IPS_INTR_ON)
-		IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+		spin_unlock(host->host_lock);
 }
 
 /****************************************************************************/
@@ -7004,7 +6904,6 @@
 	kfree(oldha);
 	ips_sh[index] = sh;
 	ips_ha[index] = ha;
-	IPS_SCSI_SET_DEVICE(sh, ha);
 
 	/* Store away needed values for later use */
 	sh->io_port = ha->io_addr;
@@ -7016,17 +6915,16 @@
 	sh->cmd_per_lun = sh->hostt->cmd_per_lun;
 	sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
 	sh->use_clustering = sh->hostt->use_clustering;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 	sh->max_sectors = 128;
-#endif
 
 	sh->max_id = ha->ntargets;
 	sh->max_lun = ha->nlun;
 	sh->max_channel = ha->nbus - 1;
 	sh->can_queue = ha->max_cmds - 1;
 
-	IPS_ADD_HOST(sh, NULL);
+	scsi_add_host(sh, NULL);
+	scsi_scan_host(sh);
+
 	return 0;
 }
 
@@ -7069,7 +6967,7 @@
 		return -ENODEV;
 	ips_driver_template.module = THIS_MODULE;
 	ips_order_controllers();
-	if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+	if (!ips_detect(&ips_driver_template)) {
 		pci_unregister_driver(&ips_pci_driver);
 		return -ENODEV;
 	}
@@ -7087,7 +6985,6 @@
 static void __exit
 ips_module_exit(void)
 {
-	IPS_UNREGISTER_HOSTS(&ips_driver_template);
 	pci_unregister_driver(&ips_pci_driver);
 	unregister_reboot_notifier(&ips_notifier);
 }
@@ -7443,15 +7340,9 @@
 	return SUCCESS;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
 MODULE_LICENSE("GPL");
-#endif
-
 MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
-
-#ifdef MODULE_VERSION
 MODULE_VERSION(IPS_VER_STRING);
-#endif
 
 
 /*
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index b726dcc..24123d5 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -58,10 +58,6 @@
    /*
     * Some handy macros
     */
-   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
-      #define IPS_HIGHIO
-   #endif
-
    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
    #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
    #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
@@ -84,38 +80,8 @@
     #define IPS_SGLIST_SIZE(ha)       (IPS_USE_ENH_SGLIST(ha) ? \
                                          sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST))
 
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
-      #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 )
-      #define scsi_set_pci_device(sh,dev) (0)
-   #endif
-
-   #ifndef IRQ_NONE
-      typedef void irqreturn_t;
-      #define IRQ_NONE
-      #define IRQ_HANDLED
-      #define IRQ_RETVAL(x)
-   #endif
-   
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-      #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
-      #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
-      #define IPS_ADD_HOST(shost,device)
-      #define IPS_REMOVE_HOST(shost)
-      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_pci_device(sh, (ha)->pcidev)
-      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
-            printk(level "%s %s:" format , "ips" ,     \
-            (pcidev)->slot_name , ## arg)
-      #define scsi_host_alloc(sh,size)         scsi_register(sh,size)
-      #define scsi_host_put(sh)             scsi_unregister(sh)
-   #else
-      #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
-      #define IPS_UNREGISTER_HOSTS(SHT)
-      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
-      #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
-      #define IPS_SCSI_SET_DEVICE(sh,ha)   do { } while (0)
-      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
+  #define IPS_PRINTK(level, pcidev, format, arg...)                 \
             dev_printk(level , &((pcidev)->dev) , format , ## arg)
-   #endif
 
    #define MDELAY(n)			\
 	do {				\
@@ -134,7 +100,7 @@
    #define pci_dma_hi32(a)         ((a >> 16) >> 16)
    #define pci_dma_lo32(a)         (a & 0xffffffff)
 
-   #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
+   #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
       #define IPS_ENABLE_DMA64        (1)
    #else
       #define IPS_ENABLE_DMA64        (0)
@@ -451,16 +417,10 @@
    /*
     * Scsi_Host Template
     */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-   static int ips_proc24_info(char *, char **, off_t, int, int, int);
-   static void ips_select_queue_depth(struct Scsi_Host *, struct scsi_device *);
-   static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
-#else
    static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int geom[]);
    static int ips_slave_configure(struct scsi_device *SDptr);
-#endif
 
 /*
  * Raid Command Formats
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 81e497d..0140766 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -1,6 +1,6 @@
 /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
  *
- * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
+ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
  */
 
 #include <linux/kernel.h>
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index b4b5269..d70ddfd 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -76,8 +76,8 @@
 			hs = DID_NO_CONNECT;
 			break;
 		case SAS_DATA_UNDERRUN:
-			sc->resid = ts->residual;
-			if (sc->request_bufflen - sc->resid < sc->underflow)
+			scsi_set_resid(sc, ts->residual);
+			if (scsi_bufflen(sc) - scsi_get_resid(sc) < sc->underflow)
 				hs = DID_ERROR;
 			break;
 		case SAS_DATA_OVERRUN:
@@ -161,9 +161,9 @@
 	task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
 	memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
 
-	task->scatter = cmd->request_buffer;
-	task->num_scatter = cmd->use_sg;
-	task->total_xfer_len = cmd->request_bufflen;
+	task->scatter = scsi_sglist(cmd);
+	task->num_scatter = scsi_sg_count(cmd);
+	task->total_xfer_len = scsi_bufflen(cmd);
 	task->data_dir = cmd->sc_data_direction;
 
 	task->task_done = sas_scsi_task_done;
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 5806ede..b12ad7c 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -77,7 +77,7 @@
 		for (i = 0; i < cmd->cmd_len; ++i)
 			printk(" %.2x", cmd->cmnd[i]);
 		printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
-		       cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
+		       scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
 	}
 #endif
 
@@ -173,8 +173,7 @@
 	writeb(CMD_SELECT, &regs->command);
 	state->phase = selecting;
 
-	if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
-		set_dma_cmds(state, cmd);
+	set_dma_cmds(state, cmd);
 }
 
 static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id)
@@ -262,7 +261,7 @@
 		writeb(CMD_NOP, &regs->command);
 		/* set DMA controller going if any data to transfer */
 		if ((stat & (STAT_MSG|STAT_CD)) == 0
-		    && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
+		    && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
 			nb = cmd->SCp.this_residual;
 			if (nb > 0xfff0)
 				nb = 0xfff0;
@@ -310,14 +309,7 @@
 			printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
 		}
 		writel(RUN << 16, &dma->control);	/* stop dma */
-		if (cmd->use_sg != 0) {
-			pci_unmap_sg(state->pdev,
-				(struct scatterlist *)cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-		} else {
-			pci_unmap_single(state->pdev, state->dma_addr,
-				cmd->request_bufflen, cmd->sc_data_direction);
-		}
+		scsi_dma_unmap(cmd);
 		/* should check dma status */
 		writeb(CMD_I_COMPLETE, &regs->command);
 		state->phase = completing;
@@ -365,47 +357,35 @@
  */
 static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
 {
-	int i, dma_cmd, total;
+	int i, dma_cmd, total, nseg;
 	struct scatterlist *scl;
 	struct dbdma_cmd *dcmds;
 	dma_addr_t dma_addr;
 	u32 dma_len;
 
+	nseg = scsi_dma_map(cmd);
+	BUG_ON(nseg < 0);
+	if (!nseg)
+		return;
+
 	dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
 			OUTPUT_MORE : INPUT_MORE;
 	dcmds = state->dma_cmds;
-	if (cmd->use_sg > 0) {
-		int nseg;
+	total = 0;
 
-		total = 0;
-		scl = (struct scatterlist *) cmd->request_buffer;
-		nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
-				cmd->sc_data_direction);
-		for (i = 0; i < nseg; ++i) {
-			dma_addr = sg_dma_address(scl);
-			dma_len = sg_dma_len(scl);
-			if (dma_len > 0xffff)
-				panic("mac53c94: scatterlist element >= 64k");
-			total += dma_len;
-			st_le16(&dcmds->req_count, dma_len);
-			st_le16(&dcmds->command, dma_cmd);
-			st_le32(&dcmds->phy_addr, dma_addr);
-			dcmds->xfer_status = 0;
-			++scl;
-			++dcmds;
-		}
-	} else {
-		total = cmd->request_bufflen;
-		if (total > 0xffff)
-			panic("mac53c94: transfer size >= 64k");
-		dma_addr = pci_map_single(state->pdev, cmd->request_buffer,
-					  total, cmd->sc_data_direction);
-		state->dma_addr = dma_addr;
-		st_le16(&dcmds->req_count, total);
+	scsi_for_each_sg(cmd, scl, nseg, i) {
+		dma_addr = sg_dma_address(scl);
+		dma_len = sg_dma_len(scl);
+		if (dma_len > 0xffff)
+			panic("mac53c94: scatterlist element >= 64k");
+		total += dma_len;
+		st_le16(&dcmds->req_count, dma_len);
+		st_le16(&dcmds->command, dma_cmd);
 		st_le32(&dcmds->phy_addr, dma_addr);
 		dcmds->xfer_status = 0;
 		++dcmds;
 	}
+
 	dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
 	st_le16(&dcmds[-1].command, dma_cmd);
 	st_le16(&dcmds->command, DBDMA_STOP);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 3cce75d..40ee07d 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -3571,7 +3571,7 @@
 			/*
 			 * The user passthru structure
 			 */
-			upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr;
+			upthru = (mega_passthru __user *)(unsigned long)MBOX(uioc)->xferaddr;
 
 			/*
 			 * Copy in the user passthru here.
@@ -3623,7 +3623,7 @@
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char __user *)uxferaddr,
+				if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
 							pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 					goto freemem_and_return;
@@ -3649,7 +3649,7 @@
 			 * Is data going up-stream
 			 */
 			if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char __user *)uxferaddr, data,
+				if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
 							pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 				}
@@ -3702,7 +3702,7 @@
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char __user *)uxferaddr,
+				if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
 							uioc.xferlen) ) {
 
 					pci_free_consistent(pdev,
@@ -3742,7 +3742,7 @@
 			 * Is data going up-stream
 			 */
 			if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char __user *)uxferaddr, data,
+				if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
 							uioc.xferlen) ) {
 
 					rval = (-EFAULT);
diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
deleted file mode 100644
index 575fe6f..0000000
--- a/drivers/scsi/mvme16x.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
- *
- * Based on work by Alan Hourihane
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/mvme16xhw.h>
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "53c7xx.h"
-#include "mvme16x.h"
-
-#include<linux/stat.h>
-
-
-int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
-{
-    static unsigned char called = 0;
-    int clock;
-    long long options;
-
-    if (!MACH_IS_MVME16x)
-		return 0;
-    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
-	printk ("SCSI detection disabled, SCSI chip not present\n");
-	return 0;
-    }
-    if (called)
-	return 0;
-
-    tpnt->proc_name = "MVME16x";
-
-    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
-
-    clock = 66000000;	/* 66MHz SCSI Clock */
-
-    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
-			0, MVME16x_IRQ_SCSI, DMA_NONE,
-			options, clock);
-    called = 1;
-    return 1;
-}
-
-static int mvme16x_scsi_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.name			= "MVME16x NCR53c710 SCSI",
-	.detect			= mvme16x_scsi_detect,
-	.release		= mvme16x_scsi_release,
-	.queuecommand		= NCR53c7xx_queue_command,
-	.abort			= NCR53c7xx_abort,
-	.reset			= NCR53c7xx_reset,
-	.can_queue		= 24,
-	.this_id		= 7,
-	.sg_tablesize		= 63,
-	.cmd_per_lun		= 3,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h
deleted file mode 100644
index 73e33b3..0000000
--- a/drivers/scsi/mvme16x.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef MVME16x_SCSI_H
-#define MVME16x_SCSI_H
-
-#include <linux/types.h>
-
-int mvme16x_scsi_detect(struct scsi_host_template *);
-const char *NCR53c7x0_info(void);
-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int NCR53c7xx_abort(Scsi_Cmnd *);
-int NCR53c7x0_release (struct Scsi_Host *);
-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 3
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 24
-#endif
-
-#include <scsi/scsicam.h>
-
-#endif /* MVME16x_SCSI_H */
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index f6f561d..8cc9e64 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -49,10 +49,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-# include <linux/blk.h>
-#endif
-
 #include "nsp32.h"
 
 
@@ -199,17 +195,9 @@
 static void __exit    exit_nsp32  (void);
 
 /* struct struct scsi_host_template */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
-#else
-static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
-#endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 static int         nsp32_detect      (struct pci_dev *pdev);
-#else
-static int         nsp32_detect      (struct scsi_host_template *);
-#endif
 static int         nsp32_queuecommand(struct scsi_cmnd *,
 		void (*done)(struct scsi_cmnd *));
 static const char *nsp32_info        (struct Scsi_Host *);
@@ -296,15 +284,7 @@
 	.eh_abort_handler       	= nsp32_eh_abort,
 	.eh_bus_reset_handler		= nsp32_eh_bus_reset,
 	.eh_host_reset_handler		= nsp32_eh_host_reset,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
-	.detect				= nsp32_detect,
-	.release			= nsp32_release,
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
-	.use_new_eh_code        	= 1,
-#else
 /*	.highmem_io			= 1, */
-#endif
 };
 
 #include "nsp32_io.h"
@@ -739,7 +719,7 @@
 	command = 0;
 	command |= (TRANSFER_GO | ALL_COUNTER_CLR);
 	if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-		if (SCpnt->request_bufflen > 0) {
+		if (scsi_bufflen(SCpnt) > 0) {
 			command |= BM_START;
 		}
 	} else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@ -888,31 +868,28 @@
 static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
 {
 	nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-	struct scatterlist   *sgl;
+	struct scatterlist *sg;
 	nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
 	int num, i;
 	u32_le l;
 
-	if (SCpnt->request_bufflen == 0) {
-		return TRUE;
-	}
-
 	if (sgt == NULL) {
 		nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null");
 		return FALSE;
 	}
 
-	if (SCpnt->use_sg) {
-		sgl = (struct scatterlist *)SCpnt->request_buffer;
-		num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
-				 SCpnt->sc_data_direction);
-		for (i = 0; i < num; i++) {
+	num = scsi_dma_map(SCpnt);
+	if (!num)
+		return TRUE;
+	else if (num < 0)
+		return FALSE;
+	else {
+		scsi_for_each_sg(SCpnt, sg, num, i) {
 			/*
 			 * Build nsp32_sglist, substitute sg dma addresses.
 			 */
-			sgt[i].addr = cpu_to_le32(sg_dma_address(sgl));
-			sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
-			sgl++;
+			sgt[i].addr = cpu_to_le32(sg_dma_address(sg));
+			sgt[i].len  = cpu_to_le32(sg_dma_len(sg));
 
 			if (le32_to_cpu(sgt[i].len) > 0x10000) {
 				nsp32_msg(KERN_ERR,
@@ -929,23 +906,6 @@
 		/* set end mark */
 		l = le32_to_cpu(sgt[num-1].len);
 		sgt[num-1].len = cpu_to_le32(l | SGTEND);
-
-	} else {
-		SCpnt->SCp.have_data_in	= pci_map_single(data->Pci,
-			SCpnt->request_buffer, SCpnt->request_bufflen,
-			SCpnt->sc_data_direction);
-
-		sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
-		sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
-
-		if (SCpnt->request_bufflen > 0x10000) {
-			nsp32_msg(KERN_ERR,
-				  "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
-			return FALSE;
-		}
-		nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
-			  le32_to_cpu(sgt[0].addr),
-			  le32_to_cpu(sgt[0].len ));
 	}
 
 	return TRUE;
@@ -962,7 +922,7 @@
 		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
 		  SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
-		  SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
+		  scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
 
 	if (data->CurrentSC != NULL) {
 		nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
@@ -994,10 +954,10 @@
 	data->CurrentSC      = SCpnt;
 	SCpnt->SCp.Status    = CHECK_CONDITION;
 	SCpnt->SCp.Message   = 0;
-	SCpnt->resid         = SCpnt->request_bufflen;
+	scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
 
-	SCpnt->SCp.ptr		    = (char *) SCpnt->request_buffer;
-	SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
+	SCpnt->SCp.ptr		    = (char *)scsi_sglist(SCpnt);
+	SCpnt->SCp.this_residual    = scsi_bufflen(SCpnt);
 	SCpnt->SCp.buffer	    = NULL;
 	SCpnt->SCp.buffers_residual = 0;
 
@@ -1210,13 +1170,9 @@
 	unsigned long flags;
 	int ret;
 	int handled = 0;
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 	struct Scsi_Host *host = data->Host;
+
 	spin_lock_irqsave(host->host_lock, flags);
-#else
-	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	/*
 	 * IRQ check, then enable IRQ mask
@@ -1312,7 +1268,7 @@
 		}
 
 		if ((auto_stat & DATA_IN_PHASE) &&
-		    (SCpnt->resid > 0) &&
+		    (scsi_get_resid(SCpnt) > 0) &&
 		    ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) {
 			printk( "auto+fifo\n");
 			//nsp32_pio_read(SCpnt);
@@ -1333,7 +1289,7 @@
 			nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
 				    nsp32_read4(base, SAVED_SACK_CNT));
 
-			SCpnt->resid = 0; /* all data transfered! */
+			scsi_set_resid(SCpnt, 0); /* all data transfered! */
 		}
 
 		/*
@@ -1480,11 +1436,7 @@
 	nsp32_write2(base, IRQ_CONTROL, 0);
 
  out2:
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 	spin_unlock_irqrestore(host->host_lock, flags);
-#else
-	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 
 	nsp32_dbg(NSP32_DEBUG_INTR, "exit");
 
@@ -1499,28 +1451,15 @@
 			nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
 		} \
 	} while(0)
-static int nsp32_proc_info(
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-	struct Scsi_Host *host,
-#endif
-	char             *buffer,
-	char            **start,
-	off_t             offset,
-	int               length,
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-	int               hostno,
-#endif
-	int               inout)
+
+static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+			   off_t offset, int length, int inout)
 {
 	char             *pos = buffer;
 	int               thislength;
 	unsigned long     flags;
 	nsp32_hw_data    *data;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
 	int               hostno;
-#else
-	struct Scsi_Host *host;
-#endif
 	unsigned int      base;
 	unsigned char     mode_reg;
 	int               id, speed;
@@ -1531,15 +1470,7 @@
 		return -EINVAL;
 	}
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
 	hostno = host->host_no;
-#else
-	/* search this HBA host */
-	host = scsi_host_hn_get(hostno);
-	if (host == NULL) {
-		return -ESRCH;
-	}
-#endif
 	data = (nsp32_hw_data *)host->hostdata;
 	base = host->io_port;
 
@@ -1626,25 +1557,8 @@
 	nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
 	unsigned int   base = SCpnt->device->host->io_port;
 
-	/*
-	 * unmap pci
-	 */
-	if (SCpnt->request_bufflen == 0) {
-		goto skip;
-	}
+	scsi_dma_unmap(SCpnt);
 
-	if (SCpnt->use_sg) {
-		pci_unmap_sg(data->Pci,
-			     (struct scatterlist *)SCpnt->request_buffer,
-			     SCpnt->use_sg, SCpnt->sc_data_direction);
-	} else {
-		pci_unmap_single(data->Pci,
-				 (u32)SCpnt->SCp.have_data_in,
-				 SCpnt->request_bufflen,
-				 SCpnt->sc_data_direction);
-	}
-
- skip:
 	/*
 	 * clear TRANSFERCONTROL_BM_START
 	 */
@@ -1800,7 +1714,7 @@
 		SCpnt->SCp.Message = 0;
 		nsp32_dbg(NSP32_DEBUG_BUSFREE, 
 			  "normal end stat=0x%x resid=0x%x\n",
-			  SCpnt->SCp.Status, SCpnt->resid);
+			  SCpnt->SCp.Status, scsi_get_resid(SCpnt));
 		SCpnt->result = (DID_OK             << 16) |
 			        (SCpnt->SCp.Message <<  8) |
 			        (SCpnt->SCp.Status  <<  0);
@@ -1844,7 +1758,7 @@
 	unsigned int          restlen, sentlen;
 	u32_le                len, addr;
 
-	nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
+	nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt));
 
 	/* adjust saved SACK count with 4 byte start address boundary */
 	s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
@@ -1888,12 +1802,12 @@
 	return;
 
  last:
-	if (SCpnt->resid < sentlen) {
+	if (scsi_get_resid(SCpnt) < sentlen) {
 		nsp32_msg(KERN_ERR, "resid underflow");
 	}
 
-	SCpnt->resid -= sentlen;
-	nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
+	scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen);
+	nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt));
 
 	/* update hostdata and lun */
 
@@ -2022,7 +1936,7 @@
 	transfer = 0;
 	transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
 	if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-		if (SCpnt->request_bufflen > 0) {
+		if (scsi_bufflen(SCpnt) > 0) {
 			transfer |= BM_START;
 		}
 	} else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@ -2674,17 +2588,7 @@
  *	0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
  *	0xc00-0xfff: CardBus status registers
  */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-#define DETECT_OK 0
-#define DETECT_NG 1
-#define PCIDEV    pdev
 static int nsp32_detect(struct pci_dev *pdev)
-#else
-#define DETECT_OK 1
-#define DETECT_NG 0
-#define PCIDEV    (data->Pci)
-static int nsp32_detect(struct scsi_host_template *sht)
-#endif
 {
 	struct Scsi_Host *host;	/* registered host structure */
 	struct resource  *res;
@@ -2697,11 +2601,7 @@
 	/*
 	 * register this HBA as SCSI device
 	 */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
-#else
-	host = scsi_register(sht, sizeof(nsp32_hw_data));
-#endif
 	if (host == NULL) {
 		nsp32_msg (KERN_ERR, "failed to scsi register");
 		goto err;
@@ -2719,9 +2619,6 @@
 	host->unique_id = data->BaseAddress;
 	host->n_io_port	= data->NumAddress;
 	host->base      = (unsigned long)data->MmioAddress;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
-	scsi_set_pci_device(host, PCIDEV);
-#endif
 
 	data->Host      = host;
 	spin_lock_init(&(data->Lock));
@@ -2776,7 +2673,7 @@
 	/*
 	 * setup DMA 
 	 */
-	if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
 		nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
 		goto scsi_unregister;
 	}
@@ -2784,7 +2681,7 @@
 	/*
 	 * allocate autoparam DMA resource.
 	 */
-	data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
+	data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr));
 	if (data->autoparam == NULL) {
 		nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
 		goto scsi_unregister;
@@ -2793,7 +2690,7 @@
 	/*
 	 * allocate scatter-gather DMA resource.
 	 */
-	data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+	data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE,
 					     &(data->sg_paddr));
 	if (data->sg_list == NULL) {
 		nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
@@ -2883,16 +2780,14 @@
 		goto free_irq;
         }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-	ret = scsi_add_host(host, &PCIDEV->dev);
+	ret = scsi_add_host(host, &pdev->dev);
 	if (ret) {
 		nsp32_msg(KERN_ERR, "failed to add scsi host");
 		goto free_region;
 	}
 	scsi_scan_host(host);
-#endif
-	pci_set_drvdata(PCIDEV, host);
-	return DETECT_OK;
+	pci_set_drvdata(pdev, host);
+	return 0;
 
  free_region:
 	release_region(host->io_port, host->n_io_port);
@@ -2901,22 +2796,19 @@
 	free_irq(host->irq, data);
 
  free_sg_list:
-	pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+	pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE,
 			    data->sg_list, data->sg_paddr);
 
  free_autoparam:
-	pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
+	pci_free_consistent(pdev, sizeof(nsp32_autoparam),
 			    data->autoparam, data->auto_paddr);
 	
  scsi_unregister:
 	scsi_host_put(host);
 
  err:
-	return DETECT_NG;
+	return 1;
 }
-#undef DETECT_OK
-#undef DETECT_NG
-#undef PCIDEV
 
 static int nsp32_release(struct Scsi_Host *host)
 {
@@ -3525,11 +3417,7 @@
 
 	pci_set_master(pdev);
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	ret = nsp32_detect(pdev);
-#else
-	ret = scsi_register_host(&nsp32_template);
-#endif
 
 	nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s",
 		  pdev->irq,
@@ -3544,25 +3432,17 @@
 
 static void __devexit nsp32_remove(struct pci_dev *pdev)
 {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
-#endif
 
 	nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
         scsi_remove_host(host);
 
 	nsp32_release(host);
 
 	scsi_host_put(host);
-#else
-	scsi_unregister_host(&nsp32_template);	
-#endif
 }
 
-
-
 static struct pci_driver nsp32_driver = {
 	.name		= "nsp32",
 	.id_table	= nsp32_pci_table,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index ffe75c4..2695b71 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -370,8 +370,6 @@
 	DEB(unsigned char seq_reg;)
 	unsigned char status, int_reg;
 	unsigned char pio_status;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
 	int port_base = dev->io_port;
 	struct sym53c500_data *data =
 	    (struct sym53c500_data *)dev->hostdata;
@@ -434,20 +432,19 @@
 	switch (status & 0x07) {	/* scsi phase */
 	case 0x00:			/* DATA-OUT */
 		if (int_reg & 0x10) {	/* Target requesting info transfer */
+			struct scatterlist *sg;
+			int i;
+
 			curSC->SCp.phase = data_out;
 			VDEB(printk("SYM53C500: Data-Out phase\n"));
 			outb(FLUSH_FIFO, port_base + CMD_REG);
-			LOAD_DMA_COUNT(port_base, curSC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC));	/* Max transfer size */
 			outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
-			if (!curSC->use_sg)	/* Don't use scatter-gather */
-				SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
-			else {	/* use scatter-gather */
-				sgcount = curSC->use_sg;
-				sglist = curSC->request_buffer;
-				while (sgcount--) {
-					SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
+
+			scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+				SYM53C500_pio_write(fast_pio, port_base,
+						    page_address(sg->page) + sg->offset,
+						    sg->length);
 			}
 			REG0(port_base);
 		}
@@ -455,20 +452,19 @@
 
 	case 0x01:		/* DATA-IN */
 		if (int_reg & 0x10) {	/* Target requesting info transfer */
+			struct scatterlist *sg;
+			int i;
+
 			curSC->SCp.phase = data_in;
 			VDEB(printk("SYM53C500: Data-In phase\n"));
 			outb(FLUSH_FIFO, port_base + CMD_REG);
-			LOAD_DMA_COUNT(port_base, curSC->request_bufflen);	/* Max transfer size */
+			LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC));	/* Max transfer size */
 			outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
-			if (!curSC->use_sg)	/* Don't use scatter-gather */
-				SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
-			else {	/* Use scatter-gather */
-				sgcount = curSC->use_sg;
-				sglist = curSC->request_buffer;
-				while (sgcount--) {
-					SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
-					sglist++;
-				}
+
+			scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+				SYM53C500_pio_read(fast_pio, port_base,
+						   page_address(sg->page) + sg->offset,
+						   sg->length);
 			}
 			REG0(port_base);
 		}
@@ -578,7 +574,7 @@
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
 	    SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, 
-	    SCpnt->device->lun,  SCpnt->request_bufflen));
+	    SCpnt->device->lun,  scsi_bufflen(SCpnt)));
 
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
 	    printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ca46346..0f04258 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1633,7 +1633,7 @@
 	uint16_t entry;
 	uint16_t index;
 	const char *name;
-	irqreturn_t (*handler)(int, void *);
+	irq_handler_t handler;
 };
 
 static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
index 6437d024..fcc184c 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.c
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -6,176 +6,9 @@
  */
 
 #include "ql4_def.h"
-#include <scsi/scsi_dbg.h>
-
-#if 0
-
-static void qla4xxx_print_srb_info(struct srb * srb)
-{
-	printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
-	printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
-	       __func__, srb->cmd, (unsigned long) srb->dma_handle);
-	printk("%s: fw_ddb_index = %d, lun = %d\n",
-	       __func__, srb->fw_ddb_index, srb->cmd->device->lun);
-	printk("%s: iocb_tov = %d\n",
-	       __func__, srb->iocb_tov);
-	printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
-	       __func__, srb->cc_stat, srb->r_start, srb->u_start);
-}
-
-void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
-{
-	printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
-	printk("  b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
-	       cmd->device->channel, cmd->device->id, cmd->device->lun,
-	       cmd->cmd_len);
-	scsi_print_command(cmd);
-	printk("  seg_cnt = %d\n", cmd->use_sg);
-	printk("  request buffer = 0x%p, request buffer len = 0x%x\n",
-	       cmd->request_buffer, cmd->request_bufflen);
-	if (cmd->use_sg) {
-		struct scatterlist *sg;
-		sg = (struct scatterlist *)cmd->request_buffer;
-		printk("  SG buffer: \n");
-		qla4xxx_dump_buffer((caddr_t) sg,
-				    (cmd->use_sg * sizeof(*sg)));
-	}
-	printk("  tag = %d, transfersize = 0x%x \n", cmd->tag,
-	       cmd->transfersize);
-	printk("  Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
-	printk("  underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
-	       cmd->sc_data_direction);
-	printk("  Current time (jiffies) = 0x%lx, "
-	       "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
-	qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
-}
-
-void __dump_registers(struct scsi_qla_host *ha)
-{
-	uint8_t i;
-	for (i = 0; i < MBOX_REG_COUNT; i++) {
-		printk(KERN_INFO "0x%02X mailbox[%d]	  = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
-		       readw(&ha->reg->mailbox[i]));
-	}
-	printk(KERN_INFO "0x%02X flash_address	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, flash_address),
-	       readw(&ha->reg->flash_address));
-	printk(KERN_INFO "0x%02X flash_data	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, flash_data),
-	       readw(&ha->reg->flash_data));
-	printk(KERN_INFO "0x%02X ctrl_status	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, ctrl_status),
-	       readw(&ha->reg->ctrl_status));
-	if (is_qla4010(ha)) {
-		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
-		       readw(&ha->reg->u1.isp4010.nvram));
-	}
-
-	else if (is_qla4022(ha) | is_qla4032(ha)) {
-		printk(KERN_INFO "0x%02X intr_mask	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u1.isp4022.intr_mask),
-		       readw(&ha->reg->u1.isp4022.intr_mask));
-		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
-		       readw(&ha->reg->u1.isp4022.nvram));
-		printk(KERN_INFO "0x%02X semaphore	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u1.isp4022.semaphore),
-		       readw(&ha->reg->u1.isp4022.semaphore));
-	}
-	printk(KERN_INFO "0x%02X req_q_in	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, req_q_in),
-	       readw(&ha->reg->req_q_in));
-	printk(KERN_INFO "0x%02X rsp_q_out	 = 0x%08X\n",
-	       (uint8_t) offsetof(struct isp_reg, rsp_q_out),
-	       readw(&ha->reg->rsp_q_out));
-	if (is_qla4010(ha)) {
-		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.ext_hw_conf),
-		       readw(&ha->reg->u2.isp4010.ext_hw_conf));
-		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_ctrl),
-		       readw(&ha->reg->u2.isp4010.port_ctrl));
-		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_status),
-		       readw(&ha->reg->u2.isp4010.port_status));
-		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.req_q_out),
-		       readw(&ha->reg->u2.isp4010.req_q_out));
-		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
-		       readw(&ha->reg->u2.isp4010.gp_out));
-		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
-		       readw(&ha->reg->u2.isp4010.gp_in));
-		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4010.port_err_status),
-		       readw(&ha->reg->u2.isp4010.port_err_status));
-	}
-
-	else if (is_qla4022(ha) | is_qla4032(ha)) {
-		printk(KERN_INFO "Page 0 Registers:\n");
-		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.ext_hw_conf),
-		       readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
-		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_ctrl),
-		       readw(&ha->reg->u2.isp4022.p0.port_ctrl));
-		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_status),
-		       readw(&ha->reg->u2.isp4022.p0.port_status));
-		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.gp_out),
-		       readw(&ha->reg->u2.isp4022.p0.gp_out));
-		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
-		       readw(&ha->reg->u2.isp4022.p0.gp_in));
-		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p0.port_err_status),
-		       readw(&ha->reg->u2.isp4022.p0.port_err_status));
-		printk(KERN_INFO "Page 1 Registers:\n");
-		writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
-		       &ha->reg->ctrl_status);
-		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
-		       (uint8_t) offsetof(struct isp_reg,
-					  u2.isp4022.p1.req_q_out),
-		       readw(&ha->reg->u2.isp4022.p1.req_q_out));
-		writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
-		       &ha->reg->ctrl_status);
-	}
-}
-
-void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
-{
-	unsigned long flags = 0;
-	int i = 0;
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	for (i = 1; i < MBOX_REG_COUNT; i++)
-		printk(KERN_INFO "  Mailbox[%d] = %08x\n", i,
-		       readw(&ha->reg->mailbox[i]));
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
-
-void qla4xxx_dump_registers(struct scsi_qla_host *ha)
-{
-	unsigned long flags = 0;
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	__dump_registers(ha);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 void qla4xxx_dump_buffer(void *b, uint32_t size)
 {
@@ -198,4 +31,3 @@
 		printk(KERN_DEBUG "\n");
 }
 
-#endif  /*  0  */
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 6f4cf2d..accaf690 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -122,8 +122,7 @@
 
 #define ISCSI_IPADDR_SIZE		4	/* IP address size */
 #define ISCSI_ALIAS_SIZE		32	/* ISCSI Alais name size */
-#define ISCSI_NAME_SIZE			255	/* ISCSI Name size -
-						 * usually a string */
+#define ISCSI_NAME_SIZE			0xE0	/* ISCSI Name size */
 
 #define LSDW(x) ((u32)((u64)(x)))
 #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
@@ -187,9 +186,21 @@
 	u_long u_start;		/* Time when we handed the cmd to F/W */
 };
 
-	/*
-	 * Device Database (DDB) structure
-	 */
+/*
+ * Asynchronous Event Queue structure
+ */
+struct aen {
+        uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
+};
+
+struct ql4_aen_log {
+        int count;
+        struct aen entry[MAX_AEN_ENTRIES];
+};
+
+/*
+ * Device Database (DDB) structure
+ */
 struct ddb_entry {
 	struct list_head list;	/* ddb list */
 	struct scsi_qla_host *ha;
@@ -254,13 +265,6 @@
 #define DF_ISNS_DISCOVERED	2	/* Device was discovered via iSNS */
 #define DF_FO_MASKED		3
 
-/*
- * Asynchronous Event Queue structure
- */
-struct aen {
-	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
-};
-
 
 #include "ql4_fw.h"
 #include "ql4_nvram.h"
@@ -270,31 +274,31 @@
  */
 struct scsi_qla_host {
 	/* Linux adapter configuration data */
-	struct Scsi_Host *host; /* pointer to host data */
-	uint32_t tot_ddbs;
 	unsigned long flags;
 
-#define AF_ONLINE		      0 /* 0x00000001 */
-#define AF_INIT_DONE		      1 /* 0x00000002 */
-#define AF_MBOX_COMMAND		      2 /* 0x00000004 */
-#define AF_MBOX_COMMAND_DONE	      3 /* 0x00000008 */
-#define AF_INTERRUPTS_ON	      6 /* 0x00000040 Not Used */
-#define AF_GET_CRASH_RECORD	      7 /* 0x00000080 */
-#define AF_LINK_UP		      8 /* 0x00000100 */
-#define AF_IRQ_ATTACHED		     10 /* 0x00000400 */
-#define AF_ISNS_CMD_IN_PROCESS	     12 /* 0x00001000 */
-#define AF_ISNS_CMD_DONE	     13 /* 0x00002000 */
+#define AF_ONLINE			0 /* 0x00000001 */
+#define AF_INIT_DONE			1 /* 0x00000002 */
+#define AF_MBOX_COMMAND			2 /* 0x00000004 */
+#define AF_MBOX_COMMAND_DONE		3 /* 0x00000008 */
+#define AF_INTERRUPTS_ON		6 /* 0x00000040 */
+#define AF_GET_CRASH_RECORD		7 /* 0x00000080 */
+#define AF_LINK_UP			8 /* 0x00000100 */
+#define AF_IRQ_ATTACHED			10 /* 0x00000400 */
+#define AF_DISABLE_ACB_COMPLETE		11 /* 0x00000800 */
 
 	unsigned long dpc_flags;
 
-#define DPC_RESET_HA		      1 /* 0x00000002 */
-#define DPC_RETRY_RESET_HA	      2 /* 0x00000004 */
-#define DPC_RELOGIN_DEVICE	      3 /* 0x00000008 */
-#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */
-#define DPC_RESET_HA_INTR	      5 /* 0x00000020 */
-#define DPC_ISNS_RESTART	      7 /* 0x00000080 */
-#define DPC_AEN			      9 /* 0x00000200 */
-#define DPC_GET_DHCP_IP_ADDR	     15 /* 0x00008000 */
+#define DPC_RESET_HA			1 /* 0x00000002 */
+#define DPC_RETRY_RESET_HA		2 /* 0x00000004 */
+#define DPC_RELOGIN_DEVICE		3 /* 0x00000008 */
+#define DPC_RESET_HA_DESTROY_DDB_LIST	4 /* 0x00000010 */
+#define DPC_RESET_HA_INTR		5 /* 0x00000020 */
+#define DPC_ISNS_RESTART		7 /* 0x00000080 */
+#define DPC_AEN				9 /* 0x00000200 */
+#define DPC_GET_DHCP_IP_ADDR		15 /* 0x00008000 */
+
+	struct Scsi_Host *host; /* pointer to host data */
+	uint32_t tot_ddbs;
 
 	uint16_t	iocb_cnt;
 	uint16_t	iocb_hiwat;
@@ -344,6 +348,7 @@
 	uint32_t firmware_version[2];
 	uint32_t patch_number;
 	uint32_t build_number;
+	uint32_t board_id;
 
 	/* --- From Init_FW --- */
 	/* init_cb_t *init_cb; */
@@ -363,7 +368,6 @@
 
 	/* --- From GetFwState --- */
 	uint32_t firmware_state;
-	uint32_t board_id;
 	uint32_t addl_fw_state;
 
 	/* Linux kernel thread */
@@ -414,6 +418,8 @@
 	uint16_t aen_out;
 	struct aen aen_q[MAX_AEN_ENTRIES];
 
+	struct ql4_aen_log aen_log;/* tracks all aens */
+
 	/* This mutex protects several threads to do mailbox commands
 	 * concurrently.
 	 */
@@ -585,10 +591,4 @@
 #define FLUSH_DDB_CHANGED_AENS	 1
 #define RELOGIN_DDB_CHANGED_AENS 2
 
-#include "ql4_version.h"
-#include "ql4_glbl.h"
-#include "ql4_dbg.h"
-#include "ql4_inline.h"
-
-
 #endif	/*_QLA4XXX_H */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 4eea8c5..9bb3d1d 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -20,143 +20,23 @@
  *************************************************************************/
 
 struct port_ctrl_stat_regs {
-	__le32 ext_hw_conf;	/*  80 x50  R/W */
-	__le32 intChipConfiguration; /*	 84 x54 */
-	__le32 port_ctrl;	/*  88 x58 */
-	__le32 port_status;	/*  92 x5c */
-	__le32 HostPrimMACHi;	/*  96 x60 */
-	__le32 HostPrimMACLow;	/* 100 x64 */
-	__le32 HostSecMACHi;	/* 104 x68 */
-	__le32 HostSecMACLow;	/* 108 x6c */
-	__le32 EPPrimMACHi;	/* 112 x70 */
-	__le32 EPPrimMACLow;	/* 116 x74 */
-	__le32 EPSecMACHi;	/* 120 x78 */
-	__le32 EPSecMACLow;	/* 124 x7c */
-	__le32 HostPrimIPHi;	/* 128 x80 */
-	__le32 HostPrimIPMidHi; /* 132 x84 */
-	__le32 HostPrimIPMidLow;	/* 136 x88 */
-	__le32 HostPrimIPLow;	/* 140 x8c */
-	__le32 HostSecIPHi;	/* 144 x90 */
-	__le32 HostSecIPMidHi;	/* 148 x94 */
-	__le32 HostSecIPMidLow; /* 152 x98 */
-	__le32 HostSecIPLow;	/* 156 x9c */
-	__le32 EPPrimIPHi;	/* 160 xa0 */
-	__le32 EPPrimIPMidHi;	/* 164 xa4 */
-	__le32 EPPrimIPMidLow;	/* 168 xa8 */
-	__le32 EPPrimIPLow;	/* 172 xac */
-	__le32 EPSecIPHi;	/* 176 xb0 */
-	__le32 EPSecIPMidHi;	/* 180 xb4 */
-	__le32 EPSecIPMidLow;	/* 184 xb8 */
-	__le32 EPSecIPLow;	/* 188 xbc */
-	__le32 IPReassemblyTimeout; /* 192 xc0 */
-	__le32 EthMaxFramePayload; /* 196 xc4 */
-	__le32 TCPMaxWindowSize; /* 200 xc8 */
-	__le32 TCPCurrentTimestampHi; /* 204 xcc */
-	__le32 TCPCurrentTimestampLow; /* 208 xd0 */
-	__le32 LocalRAMAddress; /* 212 xd4 */
-	__le32 LocalRAMData;	/* 216 xd8 */
-	__le32 PCSReserved1;	/* 220 xdc */
-	__le32 gp_out;		/* 224 xe0 */
-	__le32 gp_in;		/* 228 xe4 */
-	__le32 ProbeMuxAddr;	/* 232 xe8 */
-	__le32 ProbeMuxData;	/* 236 xec */
-	__le32 ERMQueueBaseAddr0; /* 240 xf0 */
-	__le32 ERMQueueBaseAddr1; /* 244 xf4 */
-	__le32 MACConfiguration; /* 248 xf8 */
-	__le32 port_err_status; /* 252 xfc  COR */
+	__le32 ext_hw_conf;	/* 0x50  R/W */
+	__le32 rsrvd0;		/* 0x54 */
+	__le32 port_ctrl;	/* 0x58 */
+	__le32 port_status;	/* 0x5c */
+	__le32 rsrvd1[32];	/* 0x60-0xdf */
+	__le32 gp_out;		/* 0xe0 */
+	__le32 gp_in;		/* 0xe4 */
+	__le32 rsrvd2[5];	/* 0xe8-0xfb */
+	__le32 port_err_status; /* 0xfc */
 };
 
 struct host_mem_cfg_regs {
-	__le32 NetRequestQueueOut; /*  80 x50 */
-	__le32 NetRequestQueueOutAddrHi; /*  84 x54 */
-	__le32 NetRequestQueueOutAddrLow; /*  88 x58 */
-	__le32 NetRequestQueueBaseAddrHi; /*  92 x5c */
-	__le32 NetRequestQueueBaseAddrLow; /*  96 x60 */
-	__le32 NetRequestQueueLength; /* 100 x64 */
-	__le32 NetResponseQueueIn; /* 104 x68 */
-	__le32 NetResponseQueueInAddrHi; /* 108 x6c */
-	__le32 NetResponseQueueInAddrLow; /* 112 x70 */
-	__le32 NetResponseQueueBaseAddrHi; /* 116 x74 */
-	__le32 NetResponseQueueBaseAddrLow; /* 120 x78 */
-	__le32 NetResponseQueueLength; /* 124 x7c */
-	__le32 req_q_out;	/* 128 x80 */
-	__le32 RequestQueueOutAddrHi; /* 132 x84 */
-	__le32 RequestQueueOutAddrLow; /* 136 x88 */
-	__le32 RequestQueueBaseAddrHi; /* 140 x8c */
-	__le32 RequestQueueBaseAddrLow; /* 144 x90 */
-	__le32 RequestQueueLength; /* 148 x94 */
-	__le32 ResponseQueueIn; /* 152 x98 */
-	__le32 ResponseQueueInAddrHi; /* 156 x9c */
-	__le32 ResponseQueueInAddrLow; /* 160 xa0 */
-	__le32 ResponseQueueBaseAddrHi; /* 164 xa4 */
-	__le32 ResponseQueueBaseAddrLow; /* 168 xa8 */
-	__le32 ResponseQueueLength; /* 172 xac */
-	__le32 NetRxLargeBufferQueueOut; /* 176 xb0 */
-	__le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */
-	__le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */
-	__le32 NetRxLargeBufferQueueLength; /* 188 xbc */
-	__le32 NetRxLargeBufferLength; /* 192 xc0 */
-	__le32 NetRxSmallBufferQueueOut; /* 196 xc4 */
-	__le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */
-	__le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */
-	__le32 NetRxSmallBufferQueueLength; /* 208 xd0 */
-	__le32 NetRxSmallBufferLength; /* 212 xd4 */
-	__le32 HMCReserved0[10]; /* 216 xd8 */
+	__le32 rsrvd0[12];	/* 0x50-0x79 */
+	__le32 req_q_out;	/* 0x80 */
+	__le32 rsrvd1[31];	/* 0x84-0xFF */
 };
 
-struct local_ram_cfg_regs {
-	__le32 BufletSize;	/*  80 x50 */
-	__le32 BufletMaxCount;	/*  84 x54 */
-	__le32 BufletCurrCount; /*  88 x58 */
-	__le32 BufletPauseThresholdCount; /*  92 x5c */
-	__le32 BufletTCPWinThresholdHi; /*  96 x60 */
-	__le32 BufletTCPWinThresholdLow; /* 100 x64 */
-	__le32 IPHashTableBaseAddr; /* 104 x68 */
-	__le32 IPHashTableSize; /* 108 x6c */
-	__le32 TCPHashTableBaseAddr; /* 112 x70 */
-	__le32 TCPHashTableSize; /* 116 x74 */
-	__le32 NCBAreaBaseAddr; /* 120 x78 */
-	__le32 NCBMaxCount;	/* 124 x7c */
-	__le32 NCBCurrCount;	/* 128 x80 */
-	__le32 DRBAreaBaseAddr; /* 132 x84 */
-	__le32 DRBMaxCount;	/* 136 x88 */
-	__le32 DRBCurrCount;	/* 140 x8c */
-	__le32 LRCReserved[28]; /* 144 x90 */
-};
-
-struct prot_stat_regs {
-	__le32 MACTxFrameCount; /*  80 x50   R */
-	__le32 MACTxByteCount;	/*  84 x54   R */
-	__le32 MACRxFrameCount; /*  88 x58   R */
-	__le32 MACRxByteCount;	/*  92 x5c   R */
-	__le32 MACCRCErrCount;	/*  96 x60   R */
-	__le32 MACEncErrCount;	/* 100 x64   R */
-	__le32 MACRxLengthErrCount; /* 104 x68	 R */
-	__le32 IPTxPacketCount; /* 108 x6c   R */
-	__le32 IPTxByteCount;	/* 112 x70   R */
-	__le32 IPTxFragmentCount; /* 116 x74   R */
-	__le32 IPRxPacketCount; /* 120 x78   R */
-	__le32 IPRxByteCount;	/* 124 x7c   R */
-	__le32 IPRxFragmentCount; /* 128 x80   R */
-	__le32 IPDatagramReassemblyCount; /* 132 x84   R */
-	__le32 IPV6RxPacketCount; /* 136 x88   R */
-	__le32 IPErrPacketCount; /* 140 x8c   R */
-	__le32 IPReassemblyErrCount; /* 144 x90	  R */
-	__le32 TCPTxSegmentCount; /* 148 x94   R */
-	__le32 TCPTxByteCount;	/* 152 x98   R */
-	__le32 TCPRxSegmentCount; /* 156 x9c   R */
-	__le32 TCPRxByteCount;	/* 160 xa0   R */
-	__le32 TCPTimerExpCount; /* 164 xa4   R */
-	__le32 TCPRxAckCount;	/* 168 xa8   R */
-	__le32 TCPTxAckCount;	/* 172 xac   R */
-	__le32 TCPRxErrOOOCount; /* 176 xb0   R */
-	__le32 PSReserved0;	/* 180 xb4 */
-	__le32 TCPRxWindowProbeUpdateCount; /* 184 xb8	 R */
-	__le32 ECCErrCorrectionCount; /* 188 xbc   R */
-	__le32 PSReserved1[16]; /* 192 xc0 */
-};
-
-
 /*  remote register set (access via PCI memory read/write) */
 struct isp_reg {
 #define MBOX_REG_COUNT 8
@@ -207,11 +87,7 @@
 			union {
 				struct port_ctrl_stat_regs p0;
 				struct host_mem_cfg_regs p1;
-				struct local_ram_cfg_regs p2;
-				struct prot_stat_regs p3;
-				__le32 r_union[44];
 			};
-
 		} __attribute__ ((packed)) isp4022;
 	} u2;
 };				/* 256 x100 */
@@ -296,6 +172,7 @@
 /*  ISP Semaphore definitions */
 
 /*  ISP General Purpose Output definitions */
+#define GPOR_TOPCAT_RESET			0x00000004
 
 /*  shadow registers (DMA'd from HA to system memory.  read only) */
 struct shadow_regs {
@@ -337,6 +214,7 @@
 
 /*  Mailbox command definitions */
 #define MBOX_CMD_ABOUT_FW			0x0009
+#define MBOX_CMD_PING				0x000B
 #define MBOX_CMD_LUN_RESET			0x0016
 #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
 #define MBOX_CMD_GET_FW_STATUS			0x001F
@@ -364,6 +242,17 @@
 #define MBOX_CMD_GET_FW_STATE			0x0069
 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
 #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS	0x0087
+#define MBOX_CMD_SET_ACB			0x0088
+#define MBOX_CMD_GET_ACB			0x0089
+#define MBOX_CMD_DISABLE_ACB			0x008A
+#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE	0x008B
+#define MBOX_CMD_GET_IPV6_DEST_CACHE		0x008C
+#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST	0x008D
+#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST	0x008E
+#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE	0x0090
+#define MBOX_CMD_GET_IP_ADDR_STATE		0x0091
+#define MBOX_CMD_SEND_IPV6_ROUTER_SOL		0x0092
+#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR	0x0093
 
 /* Mailbox 1 */
 #define FW_STATE_READY				0x0000
@@ -409,6 +298,16 @@
 #define MBOX_ASTS_DHCP_LEASE_EXPIRED		0x801D
 #define MBOX_ASTS_DHCP_LEASE_ACQUIRED		0x801F
 #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021
+#define MBOX_ASTS_DUPLICATE_IP			0x8025
+#define MBOX_ASTS_ARP_COMPLETE			0x8026
+#define MBOX_ASTS_SUBNET_STATE_CHANGE		0x8027
+#define MBOX_ASTS_RESPONSE_QUEUE_FULL		0x8028
+#define MBOX_ASTS_IP_ADDR_STATE_CHANGED		0x8029
+#define MBOX_ASTS_IPV6_PREFIX_EXPIRED		0x802B
+#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED	0x802C
+#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED	0x802D
+#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD		0x802E
+
 #define ISNS_EVENT_DATA_RECEIVED		0x0000
 #define ISNS_EVENT_CONNECTION_OPENED		0x0001
 #define ISNS_EVENT_CONNECTION_FAILED		0x0002
@@ -418,137 +317,166 @@
 /*************************************************************************/
 
 /* Host Adapter Initialization Control Block (from host) */
-struct init_fw_ctrl_blk {
-	uint8_t Version;	/* 00 */
-	uint8_t Control;	/* 01 */
+struct addr_ctrl_blk {
+	uint8_t version;	/* 00 */
+	uint8_t control;	/* 01 */
 
-	uint16_t FwOptions;	/* 02-03 */
+	uint16_t fw_options;	/* 02-03 */
 #define	 FWOPT_HEARTBEAT_ENABLE		  0x1000
 #define	 FWOPT_SESSION_MODE		  0x0040
 #define	 FWOPT_INITIATOR_MODE		  0x0020
 #define	 FWOPT_TARGET_MODE		  0x0010
 
-	uint16_t ExecThrottle;	/* 04-05 */
-	uint8_t RetryCount;	/* 06 */
-	uint8_t RetryDelay;	/* 07 */
-	uint16_t MaxEthFrPayloadSize;	/* 08-09 */
-	uint16_t AddFwOptions;	/* 0A-0B */
+	uint16_t exec_throttle;	/* 04-05 */
+	uint8_t zio_count;	/* 06 */
+	uint8_t res0;	/* 07 */
+	uint16_t eth_mtu_size;	/* 08-09 */
+	uint16_t add_fw_options;	/* 0A-0B */
 
-	uint8_t HeartbeatInterval;	/* 0C */
-	uint8_t InstanceNumber; /* 0D */
-	uint16_t RES2;		/* 0E-0F */
-	uint16_t ReqQConsumerIndex;	/* 10-11 */
-	uint16_t ComplQProducerIndex;	/* 12-13 */
-	uint16_t ReqQLen;	/* 14-15 */
-	uint16_t ComplQLen;	/* 16-17 */
-	uint32_t ReqQAddrLo;	/* 18-1B */
-	uint32_t ReqQAddrHi;	/* 1C-1F */
-	uint32_t ComplQAddrLo;	/* 20-23 */
-	uint32_t ComplQAddrHi;	/* 24-27 */
-	uint32_t ShadowRegBufAddrLo;	/* 28-2B */
-	uint32_t ShadowRegBufAddrHi;	/* 2C-2F */
+	uint8_t hb_interval;	/* 0C */
+	uint8_t inst_num; /* 0D */
+	uint16_t res1;		/* 0E-0F */
+	uint16_t rqq_consumer_idx;	/* 10-11 */
+	uint16_t compq_producer_idx;	/* 12-13 */
+	uint16_t rqq_len;	/* 14-15 */
+	uint16_t compq_len;	/* 16-17 */
+	uint32_t rqq_addr_lo;	/* 18-1B */
+	uint32_t rqq_addr_hi;	/* 1C-1F */
+	uint32_t compq_addr_lo;	/* 20-23 */
+	uint32_t compq_addr_hi;	/* 24-27 */
+	uint32_t shdwreg_addr_lo;	/* 28-2B */
+	uint32_t shdwreg_addr_hi;	/* 2C-2F */
 
-	uint16_t iSCSIOptions;	/* 30-31 */
+	uint16_t iscsi_opts;	/* 30-31 */
+	uint16_t ipv4_tcp_opts;	/* 32-33 */
+	uint16_t ipv4_ip_opts;	/* 34-35 */
 
-	uint16_t TCPOptions;	/* 32-33 */
+	uint16_t iscsi_max_pdu_size;	/* 36-37 */
+	uint8_t ipv4_tos;	/* 38 */
+	uint8_t ipv4_ttl;	/* 39 */
+	uint8_t acb_version;	/* 3A */
+	uint8_t res2;	/* 3B */
+	uint16_t def_timeout;	/* 3C-3D */
+	uint16_t iscsi_fburst_len;	/* 3E-3F */
+	uint16_t iscsi_def_time2wait;	/* 40-41 */
+	uint16_t iscsi_def_time2retain;	/* 42-43 */
+	uint16_t iscsi_max_outstnd_r2t;	/* 44-45 */
+	uint16_t conn_ka_timeout;	/* 46-47 */
+	uint16_t ipv4_port;	/* 48-49 */
+	uint16_t iscsi_max_burst_len;	/* 4A-4B */
+	uint32_t res5;		/* 4C-4F */
+	uint8_t ipv4_addr[4];	/* 50-53 */
+	uint16_t ipv4_vlan_tag;	/* 54-55 */
+	uint8_t ipv4_addr_state;	/* 56 */
+	uint8_t ipv4_cacheid;	/* 57 */
+	uint8_t res6[8];	/* 58-5F */
+	uint8_t ipv4_subnet[4];	/* 60-63 */
+	uint8_t res7[12];	/* 64-6F */
+	uint8_t ipv4_gw_addr[4];	/* 70-73 */
+	uint8_t res8[0xc];	/* 74-7F */
+	uint8_t pri_dns_srvr_ip[4];/* 80-83 */
+	uint8_t sec_dns_srvr_ip[4];/* 84-87 */
+	uint16_t min_eph_port;	/* 88-89 */
+	uint16_t max_eph_port;	/* 8A-8B */
+	uint8_t res9[4];	/* 8C-8F */
+	uint8_t iscsi_alias[32];/* 90-AF */
+	uint8_t res9_1[0x16];	/* B0-C5 */
+	uint16_t tgt_portal_grp;/* C6-C7 */
+	uint8_t abort_timer;	/* C8	 */
+	uint8_t ipv4_tcp_wsf;	/* C9	 */
+	uint8_t res10[6];	/* CA-CF */
+	uint8_t ipv4_sec_ip_addr[4];	/* D0-D3 */
+	uint8_t ipv4_dhcp_vid_len;	/* D4 */
+	uint8_t ipv4_dhcp_vid[11];	/* D5-DF */
+	uint8_t res11[20];	/* E0-F3 */
+	uint8_t ipv4_dhcp_alt_cid_len;	/* F4 */
+	uint8_t ipv4_dhcp_alt_cid[11];	/* F5-FF */
+	uint8_t iscsi_name[224];	/* 100-1DF */
+	uint8_t res12[32];	/* 1E0-1FF */
+	uint32_t cookie;	/* 200-203 */
+	uint16_t ipv6_port;	/* 204-205 */
+	uint16_t ipv6_opts;	/* 206-207 */
+	uint16_t ipv6_addtl_opts;	/* 208-209 */
+	uint16_t ipv6_tcp_opts;	/* 20A-20B */
+	uint8_t ipv6_tcp_wsf;	/* 20C */
+	uint16_t ipv6_flow_lbl;	/* 20D-20F */
+	uint8_t ipv6_gw_addr[16];	/* 210-21F */
+	uint16_t ipv6_vlan_tag;	/* 220-221 */
+	uint8_t ipv6_lnk_lcl_addr_state;/* 222 */
+	uint8_t ipv6_addr0_state;	/* 223 */
+	uint8_t ipv6_addr1_state;	/* 224 */
+	uint8_t ipv6_gw_state;	/* 225 */
+	uint8_t ipv6_traffic_class;	/* 226 */
+	uint8_t ipv6_hop_limit;	/* 227 */
+	uint8_t ipv6_if_id[8];	/* 228-22F */
+	uint8_t ipv6_addr0[16];	/* 230-23F */
+	uint8_t ipv6_addr1[16];	/* 240-24F */
+	uint32_t ipv6_nd_reach_time;	/* 250-253 */
+	uint32_t ipv6_nd_rexmit_timer;	/* 254-257 */
+	uint32_t ipv6_nd_stale_timeout;	/* 258-25B */
+	uint8_t ipv6_dup_addr_detect_count;	/* 25C */
+	uint8_t ipv6_cache_id;	/* 25D */
+	uint8_t res13[18];	/* 25E-26F */
+	uint32_t ipv6_gw_advrt_mtu;	/* 270-273 */
+	uint8_t res14[140];	/* 274-2FF */
+};
 
-	uint16_t IPOptions;	/* 34-35 */
-
-	uint16_t MaxPDUSize;	/* 36-37 */
-	uint16_t RcvMarkerInt;	/* 38-39 */
-	uint16_t SndMarkerInt;	/* 3A-3B */
-	uint16_t InitMarkerlessInt;	/* 3C-3D */
-	uint16_t FirstBurstSize;	/* 3E-3F */
-	uint16_t DefaultTime2Wait;	/* 40-41 */
-	uint16_t DefaultTime2Retain;	/* 42-43 */
-	uint16_t MaxOutStndngR2T;	/* 44-45 */
-	uint16_t KeepAliveTimeout;	/* 46-47 */
-	uint16_t PortNumber;	/* 48-49 */
-	uint16_t MaxBurstSize;	/* 4A-4B */
-	uint32_t RES4;		/* 4C-4F */
-	uint8_t IPAddr[4];	/* 50-53 */
-	uint8_t RES5[12];	/* 54-5F */
-	uint8_t SubnetMask[4];	/* 60-63 */
-	uint8_t RES6[12];	/* 64-6F */
-	uint8_t GatewayIPAddr[4];	/* 70-73 */
-	uint8_t RES7[12];	/* 74-7F */
-	uint8_t PriDNSIPAddr[4];	/* 80-83 */
-	uint8_t SecDNSIPAddr[4];	/* 84-87 */
-	uint8_t RES8[8];	/* 88-8F */
-	uint8_t Alias[32];	/* 90-AF */
-	uint8_t TargAddr[8];	/* B0-B7 *//* /FIXME: Remove?? */
-	uint8_t CHAPNameSecretsTable[8];	/* B8-BF */
-	uint8_t EthernetMACAddr[6];	/* C0-C5 */
-	uint16_t TargetPortalGroup;	/* C6-C7 */
-	uint8_t SendScale;	/* C8	 */
-	uint8_t RecvScale;	/* C9	 */
-	uint8_t TypeOfService;	/* CA	 */
-	uint8_t Time2Live;	/* CB	 */
-	uint16_t VLANPriority;	/* CC-CD */
-	uint16_t Reserved8;	/* CE-CF */
-	uint8_t SecIPAddr[4];	/* D0-D3 */
-	uint8_t Reserved9[12];	/* D4-DF */
-	uint8_t iSNSIPAddr[4];	/* E0-E3 */
-	uint16_t iSNSServerPortNumber;	/* E4-E5 */
-	uint8_t Reserved10[10]; /* E6-EF */
-	uint8_t SLPDAIPAddr[4]; /* F0-F3 */
-	uint8_t Reserved11[12]; /* F4-FF */
-	uint8_t iSCSINameString[256];	/* 100-1FF */
+struct init_fw_ctrl_blk {
+	struct addr_ctrl_blk pri;
+	struct addr_ctrl_blk sec;
 };
 
 /*************************************************************************/
 
 struct dev_db_entry {
-	uint8_t options;	/* 00 */
+	uint16_t options;	/* 00-01 */
 #define DDB_OPT_DISC_SESSION  0x10
 #define DDB_OPT_TARGET	      0x02 /* device is a target */
 
-	uint8_t control;	/* 01 */
-
-	uint16_t exeThrottle;	/* 02-03 */
-	uint16_t exeCount;	/* 04-05 */
-	uint8_t retryCount;	/* 06	 */
-	uint8_t retryDelay;	/* 07	 */
-	uint16_t iSCSIOptions;	/* 08-09 */
-
-	uint16_t TCPOptions;	/* 0A-0B */
-
-	uint16_t IPOptions;	/* 0C-0D */
-
-	uint16_t maxPDUSize;	/* 0E-0F */
-	uint16_t rcvMarkerInt;	/* 10-11 */
-	uint16_t sndMarkerInt;	/* 12-13 */
-	uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */
-	uint16_t firstBurstSize;	/* 16-17 */
-	uint16_t minTime2Wait;	/* 18-19 : RA :default_time2wait */
-	uint16_t maxTime2Retain;	/* 1A-1B */
-	uint16_t maxOutstndngR2T;	/* 1C-1D */
-	uint16_t keepAliveTimeout;	/* 1E-1F */
-	uint8_t ISID[6];	/* 20-25 big-endian, must be converted
+	uint16_t exec_throttle;	/* 02-03 */
+	uint16_t exec_count;	/* 04-05 */
+	uint16_t res0;	/* 06-07 */
+	uint16_t iscsi_options;	/* 08-09 */
+	uint16_t tcp_options;	/* 0A-0B */
+	uint16_t ip_options;	/* 0C-0D */
+	uint16_t iscsi_max_rcv_data_seg_len;	/* 0E-0F */
+	uint32_t res1;	/* 10-13 */
+	uint16_t iscsi_max_snd_data_seg_len;	/* 14-15 */
+	uint16_t iscsi_first_burst_len;	/* 16-17 */
+	uint16_t iscsi_def_time2wait;	/* 18-19 */
+	uint16_t iscsi_def_time2retain;	/* 1A-1B */
+	uint16_t iscsi_max_outsnd_r2t;	/* 1C-1D */
+	uint16_t ka_timeout;	/* 1E-1F */
+	uint8_t isid[6];	/* 20-25 big-endian, must be converted
 				 * to little-endian */
-	uint16_t TSID;		/* 26-27 */
-	uint16_t portNumber;	/* 28-29 */
-	uint16_t maxBurstSize;	/* 2A-2B */
-	uint16_t taskMngmntTimeout;	/* 2C-2D */
-	uint16_t reserved1;	/* 2E-2F */
-	uint8_t ipAddr[0x10];	/* 30-3F */
-	uint8_t iSCSIAlias[0x20];	/* 40-5F */
-	uint8_t targetAddr[0x20];	/* 60-7F */
-	uint8_t userID[0x20];	/* 80-9F */
-	uint8_t password[0x20]; /* A0-BF */
-	uint8_t iscsiName[0x100];	/* C0-1BF : xxzzy Make this a
+	uint16_t tsid;		/* 26-27 */
+	uint16_t port;	/* 28-29 */
+	uint16_t iscsi_max_burst_len;	/* 2A-2B */
+	uint16_t def_timeout;	/* 2C-2D */
+	uint16_t res2;	/* 2E-2F */
+	uint8_t ip_addr[0x10];	/* 30-3F */
+	uint8_t iscsi_alias[0x20];	/* 40-5F */
+	uint8_t tgt_addr[0x20];	/* 60-7F */
+	uint16_t mss;	/* 80-81 */
+	uint16_t res3;	/* 82-83 */
+	uint16_t lcl_port;	/* 84-85 */
+	uint8_t ipv4_tos;	/* 86 */
+	uint16_t ipv6_flow_lbl;	/* 87-89 */
+	uint8_t res4[0x36];	/* 8A-BF */
+	uint8_t iscsi_name[0xE0];	/* C0-19F : xxzzy Make this a
 					 * pointer to a string so we
 					 * don't have to reserve soooo
 					 * much RAM */
-	uint16_t ddbLink;	/* 1C0-1C1 */
-	uint16_t CHAPTableIndex; /* 1C2-1C3 */
-	uint16_t TargetPortalGroup; /* 1C4-1C5 */
-	uint16_t reserved2[2];	/* 1C6-1C7 */
-	uint32_t statSN;	/* 1C8-1CB */
-	uint32_t expStatSN;	/* 1CC-1CF */
-	uint16_t reserved3[0x2C]; /* 1D0-1FB */
-	uint16_t ddbValidCookie; /* 1FC-1FD */
-	uint16_t ddbValidSize;	/* 1FE-1FF */
+	uint8_t ipv6_addr[0x10];/* 1A0-1AF */
+	uint8_t res5[0x10];	/* 1B0-1BF */
+	uint16_t ddb_link;	/* 1C0-1C1 */
+	uint16_t chap_tbl_idx;	/* 1C2-1C3 */
+	uint16_t tgt_portal_grp; /* 1C4-1C5 */
+	uint8_t tcp_xmt_wsf;	/* 1C6 */
+	uint8_t tcp_rcv_wsf;	/* 1C7 */
+	uint32_t stat_sn;	/* 1C8-1CB */
+	uint32_t exp_stat_sn;	/* 1CC-1CF */
+	uint8_t res6[0x30];	/* 1D0-1FF */
 };
 
 /*************************************************************************/
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 5b00cb0..a3608e0 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -8,6 +8,9 @@
 #ifndef __QLA4x_GBL_H
 #define	__QLA4x_GBL_H
 
+struct iscsi_cls_conn;
+
+void qla4xxx_hw_reset(struct scsi_qla_host *ha);
 int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
 int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
 int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
@@ -58,11 +61,13 @@
 void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
 				       uint32_t intr_status);
 int qla4xxx_init_rings(struct scsi_qla_host * ha);
-struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
+					uint32_t index);
 void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
 int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
 int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
 				uint32_t fw_ddb_index, uint32_t state);
+void qla4xxx_dump_buffer(void *b, uint32_t size);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdiscoverywait;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 6365df2..d8c064c 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
 					    uint32_t fw_ddb_index);
@@ -300,12 +303,12 @@
 	if (!qla4xxx_fw_ready(ha))
 		return status;
 
-	set_bit(AF_ONLINE, &ha->flags);
 	return qla4xxx_get_firmware_status(ha);
 }
 
 static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
-					       uint32_t fw_ddb_index)
+						uint32_t fw_ddb_index,
+						uint32_t *new_tgt)
 {
 	struct dev_db_entry *fw_ddb_entry = NULL;
 	dma_addr_t fw_ddb_entry_dma;
@@ -313,6 +316,7 @@
 	int found = 0;
 	uint32_t device_state;
 
+	*new_tgt = 0;
 	/* Make sure the dma buffer is valid */
 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
 					  sizeof(*fw_ddb_entry),
@@ -337,7 +341,7 @@
 	DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
 		      __func__, fw_ddb_index));
 	list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
-		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName,
+		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
 			   ISCSI_NAME_SIZE) == 0) {
 			found++;
 			break;
@@ -348,6 +352,7 @@
 		DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
 			      "new ddb\n", ha->host_no, __func__,
 			      fw_ddb_index));
+		*new_tgt = 1;
 		ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
 	}
 
@@ -409,26 +414,26 @@
 	}
 
 	status = QLA_SUCCESS;
-	ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID);
+	ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
 	ddb_entry->task_mgmt_timeout =
-		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
+		le16_to_cpu(fw_ddb_entry->def_timeout);
 	ddb_entry->CmdSn = 0;
-	ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle);
+	ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
 	ddb_entry->default_relogin_timeout =
-		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
-	ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait);
+		le16_to_cpu(fw_ddb_entry->def_timeout);
+	ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
 
 	/* Update index in case it changed */
 	ddb_entry->fw_ddb_index = fw_ddb_index;
 	ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
 
-	ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber);
-	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup);
-	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0],
+	ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
+	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
 	       min(sizeof(ddb_entry->iscsi_name),
-		   sizeof(fw_ddb_entry->iscsiName)));
-	memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0],
-	       min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr)));
+		   sizeof(fw_ddb_entry->iscsi_name)));
+	memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
+	       min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
 
 	DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
 		      ha->host_no, __func__, fw_ddb_index,
@@ -495,6 +500,7 @@
 	uint32_t ddb_state;
 	uint32_t conn_err, err_code;
 	struct ddb_entry *ddb_entry;
+	uint32_t new_tgt;
 
 	dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
 	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
@@ -526,8 +532,19 @@
 					      "completed "
 					      "or access denied failure\n",
 					      ha->host_no, __func__));
-			} else
+			} else {
 				qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
+				if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
+					NULL, 0, NULL, &next_fw_ddb_index,
+					&ddb_state, &conn_err, NULL, NULL)
+					== QLA_ERROR) {
+					DEBUG2(printk("scsi%ld: %s:"
+						"get_ddb_entry %d failed\n",
+						ha->host_no,
+						__func__, fw_ddb_index));
+					return QLA_ERROR;
+				}
+			}
 		}
 
 		if (ddb_state != DDB_DS_SESSION_ACTIVE)
@@ -540,7 +557,7 @@
 			      ha->host_no, __func__, fw_ddb_index));
 
 		/* Add DDB to internal our ddb list. */
-		ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+		ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
 		if (ddb_entry == NULL) {
 			DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
 				      "for device at fw_ddb_index %d\n",
@@ -865,21 +882,19 @@
 
 static void qla4x00_pci_config(struct scsi_qla_host *ha)
 {
-	uint16_t w, mwi;
+	uint16_t w;
 
 	dev_info(&ha->pdev->dev, "Configuring PCI space...\n");
 
 	pci_set_master(ha->pdev);
-	mwi = 0;
-	if (pci_set_mwi(ha->pdev))
-		mwi = PCI_COMMAND_INVALIDATE;
+	pci_set_mwi(ha->pdev);
 	/*
 	 * We want to respect framework's setting of PCI configuration space
 	 * command register and also want to make sure that all bits of
 	 * interest to us are properly set in command register.
 	 */
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
 	w &= ~PCI_COMMAND_INTX_DISABLE;
 	pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 }
@@ -911,6 +926,9 @@
 		writel(set_rmask(NVR_WRITE_ENABLE),
 		       &ha->reg->u1.isp4022.nvram);
 
+        writel(2, &ha->reg->mailbox[6]);
+        readl(&ha->reg->mailbox[6]);
+
 	writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status);
 	readl(&ha->reg->ctrl_status);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -958,25 +976,25 @@
 	return status;
 }
 
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
 {
-#define QL4_LOCK_DRVR_WAIT	30
+#define QL4_LOCK_DRVR_WAIT	60
 #define QL4_LOCK_DRVR_SLEEP	1
 
 	int drvr_wait = QL4_LOCK_DRVR_WAIT;
 	while (drvr_wait) {
-		if (ql4xxx_lock_drvr(ha) == 0) {
+		if (ql4xxx_lock_drvr(a) == 0) {
 			ssleep(QL4_LOCK_DRVR_SLEEP);
 			if (drvr_wait) {
 				DEBUG2(printk("scsi%ld: %s: Waiting for "
-					      "Global Init Semaphore(%d)...n",
-					      ha->host_no,
+					      "Global Init Semaphore(%d)...\n",
+					      a->host_no,
 					      __func__, drvr_wait));
 			}
 			drvr_wait -= QL4_LOCK_DRVR_SLEEP;
 		} else {
 			DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
-				      "acquired.n", ha->host_no, __func__));
+				      "acquired\n", a->host_no, __func__));
 			return QLA_SUCCESS;
 		}
 	}
@@ -1142,8 +1160,10 @@
 	 * the ddb_list and wait for DHCP lease acquired aen to come in
 	 * followed by 0x8014 aen" to trigger the tgt discovery process.
 	 */
-	if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)
+	if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS){
+		set_bit(AF_ONLINE, &ha->flags);
 		return status;
+	}
 
 	/* Skip device discovery if ip and subnet is zero */
 	if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
@@ -1177,6 +1197,7 @@
 			      ha->host_no));
 	}
 
+	set_bit(AF_ONLINE, &ha->flags);
  exit_init_hba:
 	return status;
 
@@ -1193,9 +1214,10 @@
 					   uint32_t fw_ddb_index)
 {
 	struct ddb_entry * ddb_entry;
+	uint32_t new_tgt;
 
 	/* First allocate a device structure */
-	ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+	ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
 	if (ddb_entry == NULL) {
 		DEBUG2(printk(KERN_WARNING
 			      "scsi%ld: Unable to allocate memory to add "
@@ -1203,6 +1225,18 @@
 		return;
 	}
 
+	if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
+		/* Target has been bound to a new fw_ddb_index */
+		qla4xxx_free_ddb(ha, ddb_entry);
+		ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
+		if (ddb_entry == NULL) {
+			DEBUG2(printk(KERN_WARNING
+				"scsi%ld: Unable to allocate memory"
+				" to add fw_ddb_index %d\n",
+				ha->host_no, fw_ddb_index));
+			return;
+		}
+	}
 	if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
 				    QLA_ERROR) {
 		ha->fw_ddb_index_map[fw_ddb_index] =
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index a216a17..5006ecb 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -6,6 +6,10 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
+
 
 #include <scsi/scsi_tcq.h>
 
@@ -141,11 +145,13 @@
 	uint16_t avail_dsds;
 	struct data_seg_a64 *cur_dsd;
 	struct scsi_cmnd *cmd;
+	struct scatterlist *sg;
+	int i;
 
 	cmd = srb->cmd;
 	ha = srb->ha;
 
-	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+	if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
 		/* No data being transferred */
 		cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
 		return;
@@ -154,40 +160,27 @@
 	avail_dsds = COMMAND_SEG;
 	cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]);
 
-	/* Load data segments */
-	if (cmd->use_sg) {
-		struct scatterlist *cur_seg;
-		struct scatterlist *end_seg;
+	scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+		dma_addr_t sle_dma;
 
-		cur_seg = (struct scatterlist *)cmd->request_buffer;
-		end_seg = cur_seg + tot_dsds;
-		while (cur_seg < end_seg) {
-			dma_addr_t sle_dma;
+		/* Allocate additional continuation packets? */
+		if (avail_dsds == 0) {
+			struct continuation_t1_entry *cont_entry;
 
-			/* Allocate additional continuation packets? */
-			if (avail_dsds == 0) {
-				struct continuation_t1_entry *cont_entry;
-
-				cont_entry = qla4xxx_alloc_cont_entry(ha);
-				cur_dsd =
-					(struct data_seg_a64 *)
-					&cont_entry->dataseg[0];
-				avail_dsds = CONTINUE_SEG;
-			}
-
-			sle_dma = sg_dma_address(cur_seg);
-			cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
-			cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
-			cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg));
-			avail_dsds--;
-
-			cur_dsd++;
-			cur_seg++;
+			cont_entry = qla4xxx_alloc_cont_entry(ha);
+			cur_dsd =
+				(struct data_seg_a64 *)
+				&cont_entry->dataseg[0];
+			avail_dsds = CONTINUE_SEG;
 		}
-	} else {
-		cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle));
-		cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle));
-		cur_dsd->count = cpu_to_le32(cmd->request_bufflen);
+
+		sle_dma = sg_dma_address(sg);
+		cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
+		cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
+		cur_dsd->count = cpu_to_le32(sg_dma_len(sg));
+		avail_dsds--;
+
+		cur_dsd++;
 	}
 }
 
@@ -204,8 +197,8 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	struct ddb_entry *ddb_entry;
 	struct command_t3_entry *cmd_entry;
-	struct scatterlist *sg = NULL;
 
+	int nseg;
 	uint16_t tot_dsds;
 	uint16_t req_cnt;
 
@@ -233,24 +226,11 @@
 	index = (uint32_t)cmd->request->tag;
 
 	/* Calculate the number of request entries needed. */
-	if (cmd->use_sg) {
-		sg = (struct scatterlist *)cmd->request_buffer;
-		tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
-				      cmd->sc_data_direction);
-		if (tot_dsds == 0)
-			goto queuing_error;
-	} else if (cmd->request_bufflen) {
-		dma_addr_t	req_dma;
+	nseg = scsi_dma_map(cmd);
+	if (nseg < 0)
+		goto queuing_error;
+	tot_dsds = nseg;
 
-		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
-					 cmd->request_bufflen,
-					 cmd->sc_data_direction);
-		if (dma_mapping_error(req_dma))
-			goto queuing_error;
-
-		srb->dma_handle = req_dma;
-		tot_dsds = 1;
-	}
 	req_cnt = qla4xxx_calc_request_entries(tot_dsds);
 
 	if (ha->req_q_count < (req_cnt + 2)) {
@@ -279,7 +259,7 @@
 
 	int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
 	cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
-	cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen);
+	cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
 	memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
 	cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
 	cmd_entry->hdr.entryCount = req_cnt;
@@ -289,13 +269,13 @@
 	 *	 transferred, as the data direction bit is sometimed filled
 	 *	 in when there is no data to be transferred */
 	cmd_entry->control_flags = CF_NO_DATA;
-	if (cmd->request_bufflen) {
+	if (scsi_bufflen(cmd)) {
 		if (cmd->sc_data_direction == DMA_TO_DEVICE)
 			cmd_entry->control_flags = CF_WRITE;
 		else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
 			cmd_entry->control_flags = CF_READ;
 
-		ha->bytes_xfered += cmd->request_bufflen;
+		ha->bytes_xfered += scsi_bufflen(cmd);
 		if (ha->bytes_xfered & ~0xFFFFF){
 			ha->total_mbytes_xferred += ha->bytes_xfered >> 20;
 			ha->bytes_xfered &= 0xFFFFF;
@@ -359,14 +339,9 @@
 	return QLA_SUCCESS;
 
 queuing_error:
+	if (tot_dsds)
+		scsi_dma_unmap(cmd);
 
-	if (cmd->use_sg && tot_dsds) {
-		sg = (struct scatterlist *) cmd->request_buffer;
-		pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
-			     cmd->sc_data_direction);
-	} else if (tot_dsds)
-		pci_unmap_single(ha->pdev, srb->dma_handle,
-				 cmd->request_bufflen, cmd->sc_data_direction);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	return QLA_ERROR;
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 35b9e36..b47bd85 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 /**
  * qla2x00_process_completed_request() - Process a Fast Post response.
@@ -92,7 +95,7 @@
 
 		if (sts_entry->iscsiFlags &
 		    (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER))
-			cmd->resid = residual;
+			scsi_set_resid(cmd, residual);
 
 		cmd->result = DID_OK << 16 | scsi_status;
 
@@ -176,14 +179,14 @@
 			 * Firmware detected a SCSI transport underrun
 			 * condition
 			 */
-			cmd->resid = residual;
+			scsi_set_resid(cmd, residual);
 			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
 				      "detected, xferlen = 0x%x, residual = "
 				      "0x%x\n",
 				      ha->host_no, cmd->device->channel,
 				      cmd->device->id,
 				      cmd->device->lun, __func__,
-				      cmd->request_bufflen,
+				      scsi_bufflen(cmd),
 				      residual));
 		}
 
@@ -227,7 +230,7 @@
 			if ((sts_entry->iscsiFlags &
 			     ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
 				cmd->result = DID_BUS_BUSY << 16;
-			} else if ((cmd->request_bufflen - residual) <
+			} else if ((scsi_bufflen(cmd) - residual) <
 				   cmd->underflow) {
 				/*
 				 * Handle mid-layer underflow???
@@ -248,7 +251,7 @@
 					      cmd->device->channel,
 					      cmd->device->id,
 					      cmd->device->lun, __func__,
-					      cmd->request_bufflen, residual));
+					      scsi_bufflen(cmd), residual));
 
 				cmd->result = DID_ERROR << 16;
 			} else {
@@ -417,6 +420,7 @@
 				       uint32_t mbox_status)
 {
 	int i;
+	uint32_t mbox_stat2, mbox_stat3;
 
 	if ((mbox_status == MBOX_STS_BUSY) ||
 	    (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
@@ -437,6 +441,12 @@
 	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
 		/* Immediately process the AENs that don't require much work.
 		 * Only queue the database_changed AENs */
+		if (ha->aen_log.count < MAX_AEN_ENTRIES) {
+			for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
+				ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
+					readl(&ha->reg->mailbox[i]);
+			ha->aen_log.count++;
+		}
 		switch (mbox_status) {
 		case MBOX_ASTS_SYSTEM_ERROR:
 			/* Log Mailbox registers */
@@ -493,6 +503,16 @@
 				      mbox_status));
 			break;
 
+		case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
+			mbox_stat2 = readl(&ha->reg->mailbox[2]);
+			mbox_stat3 = readl(&ha->reg->mailbox[3]);
+
+			if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
+				set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
+			else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
+				set_bit(DPC_RESET_HA, &ha->dpc_flags);
+			break;
+
 		case MBOX_ASTS_MAC_ADDRESS_CHANGED:
 		case MBOX_ASTS_DNS:
 			/* No action */
@@ -518,11 +538,6 @@
 			/* Queue AEN information and process it in the DPC
 			 * routine */
 			if (ha->aen_q_count > 0) {
-				/* advance pointer */
-				if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
-					ha->aen_in = 0;
-				else
-					ha->aen_in++;
 
 				/* decrement available counter */
 				ha->aen_q_count--;
@@ -542,6 +557,10 @@
 					      ha->aen_q[ha->aen_in].mbox_sts[2],
 					      ha->aen_q[ha->aen_in].mbox_sts[3],
 					      ha->aen_q[ha->aen_in].  mbox_sts[4]));
+				/* advance pointer */
+				ha->aen_in++;
+				if (ha->aen_in == MAX_AEN_ENTRIES)
+					ha->aen_in = 0;
 
 				/* The DPC routine will process the aen */
 				set_bit(DPC_AEN, &ha->dpc_flags);
@@ -724,25 +743,24 @@
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	while (ha->aen_out != ha->aen_in) {
-		/* Advance pointers for next entry */
-		if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
-			ha->aen_out = 0;
-		else
-			ha->aen_out++;
-
-		ha->aen_q_count++;
 		aen = &ha->aen_q[ha->aen_out];
-
 		/* copy aen information to local structure */
 		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
 			mbox_sts[i] = aen->mbox_sts[i];
 
+		ha->aen_q_count++;
+		ha->aen_out++;
+
+		if (ha->aen_out == MAX_AEN_ENTRIES)
+			ha->aen_out = 0;
+
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x "
-			     "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out,
-			     mbox_sts[0], mbox_sts[2], mbox_sts[3],
-			     mbox_sts[1], mbox_sts[4]));
+		DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
+			" mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
+			(ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
+			mbox_sts[0], mbox_sts[1], mbox_sts[2],
+			mbox_sts[3], mbox_sts[4]));
 
 		switch (mbox_sts[0]) {
 		case MBOX_ASTS_DATABASE_CHANGED:
@@ -792,6 +810,5 @@
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 	}
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
 }
 
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index f116ff9..35cd73c 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 
 /**
@@ -169,84 +172,6 @@
 	return status;
 }
 
-
-#if 0
-
-/**
- * qla4xxx_issue_iocb - issue mailbox iocb command
- * @ha: adapter state pointer.
- * @buffer: buffer pointer.
- * @phys_addr: physical address of buffer.
- * @size: size of buffer.
- *
- * Issues iocbs via mailbox commands.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- **/
-int
-qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
-		   dma_addr_t phys_addr, size_t size)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-	int status;
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
-	mbox_cmd[1] = 0;
-	mbox_cmd[2] = LSDW(phys_addr);
-	mbox_cmd[3] = MSDW(phys_addr);
-	status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
-	return status;
-}
-
-int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
-				   uint16_t fw_ddb_index,
-				   uint16_t connection_id,
-				   uint16_t option)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
-	mbox_cmd[1] = fw_ddb_index;
-	mbox_cmd[2] = connection_id;
-	mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
-	if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
-	    QLA_SUCCESS) {
-		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
-			      "option %04x failed sts %04X %04X",
-			      ha->host_no, __func__,
-			      option, mbox_sts[0], mbox_sts[1]));
-		if (mbox_sts[0] == 0x4005)
-			DEBUG2(printk("%s reason %04X\n", __func__,
-				      mbox_sts[1]));
-	}
-	return QLA_SUCCESS;
-}
-
-int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
-				 uint16_t fw_ddb_index)
-{
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
-	mbox_cmd[1] = fw_ddb_index;
-	if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-	    QLA_SUCCESS)
-		return QLA_ERROR;
-
-	return QLA_SUCCESS;
-}
-
-#endif  /*  0  */
-
 /**
  * qla4xxx_initialize_fw_cb - initializes firmware control block.
  * @ha: Pointer to host adapter structure.
@@ -272,10 +197,13 @@
 	/* Get Initialize Firmware Control Block. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		dma_free_coherent(&ha->pdev->dev,
 				  sizeof(struct init_fw_ctrl_blk),
@@ -287,51 +215,56 @@
 	qla4xxx_init_rings(ha);
 
 	/* Fill in the request and response queue information. */
-	init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
-	init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
-	init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
-	init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
-	init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
-	init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
-	init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
-	init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
-	init_fw_cb->ShadowRegBufAddrLo =
+	init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out);
+	init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in);
+	init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
+	init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
+	init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
+	init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
+	init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
+	init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
+	init_fw_cb->pri.shdwreg_addr_lo =
 		cpu_to_le32(LSDW(ha->shadow_regs_dma));
-	init_fw_cb->ShadowRegBufAddrHi =
+	init_fw_cb->pri.shdwreg_addr_hi =
 		cpu_to_le32(MSDW(ha->shadow_regs_dma));
 
 	/* Set up required options. */
-	init_fw_cb->FwOptions |=
+	init_fw_cb->pri.fw_options |=
 		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
 				       FWOPT_INITIATOR_MODE);
-	init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
+	init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
 
 	/* Save some info in adapter structure. */
-	ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
-	ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
-	ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
-	memcpy(ha->ip_address, init_fw_cb->IPAddr,
-	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
-	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
-	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
-	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
-	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
-	memcpy(ha->name_string, init_fw_cb->iSCSINameString,
+	ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options);
+	ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts);
+	ha->heartbeat_interval = init_fw_cb->pri.hb_interval;
+	memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+	memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+	memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
+	memcpy(ha->name_string, init_fw_cb->pri.iscsi_name,
 	       min(sizeof(ha->name_string),
-		   sizeof(init_fw_cb->iSCSINameString)));
-	memcpy(ha->alias, init_fw_cb->Alias,
-	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
+		   sizeof(init_fw_cb->pri.iscsi_name)));
+	/*memcpy(ha->alias, init_fw_cb->Alias,
+	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
 
 	/* Save Command Line Paramater info */
-	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
+	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout);
 	ha->discovery_wait = ql4xdiscoverywait;
 
 	/* Send Initialize Firmware Control Block. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
 	mbox_cmd[1] = 0;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) ==
 	    QLA_SUCCESS)
 		status = QLA_SUCCESS;
 	 else {
@@ -368,12 +301,14 @@
 	/* Get Initialize Firmware Control Block. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
 	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
 	mbox_cmd[2] = LSDW(init_fw_cb_dma);
 	mbox_cmd[3] = MSDW(init_fw_cb_dma);
+	mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
 
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
 			      ha->host_no, __func__));
@@ -384,12 +319,12 @@
 	}
 
 	/* Save IP Address. */
-	memcpy(ha->ip_address, init_fw_cb->IPAddr,
-	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
-	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
-	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
-	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
-	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
+	memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+	memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+	memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
 
 	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
 			  init_fw_cb, init_fw_cb_dma);
@@ -409,8 +344,10 @@
 	/* Get firmware version */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
-	if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
 			      "status %04X\n", ha->host_no, __func__,
@@ -438,8 +375,10 @@
 	/* Get firmware version */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
-	if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
 			      "status %04X\n", ha->host_no, __func__,
@@ -491,11 +430,14 @@
 	}
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
+	mbox_cmd[4] = sizeof(struct dev_db_entry);
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
 	    QLA_ERROR) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
 			      " with status 0x%04X\n", ha->host_no, __func__,
@@ -512,11 +454,11 @@
 		dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
 			   "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
 			   fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
-			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
-			   fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
-			   fw_ddb_entry->ipAddr[3],
-			   le16_to_cpu(fw_ddb_entry->portNumber),
-			   fw_ddb_entry->iscsiName);
+			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0],
+			   fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2],
+			   fw_ddb_entry->ip_addr[3],
+			   le16_to_cpu(fw_ddb_entry->port),
+			   fw_ddb_entry->iscsi_name);
 	}
 	if (num_valid_ddb_entries)
 		*num_valid_ddb_entries = mbox_sts[2];
@@ -571,36 +513,11 @@
 	mbox_cmd[1] = (uint32_t) fw_ddb_index;
 	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
 	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
-	return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
+	mbox_cmd[4] = sizeof(struct dev_db_entry);
+
+	return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
 }
 
-#if 0
-int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
-				    uint16_t fw_ddb_index)
-{
-	int status = QLA_ERROR;
-	uint32_t mbox_cmd[MBOX_REG_COUNT];
-	uint32_t mbox_sts[MBOX_REG_COUNT];
-
-	/* Do not wait for completion. The firmware will send us an
-	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
-	 */
-	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-	memset(&mbox_sts, 0, sizeof(mbox_sts));
-	mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
-	mbox_cmd[1] = (uint32_t) fw_ddb_index;
-	mbox_cmd[2] = 0;
-	mbox_cmd[3] = 0;
-	mbox_cmd[4] = 0;
-	status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
-	DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
-		      __func__, fw_ddb_index, status, mbox_sts[0],
-		      mbox_sts[1]);)
-
-		return status;
-}
-#endif  /*  0  */
-
 /**
  * qla4xxx_get_crash_record - retrieves crash record.
  * @ha: Pointer to host adapter structure.
@@ -614,12 +531,14 @@
 	struct crash_record *crash_record = NULL;
 	dma_addr_t crash_record_dma = 0;
 	uint32_t crash_record_size = 0;
+
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_cmd));
 
 	/* Get size of crash record. */
 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
-	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
 			      ha->host_no, __func__));
@@ -639,11 +558,15 @@
 		goto exit_get_crash_record;
 
 	/* Get Crash Record. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
 	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
 	mbox_cmd[2] = LSDW(crash_record_dma);
 	mbox_cmd[3] = MSDW(crash_record_dma);
 	mbox_cmd[4] = crash_record_size;
-	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS)
 		goto exit_get_crash_record;
 
@@ -655,7 +578,6 @@
 				  crash_record, crash_record_dma);
 }
 
-#if 0
 /**
  * qla4xxx_get_conn_event_log - retrieves connection event log
  * @ha: Pointer to host adapter structure.
@@ -678,7 +600,8 @@
 
 	/* Get size of crash record. */
 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS)
 		goto exit_get_event_log;
 
@@ -693,10 +616,14 @@
 		goto exit_get_event_log;
 
 	/* Get Crash Record. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
 	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
 	mbox_cmd[2] = LSDW(event_log_dma);
 	mbox_cmd[3] = MSDW(event_log_dma);
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
 			      "log!\n", ha->host_no, __func__));
@@ -745,7 +672,6 @@
 		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
 				  event_log_dma);
 }
-#endif  /*  0  */
 
 /**
  * qla4xxx_reset_lun - issues LUN Reset
@@ -773,11 +699,13 @@
 	 */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
 	mbox_cmd[1] = ddb_entry->fw_ddb_index;
 	mbox_cmd[2] = lun << 8;
 	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
-	qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
+
+	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
 	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
 		status = QLA_ERROR;
@@ -794,12 +722,14 @@
 
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
 	mbox_cmd[1] = LSDW(dma_addr);
 	mbox_cmd[2] = MSDW(dma_addr);
 	mbox_cmd[3] = offset;
 	mbox_cmd[4] = len;
-	if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
 		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
@@ -825,8 +755,10 @@
 	/* Get firmware version. */
 	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
 	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
 	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
-	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
 		    "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
@@ -855,7 +787,7 @@
 	mbox_cmd[2] = LSDW(dma_addr);
 	mbox_cmd[3] = MSDW(dma_addr);
 
-	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
 		     ha->host_no, __func__, mbox_sts[0]));
@@ -875,7 +807,7 @@
 	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
 	mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
 
-	if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+	if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
 	    QLA_SUCCESS) {
 		if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
 			*ddb_index = mbox_sts[2];
@@ -918,23 +850,23 @@
 	if (ret_val != QLA_SUCCESS)
 		goto qla4xxx_send_tgts_exit;
 
-	memset((void *)fw_ddb_entry->iSCSIAlias, 0,
-	       sizeof(fw_ddb_entry->iSCSIAlias));
+	memset(fw_ddb_entry->iscsi_alias, 0,
+	       sizeof(fw_ddb_entry->iscsi_alias));
 
-	memset((void *)fw_ddb_entry->iscsiName, 0,
-	       sizeof(fw_ddb_entry->iscsiName));
+	memset(fw_ddb_entry->iscsi_name, 0,
+	       sizeof(fw_ddb_entry->iscsi_name));
 
-	memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
-	memset((void *)fw_ddb_entry->targetAddr, 0,
-	       sizeof(fw_ddb_entry->targetAddr));
+	memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
+	memset(fw_ddb_entry->tgt_addr, 0,
+	       sizeof(fw_ddb_entry->tgt_addr));
 
 	fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
-	fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
+	fw_ddb_entry->port = cpu_to_le16(ntohs(port));
 
-	fw_ddb_entry->ipAddr[0] = *ip;
-	fw_ddb_entry->ipAddr[1] = *(ip + 1);
-	fw_ddb_entry->ipAddr[2] = *(ip + 2);
-	fw_ddb_entry->ipAddr[3] = *(ip + 3);
+	fw_ddb_entry->ip_addr[0] = *ip;
+	fw_ddb_entry->ip_addr[1] = *(ip + 1);
+	fw_ddb_entry->ip_addr[2] = *(ip + 2);
+	fw_ddb_entry->ip_addr[3] = *(ip + 3);
 
 	ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
 
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index 58afd13..7fe0482 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -6,6 +6,9 @@
  */
 
 #include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha)
 {
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index da21f5f..e09fc42 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -10,6 +10,10 @@
 #include <scsi/scsicam.h>
 
 #include "ql4_def.h"
+#include "ql4_version.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
 
 /*
  * Driver version
@@ -369,14 +373,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 
 	if (srb->flags & SRB_DMA_VALID) {
-		if (cmd->use_sg) {
-			pci_unmap_sg(ha->pdev, cmd->request_buffer,
-				     cmd->use_sg, cmd->sc_data_direction);
-		} else if (cmd->request_bufflen) {
-			pci_unmap_single(ha->pdev, srb->dma_handle,
-					 cmd->request_bufflen,
-					 cmd->sc_data_direction);
-		}
+		scsi_dma_unmap(cmd);
 		srb->flags &= ~SRB_DMA_VALID;
 	}
 	cmd->SCp.ptr = NULL;
@@ -711,7 +708,7 @@
 	return stat;
 }
 
-static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
+void qla4xxx_hw_reset(struct scsi_qla_host *ha)
 {
 	uint32_t ctrl_status;
 	unsigned long flags = 0;
@@ -1081,13 +1078,13 @@
 	if (ha->timer_active)
 		qla4xxx_stop_timer(ha);
 
-	/* free extra memory */
-	qla4xxx_mem_free(ha);
-
 	/* Detach interrupts */
 	if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
 		free_irq(ha->pdev->irq, ha);
 
+	/* free extra memory */
+	qla4xxx_mem_free(ha);
+
 	pci_disable_device(ha->pdev);
 
 }
@@ -1332,6 +1329,11 @@
 
 	ha = pci_get_drvdata(pdev);
 
+	qla4xxx_disable_intrs(ha);
+
+	while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+		ssleep(1);
+
 	/* remove devs from iscsi_sessions to scsi_devices */
 	qla4xxx_free_ddb_list(ha);
 
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index e5183a6..2149069 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,5 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.00.07-k1"
+#define QLA4XXX_DRIVER_VERSION	"5.01.00-k7"
+
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 2e7db18..2bfbf26 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -265,8 +265,6 @@
 	unsigned int message;	/* scsi returned message */
 	unsigned int phase;	/* recorded scsi phase */
 	unsigned int reqlen;	/* total length of transfer */
-	struct scatterlist *sglist;	/* scatter-gather list pointer */
-	unsigned int sgcount;	/* sg counter */
 	char *buf;
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
 	int qbase = priv->qbase;
@@ -301,9 +299,10 @@
 	if (inb(qbase + 7) & 0x1f)	/* if some bytes in fifo */
 		outb(1, qbase + 3);	/* clear fifo */
 	/* note that request_bufflen is the total xfer size when sg is used */
-	reqlen = cmd->request_bufflen;
+	reqlen = scsi_bufflen(cmd);
 	/* note that it won't work if transfers > 16M are requested */
 	if (reqlen && !((phase = inb(qbase + 4)) & 6)) {	/* data phase */
+		struct scatterlist *sg;
 		rtrc(2)
 		outb(reqlen, qbase);	/* low-mid xfer cnt */
 		outb(reqlen >> 8, qbase + 1);	/* low-mid xfer cnt */
@@ -311,23 +310,16 @@
 		outb(0x90, qbase + 3);	/* command do xfer */
 		/* PIO pseudo DMA to buffer or sglist */
 		REG1;
-		if (!cmd->use_sg)
-			ql_pdma(priv, phase, cmd->request_buffer,
-				cmd->request_bufflen);
-		else {
-			sgcount = cmd->use_sg;
-			sglist = cmd->request_buffer;
-			while (sgcount--) {
-				if (priv->qabort) {
-					REG0;
-					return ((priv->qabort == 1 ?
-						DID_ABORT : DID_RESET) << 16);
-				}
-				buf = page_address(sglist->page) + sglist->offset;
-				if (ql_pdma(priv, phase, buf, sglist->length))
-					break;
-				sglist++;
+
+		scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
+			if (priv->qabort) {
+				REG0;
+				return ((priv->qabort == 1 ?
+					 DID_ABORT : DID_RESET) << 16);
 			}
+			buf = page_address(sg->page) + sg->offset;
+			if (ql_pdma(priv, phase, buf, sg->length))
+				break;
 		}
 		REG0;
 		rtrc(2)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index e8350c5..9adb64a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -18,12 +18,12 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/scatterlist.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -640,16 +640,8 @@
 	memcpy(scmd->cmnd, cmnd, cmnd_size);
 
 	if (copy_sense) {
-		gfp_t gfp_mask = GFP_ATOMIC;
-
-		if (shost->hostt->unchecked_isa_dma)
-			gfp_mask |= __GFP_DMA;
-
-		sgl.page = alloc_page(gfp_mask);
-		if (!sgl.page)
-			return FAILED;
-		sgl.offset = 0;
-		sgl.length = 252;
+		sg_init_one(&sgl, scmd->sense_buffer,
+			    sizeof(scmd->sense_buffer));
 
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
 		scmd->request_bufflen = sgl.length;
@@ -720,18 +712,6 @@
 
 
 	/*
-	 * Last chance to have valid sense data.
-	 */
-	if (copy_sense) {
-		if (!SCSI_SENSE_VALID(scmd)) {
-			memcpy(scmd->sense_buffer, page_address(sgl.page),
-			       sizeof(scmd->sense_buffer));
-		}
-		__free_page(sgl.page);
-	}
-
-
-	/*
 	 * Restore original data
 	 */
 	scmd->request_buffer = old_buffer;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1f5a07b..70454b4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2290,3 +2290,41 @@
 	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
 }
 EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
+
+/**
+ * scsi_dma_map - perform DMA mapping against command's sg lists
+ * @cmd:	scsi command
+ *
+ * Returns the number of sg lists actually used, zero if the sg lists
+ * is NULL, or -ENOMEM if the mapping failed.
+ */
+int scsi_dma_map(struct scsi_cmnd *cmd)
+{
+	int nseg = 0;
+
+	if (scsi_sg_count(cmd)) {
+		struct device *dev = cmd->device->host->shost_gendev.parent;
+
+		nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+				  cmd->sc_data_direction);
+		if (unlikely(!nseg))
+			return -ENOMEM;
+	}
+	return nseg;
+}
+EXPORT_SYMBOL(scsi_dma_map);
+
+/**
+ * scsi_dma_unmap - unmap command's sg lists mapped by scsi_dma_map
+ * @cmd:	scsi command
+ */
+void scsi_dma_unmap(struct scsi_cmnd *cmd)
+{
+	if (scsi_sg_count(cmd)) {
+		struct device *dev = cmd->device->host->shost_gendev.parent;
+
+		dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+			     cmd->sc_data_direction);
+	}
+}
+EXPORT_SYMBOL(scsi_dma_unmap);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 67a38a1..ed72086 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -293,30 +293,18 @@
 {
 	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
-	struct scsi_host_template *sht = sdev->host->hostt;
 	int err;
 
 	err = scsi_device_quiesce(sdev);
 	if (err)
 		return err;
 
-	/* call HLD suspend first */
 	if (drv && drv->suspend) {
 		err = drv->suspend(dev, state);
 		if (err)
 			return err;
 	}
 
-	/* then, call host suspend */
-	if (sht->suspend) {
-		err = sht->suspend(sdev, state);
-		if (err) {
-			if (drv && drv->resume)
-				drv->resume(dev);
-			return err;
-		}
-	}
-
 	return 0;
 }
 
@@ -324,21 +312,14 @@
 {
 	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
-	struct scsi_host_template *sht = sdev->host->hostt;
-	int err = 0, err2 = 0;
+	int err = 0;
 
-	/* call host resume first */
-	if (sht->resume)
-		err = sht->resume(sdev);
-
-	/* then, call HLD resume */
 	if (drv && drv->resume)
-		err2 = drv->resume(dev);
+		err = drv->resume(dev);
 
 	scsi_device_resume(sdev);
 
-	/* favor LLD failure */
-	return err ? err : err2;;
+	return err;
 }
 
 struct bus_type scsi_bus_type = {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index b4d1ece..4953f0d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1,4 +1,4 @@
-/* 
+/*
  *  FiberChannel transport specific attributes exported to sysfs.
  *
  *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
@@ -19,9 +19,10 @@
  *
  *  ========
  *
- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
  *    Rewrite for host, target, device, and remote port attributes,
  *    statistics, and service functions...
+ *    Add vports, etc
  *
  */
 #include <linux/module.h>
@@ -37,6 +38,34 @@
 #include "scsi_priv.h"
 
 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+static void fc_vport_sched_delete(struct work_struct *work);
+
+/*
+ * This is a temporary carrier for creating a vport. It will eventually
+ * be replaced  by a real message definition for sgio or netlink.
+ *
+ * fc_vport_identifiers: This set of data contains all elements
+ * to uniquely identify and instantiate a FC virtual port.
+ *
+ * Notes:
+ *   symbolic_name: The driver is to append the symbolic_name string data
+ *      to the symbolic_node_name data that it generates by default.
+ *      the resulting combination should then be registered with the switch.
+ *      It is expected that things like Xen may stuff a VM title into
+ *      this field.
+ */
+struct fc_vport_identifiers {
+	u64 node_name;
+	u64 port_name;
+	u32 roles;
+	bool disable;
+	enum fc_port_type vport_type;	/* only FC_PORTTYPE_NPIV allowed */
+	char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+};
+
+static int fc_vport_create(struct Scsi_Host *shost, int channel,
+	struct device *pdev, struct fc_vport_identifiers  *ids,
+	struct fc_vport **vport);
 
 /*
  * Redefine so that we can have same named attributes in the
@@ -90,10 +119,14 @@
 	{ FC_PORTTYPE_NLPORT,	"NLPort (fabric via loop)" },
 	{ FC_PORTTYPE_LPORT,	"LPort (private loop)" },
 	{ FC_PORTTYPE_PTP,	"Point-To-Point (direct nport connection" },
+	{ FC_PORTTYPE_NPIV,		"NPIV VPORT" },
 };
 fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
 #define FC_PORTTYPE_MAX_NAMELEN		50
 
+/* Reuse fc_port_type enum function for vport_type */
+#define get_fc_vport_type_name get_fc_port_type_name
+
 
 /* Convert fc_host_event_code values to ascii string name */
 static const struct {
@@ -139,6 +172,29 @@
 #define FC_PORTSTATE_MAX_NAMELEN	20
 
 
+/* Convert fc_vport_state values to ascii string name */
+static struct {
+	enum fc_vport_state	value;
+	char			*name;
+} fc_vport_state_names[] = {
+	{ FC_VPORT_UNKNOWN,		"Unknown" },
+	{ FC_VPORT_ACTIVE,		"Active" },
+	{ FC_VPORT_DISABLED,		"Disabled" },
+	{ FC_VPORT_LINKDOWN,		"Linkdown" },
+	{ FC_VPORT_INITIALIZING,	"Initializing" },
+	{ FC_VPORT_NO_FABRIC_SUPP,	"No Fabric Support" },
+	{ FC_VPORT_NO_FABRIC_RSCS,	"No Fabric Resources" },
+	{ FC_VPORT_FABRIC_LOGOUT,	"Fabric Logout" },
+	{ FC_VPORT_FABRIC_REJ_WWN,	"Fabric Rejected WWN" },
+	{ FC_VPORT_FAILED,		"VPort Failed" },
+};
+fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
+#define FC_VPORTSTATE_MAX_NAMELEN	24
+
+/* Reuse fc_vport_state enum function for vport_last_state */
+#define get_fc_vport_last_state_name get_fc_vport_state_name
+
+
 /* Convert fc_tgtid_binding_type values to ascii string name */
 static const struct {
 	enum fc_tgtid_binding_type	value;
@@ -219,16 +275,16 @@
 }
 
 
-/* Convert FC_RPORT_ROLE bit values to ascii string name */
+/* Convert FC_PORT_ROLE bit values to ascii string name */
 static const struct {
 	u32 			value;
 	char			*name;
-} fc_remote_port_role_names[] = {
-	{ FC_RPORT_ROLE_FCP_TARGET,	"FCP Target" },
-	{ FC_RPORT_ROLE_FCP_INITIATOR,	"FCP Initiator" },
-	{ FC_RPORT_ROLE_IP_PORT,	"IP Port" },
+} fc_port_role_names[] = {
+	{ FC_PORT_ROLE_FCP_TARGET,	"FCP Target" },
+	{ FC_PORT_ROLE_FCP_INITIATOR,	"FCP Initiator" },
+	{ FC_PORT_ROLE_IP_PORT,		"IP Port" },
 };
-fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
+fc_bitfield_name_search(port_roles, fc_port_role_names)
 
 /*
  * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
@@ -252,7 +308,8 @@
  */
 #define FC_STARGET_NUM_ATTRS 	3
 #define FC_RPORT_NUM_ATTRS	10
-#define FC_HOST_NUM_ATTRS	17
+#define FC_VPORT_NUM_ATTRS	9
+#define FC_HOST_NUM_ATTRS	21
 
 struct fc_internal {
 	struct scsi_transport_template t;
@@ -278,6 +335,10 @@
 	struct transport_container rport_attr_cont;
 	struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
 	struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
+
+	struct transport_container vport_attr_cont;
+	struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
+	struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
 };
 
 #define to_fc_internal(tmpl)	container_of(tmpl, struct fc_internal, t)
@@ -318,7 +379,7 @@
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 
-	/* 
+	/*
 	 * Set default values easily detected by the midlayer as
 	 * failure cases.  The scsi lldd is responsible for initializing
 	 * all transport attributes to valid values per host.
@@ -331,6 +392,7 @@
 		sizeof(fc_host->supported_fc4s));
 	fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
 	fc_host->maxframe_size = -1;
+	fc_host->max_npiv_vports = 0;
 	memset(fc_host->serial_number, 0,
 		sizeof(fc_host->serial_number));
 
@@ -348,8 +410,11 @@
 
 	INIT_LIST_HEAD(&fc_host->rports);
 	INIT_LIST_HEAD(&fc_host->rport_bindings);
+	INIT_LIST_HEAD(&fc_host->vports);
 	fc_host->next_rport_number = 0;
 	fc_host->next_target_id = 0;
+	fc_host->next_vport_number = 0;
+	fc_host->npiv_vports_inuse = 0;
 
 	snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
 		shost->host_no);
@@ -388,6 +453,16 @@
 			       NULL);
 
 /*
+ * Setup and Remove actions for virtual ports are handled
+ * in the service functions below.
+ */
+static DECLARE_TRANSPORT_CLASS(fc_vport_class,
+			       "fc_vports",
+			       NULL,
+			       NULL,
+			       NULL);
+
+/*
  * Module Parameters
  */
 
@@ -585,6 +660,9 @@
 	error = transport_class_register(&fc_host_class);
 	if (error)
 		return error;
+	error = transport_class_register(&fc_vport_class);
+	if (error)
+		return error;
 	error = transport_class_register(&fc_rport_class);
 	if (error)
 		return error;
@@ -596,6 +674,7 @@
 	transport_class_unregister(&fc_transport_class);
 	transport_class_unregister(&fc_rport_class);
 	transport_class_unregister(&fc_host_class);
+	transport_class_unregister(&fc_vport_class);
 }
 
 /*
@@ -800,9 +879,9 @@
 			return snprintf(buf, 30, "Unknown Fabric Entity\n");
 		}
 	} else {
-		if (rport->roles == FC_RPORT_ROLE_UNKNOWN)
+		if (rport->roles == FC_PORT_ROLE_UNKNOWN)
 			return snprintf(buf, 20, "unknown\n");
-		return get_fc_remote_port_roles_names(rport->roles, buf);
+		return get_fc_port_roles_names(rport->roles, buf);
 	}
 }
 static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
@@ -857,7 +936,7 @@
 
 /*
  * Note: in the target show function we recognize when the remote
- *  port is in the hierarchy and do not allow the driver to get
+ *  port is in the heirarchy and do not allow the driver to get
  *  involved in sysfs functions. The driver only gets involved if
  *  it's the "old" style that doesn't use rports.
  */
@@ -912,6 +991,257 @@
 
 
 /*
+ * FC Virtual Port Attribute Management
+ */
+
+#define fc_vport_show_function(field, format_string, sz, cast)		\
+static ssize_t								\
+show_fc_vport_##field (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	if ((i->f->get_vport_##field) &&				\
+	    !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)))	\
+		i->f->get_vport_##field(vport);				\
+	return snprintf(buf, sz, format_string, cast vport->field); 	\
+}
+
+#define fc_vport_store_function(field)					\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	int val;							\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	char *cp;							\
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))	\
+		return -EBUSY;						\
+	val = simple_strtoul(buf, &cp, 0);				\
+	if (*cp && (*cp != '\n'))					\
+		return -EINVAL;						\
+	i->f->set_vport_##field(vport, val);				\
+	return count;							\
+}
+
+#define fc_vport_store_str_function(field, slen)			\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	struct Scsi_Host *shost = vport_to_shost(vport);		\
+	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+	unsigned int cnt=count;						\
+									\
+	/* count may include a LF at end of string */			\
+	if (buf[cnt-1] == '\n')						\
+		cnt--;							\
+	if (cnt > ((slen) - 1))						\
+		return -EINVAL;						\
+	memcpy(vport->field, buf, cnt);					\
+	i->f->set_vport_##field(vport);					\
+	return count;							\
+}
+
+#define fc_vport_rd_attr(field, format_string, sz)			\
+	fc_vport_show_function(field, format_string, sz, )		\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			 show_fc_vport_##field, NULL)
+
+#define fc_vport_rd_attr_cast(field, format_string, sz, cast)		\
+	fc_vport_show_function(field, format_string, sz, (cast))	\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			  show_fc_vport_##field, NULL)
+
+#define fc_vport_rw_attr(field, format_string, sz)			\
+	fc_vport_show_function(field, format_string, sz, )		\
+	fc_vport_store_function(field)					\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+			show_fc_vport_##field,				\
+			store_fc_vport_##field)
+
+#define fc_private_vport_show_function(field, format_string, sz, cast)	\
+static ssize_t								\
+show_fc_vport_##field (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	return snprintf(buf, sz, format_string, cast vport->field); 	\
+}
+
+#define fc_private_vport_store_u32_function(field)			\
+static ssize_t								\
+store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+			   size_t count)				\
+{									\
+	u32 val;							\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	char *cp;							\
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))		\
+		return -EBUSY;						\
+	val = simple_strtoul(buf, &cp, 0);				\
+	if (*cp && (*cp != '\n'))					\
+		return -EINVAL;						\
+	vport->field = val;						\
+	return count;							\
+}
+
+
+#define fc_private_vport_rd_attr(field, format_string, sz)		\
+	fc_private_vport_show_function(field, format_string, sz, )	\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			 show_fc_vport_##field, NULL)
+
+#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast)	\
+	fc_private_vport_show_function(field, format_string, sz, (cast)) \
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
+			  show_fc_vport_##field, NULL)
+
+#define fc_private_vport_rw_u32_attr(field, format_string, sz)		\
+	fc_private_vport_show_function(field, format_string, sz, )	\
+	fc_private_vport_store_u32_function(field)			\
+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+			show_fc_vport_##field,				\
+			store_fc_vport_##field)
+
+
+#define fc_private_vport_rd_enum_attr(title, maxlen)			\
+static ssize_t								\
+show_fc_vport_##title (struct class_device *cdev, char *buf)		\
+{									\
+	struct fc_vport *vport = transport_class_to_vport(cdev);	\
+	const char *name;						\
+	name = get_fc_##title##_name(vport->title);			\
+	if (!name)							\
+		return -EINVAL;						\
+	return snprintf(buf, maxlen, "%s\n", name);			\
+}									\
+static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,			\
+			show_fc_vport_##title, NULL)
+
+
+#define SETUP_VPORT_ATTRIBUTE_RD(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_vport_attrs[count].store = NULL;			\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	if (i->f->get_##field)						\
+		count++
+	/* NOTE: Above MACRO differs: checks function not show bit */
+
+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)				\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_vport_attrs[count].store = NULL;			\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++
+
+#define SETUP_VPORT_ATTRIBUTE_WR(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	if (i->f->field)						\
+		count++
+	/* NOTE: Above MACRO differs: checks function */
+
+#define SETUP_VPORT_ATTRIBUTE_RW(field)					\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	if (!i->f->set_vport_##field) {					\
+		i->private_vport_attrs[count].attr.mode = S_IRUGO;	\
+		i->private_vport_attrs[count].store = NULL;		\
+	}								\
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++
+	/* NOTE: Above MACRO differs: does not check show bit */
+
+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)				\
+{									\
+	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+	count++;							\
+}
+
+
+/* The FC Transport Virtual Port Attributes: */
+
+/* Fixed Virtual Port Attributes */
+
+/* Dynamic Virtual Port Attributes */
+
+/* Private Virtual Port Attributes */
+
+fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
+fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+
+static ssize_t
+show_fc_vport_roles (struct class_device *cdev, char *buf)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+
+	if (vport->roles == FC_PORT_ROLE_UNKNOWN)
+		return snprintf(buf, 20, "unknown\n");
+	return get_fc_port_roles_names(vport->roles, buf);
+}
+static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
+
+fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+
+fc_private_vport_show_function(symbolic_name, "%s\n",
+		FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
+		show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
+
+static ssize_t
+store_fc_vport_delete(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+	struct Scsi_Host *shost = vport_to_shost(vport);
+
+	fc_queue_work(shost, &vport->vport_delete_work);
+	return count;
+}
+static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+			NULL, store_fc_vport_delete);
+
+
+/*
+ * Enable/Disable vport
+ *  Write "1" to disable, write "0" to enable
+ */
+static ssize_t
+store_fc_vport_disable(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct fc_vport *vport = transport_class_to_vport(cdev);
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_internal *i = to_fc_internal(shost->transportt);
+	int stat;
+
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
+		return -EBUSY;
+
+	if (*buf == '0') {
+		if (vport->vport_state != FC_VPORT_DISABLED)
+			return -EALREADY;
+	} else if (*buf == '1') {
+		if (vport->vport_state == FC_VPORT_DISABLED)
+			return -EALREADY;
+	} else
+		return -EINVAL;
+
+	stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+			NULL, store_fc_vport_disable);
+
+
+/*
  * Host Attribute Management
  */
 
@@ -1003,6 +1333,13 @@
 	if (i->f->show_host_##field)					\
 		count++
 
+#define SETUP_HOST_ATTRIBUTE_RD_NS(field)				\
+	i->private_host_attrs[count] = class_device_attr_host_##field;	\
+	i->private_host_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_host_attrs[count].store = NULL;			\
+	i->host_attrs[count] = &i->private_host_attrs[count];		\
+	count++
+
 #define SETUP_HOST_ATTRIBUTE_RW(field)					\
 	i->private_host_attrs[count] = class_device_attr_host_##field;	\
 	if (!i->f->set_host_##field) {					\
@@ -1090,6 +1427,7 @@
 fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
 			     unsigned long long);
 fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
+fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
 fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
 
 
@@ -1210,6 +1548,9 @@
 static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
 			store_fc_private_host_issue_lip);
 
+fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+
+
 /*
  * Host Statistics Management
  */
@@ -1285,7 +1626,6 @@
 static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
 				fc_reset_statistics);
 
-
 static struct attribute *fc_statistics_attrs[] = {
 	&class_device_attr_host_seconds_since_last_reset.attr,
 	&class_device_attr_host_tx_frames.attr,
@@ -1316,6 +1656,142 @@
 	.attrs = fc_statistics_attrs,
 };
 
+
+/* Host Vport Attributes */
+
+static int
+fc_parse_wwn(const char *ns, u64 *nm)
+{
+	unsigned int i, j;
+	u8 wwn[8];
+
+	memset(wwn, 0, sizeof(wwn));
+
+	/* Validate and store the new name */
+	for (i=0, j=0; i < 16; i++) {
+		if ((*ns >= 'a') && (*ns <= 'f'))
+			j = ((j << 4) | ((*ns++ -'a') + 10));
+		else if ((*ns >= 'A') && (*ns <= 'F'))
+			j = ((j << 4) | ((*ns++ -'A') + 10));
+		else if ((*ns >= '0') && (*ns <= '9'))
+			j = ((j << 4) | (*ns++ -'0'));
+		else
+			return -EINVAL;
+		if (i % 2) {
+			wwn[i/2] = j & 0xff;
+			j = 0;
+		}
+	}
+
+	*nm = wwn_to_u64(wwn);
+
+	return 0;
+}
+
+
+/*
+ * "Short-cut" sysfs variable to create a new vport on a FC Host.
+ * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
+ * will default to a NPIV-based FCP_Initiator; The WWNs are specified
+ * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+	struct fc_vport_identifiers vid;
+	struct fc_vport *vport;
+	unsigned int cnt=count;
+	int stat;
+
+	memset(&vid, 0, sizeof(vid));
+
+	/* count may include a LF at end of string */
+	if (buf[cnt-1] == '\n')
+		cnt--;
+
+	/* validate we have enough characters for WWPN */
+	if ((cnt != (16+1+16)) || (buf[16] != ':'))
+		return -EINVAL;
+
+	stat = fc_parse_wwn(&buf[0], &vid.port_name);
+	if (stat)
+		return stat;
+
+	stat = fc_parse_wwn(&buf[17], &vid.node_name);
+	if (stat)
+		return stat;
+
+	vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
+	vid.vport_type = FC_PORTTYPE_NPIV;
+	/* vid.symbolic_name is already zero/NULL's */
+	vid.disable = false;		/* always enabled */
+
+	/* we only allow support on Channel 0 !!! */
+	stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+			store_fc_host_vport_create);
+
+
+/*
+ * "Short-cut" sysfs variable to delete a vport on a FC Host.
+ * Vport is identified by a string containing "<WWPN>:<WWNN>".
+ * The WWNs are specified as hex characters, and may *not* contain
+ * any prefixes (e.g. 0x, x, etc)
+ */
+static ssize_t
+store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+			   size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_vport *vport;
+	u64 wwpn, wwnn;
+	unsigned long flags;
+	unsigned int cnt=count;
+	int stat, match;
+
+	/* count may include a LF at end of string */
+	if (buf[cnt-1] == '\n')
+		cnt--;
+
+	/* validate we have enough characters for WWPN */
+	if ((cnt != (16+1+16)) || (buf[16] != ':'))
+		return -EINVAL;
+
+	stat = fc_parse_wwn(&buf[0], &wwpn);
+	if (stat)
+		return stat;
+
+	stat = fc_parse_wwn(&buf[17], &wwnn);
+	if (stat)
+		return stat;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	match = 0;
+	/* we only allow support on Channel 0 !!! */
+	list_for_each_entry(vport, &fc_host->vports, peers) {
+		if ((vport->channel == 0) &&
+		    (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
+			match = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (!match)
+		return -ENODEV;
+
+	stat = fc_vport_terminate(vport);
+	return stat ? stat : count;
+}
+static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
+			store_fc_host_vport_delete);
+
+
 static int fc_host_match(struct attribute_container *cont,
 			  struct device *dev)
 {
@@ -1387,6 +1863,40 @@
 }
 
 
+static void fc_vport_dev_release(struct device *dev)
+{
+	struct fc_vport *vport = dev_to_vport(dev);
+	put_device(dev->parent);		/* release kobj parent */
+	kfree(vport);
+}
+
+int scsi_is_fc_vport(const struct device *dev)
+{
+	return dev->release == fc_vport_dev_release;
+}
+EXPORT_SYMBOL(scsi_is_fc_vport);
+
+static int fc_vport_match(struct attribute_container *cont,
+			    struct device *dev)
+{
+	struct fc_vport *vport;
+	struct Scsi_Host *shost;
+	struct fc_internal *i;
+
+	if (!scsi_is_fc_vport(dev))
+		return 0;
+	vport = dev_to_vport(dev);
+
+	shost = vport_to_shost(vport);
+	if (!shost->transportt  || shost->transportt->host_attrs.ac.class
+	    != &fc_host_class.class)
+		return 0;
+
+	i = to_fc_internal(shost->transportt);
+	return &i->vport_attr_cont.ac == cont;
+}
+
+
 /**
  * fc_timed_out - FC Transport I/O timeout intercept handler
  *
@@ -1472,6 +1982,11 @@
 	i->rport_attr_cont.ac.match = fc_rport_match;
 	transport_container_register(&i->rport_attr_cont);
 
+	i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
+	i->vport_attr_cont.ac.class = &fc_vport_class.class;
+	i->vport_attr_cont.ac.match = fc_vport_match;
+	transport_container_register(&i->vport_attr_cont);
+
 	i->f = ft;
 
 	/* Transport uses the shost workq for scsi scanning */
@@ -1480,7 +1995,7 @@
 	i->t.eh_timed_out = fc_timed_out;
 
 	i->t.user_scan = fc_user_scan;
-	
+
 	/*
 	 * Setup SCSI Target Attributes.
 	 */
@@ -1505,6 +2020,10 @@
 	SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
 	SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
 	SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
+	if (ft->vport_create) {
+		SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
+		SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
+	}
 	SETUP_HOST_ATTRIBUTE_RD(serial_number);
 
 	SETUP_HOST_ATTRIBUTE_RD(port_id);
@@ -1520,6 +2039,10 @@
 	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
 	if (ft->issue_fc_host_lip)
 		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
+	if (ft->vport_create)
+		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
+	if (ft->vport_delete)
+		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
 
 	BUG_ON(count > FC_HOST_NUM_ATTRS);
 
@@ -1545,6 +2068,24 @@
 
 	i->rport_attrs[count] = NULL;
 
+	/*
+	 * Setup Virtual Port Attributes.
+	 */
+	count=0;
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
+	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
+	SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
+	SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
+	SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
+
+	BUG_ON(count > FC_VPORT_NUM_ATTRS);
+
+	i->vport_attrs[count] = NULL;
+
 	return &i->t;
 }
 EXPORT_SYMBOL(fc_attach_transport);
@@ -1556,6 +2097,7 @@
 	transport_container_unregister(&i->t.target_attrs);
 	transport_container_unregister(&i->t.host_attrs);
 	transport_container_unregister(&i->rport_attr_cont);
+	transport_container_unregister(&i->vport_attr_cont);
 
 	kfree(i);
 }
@@ -1667,9 +2209,17 @@
 void
 fc_remove_host(struct Scsi_Host *shost)
 {
-	struct fc_rport *rport, *next_rport;
+	struct fc_vport *vport = NULL, *next_vport = NULL;
+	struct fc_rport *rport = NULL, *next_rport = NULL;
 	struct workqueue_struct *work_q;
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	/* Remove any vports */
+	list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
+		fc_queue_work(shost, &vport->vport_delete_work);
 
 	/* Remove any remote ports */
 	list_for_each_entry_safe(rport, next_rport,
@@ -1686,6 +2236,8 @@
 		fc_queue_work(shost, &rport->rport_delete_work);
 	}
 
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
 	/* flush all scan work items */
 	scsi_flush_work(shost);
 
@@ -1744,7 +2296,7 @@
 	unsigned long flags;
 
 	/*
-	 * if a scan is pending, flush the SCSI Host work_q so that 
+	 * if a scan is pending, flush the SCSI Host work_q so that
 	 * that we can reclaim the rport scan work element.
 	 */
 	if (rport->flags & FC_RPORT_SCAN_PENDING)
@@ -1844,7 +2396,7 @@
 	spin_lock_irqsave(shost->host_lock, flags);
 
 	rport->number = fc_host->next_rport_number++;
-	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+	if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
 		rport->scsi_target_id = fc_host->next_target_id++;
 	else
 		rport->scsi_target_id = -1;
@@ -1869,7 +2421,7 @@
 	transport_add_device(dev);
 	transport_configure_device(dev);
 
-	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+	if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
 		/* initiate a scan of the target */
 		rport->flags |= FC_RPORT_SCAN_PENDING;
 		scsi_queue_work(shost, &rport->scan_work);
@@ -2003,7 +2555,7 @@
 
 				/* was a target, not in roles */
 				if ((rport->scsi_target_id != -1) &&
-				    (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
+				    (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
 					return rport;
 
 				/*
@@ -2086,7 +2638,7 @@
 				memset(rport->dd_data, 0,
 						fci->f->dd_fcrport_size);
 
-			if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+			if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
 				/* initiate a scan of the target */
 				rport->flags |= FC_RPORT_SCAN_PENDING;
 				scsi_queue_work(shost, &rport->scan_work);
@@ -2243,11 +2795,11 @@
 	int create = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	if (roles & FC_RPORT_ROLE_FCP_TARGET) {
+	if (roles & FC_PORT_ROLE_FCP_TARGET) {
 		if (rport->scsi_target_id == -1) {
 			rport->scsi_target_id = fc_host->next_target_id++;
 			create = 1;
-		} else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
+		} else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
 			create = 1;
 	}
 
@@ -2294,7 +2846,7 @@
  * fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
  * 			which we blocked, and has now failed to return
  * 			in the allotted time.
- * 
+ *
  * @work:	rport target that failed to reappear in the allotted time.
  **/
 static void
@@ -2317,7 +2869,7 @@
 	 */
 	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
 	    (rport->scsi_target_id != -1) &&
-	    !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+	    !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
 		dev_printk(KERN_ERR, &rport->dev,
 			"blocked FC remote port time out: no longer"
 			" a FCP target, removing starget\n");
@@ -2367,7 +2919,7 @@
 	 */
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
-	rport->roles = FC_RPORT_ROLE_UNKNOWN;
+	rport->roles = FC_PORT_ROLE_UNKNOWN;
 	rport->port_state = FC_PORTSTATE_NOTPRESENT;
 
 	/* remove the identifiers that aren't used in the consisting binding */
@@ -2436,7 +2988,7 @@
 	unsigned long flags;
 
 	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
-	    (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+	    (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
 		scsi_scan_target(&rport->dev, rport->channel,
 			rport->scsi_target_id, SCAN_WILD_CARD, 1);
 	}
@@ -2447,7 +2999,227 @@
 }
 
 
-MODULE_AUTHOR("Martin Hicks");
+/**
+ * fc_vport_create - allocates and creates a FC virtual port.
+ * @shost:	scsi host the virtual port is connected to.
+ * @channel:	Channel on shost port connected to.
+ * @pdev:	parent device for vport
+ * @ids:	The world wide names, FC4 port roles, etc for
+ *              the virtual port.
+ * @ret_vport:	The pointer to the created vport.
+ *
+ * Allocates and creates the vport structure, calls the parent host
+ * to instantiate the vport, the completes w/ class and sysfs creation.
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
+ **/
+static int
+fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
+	struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
+{
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_internal *fci = to_fc_internal(shost->transportt);
+	struct fc_vport *vport;
+	struct device *dev;
+	unsigned long flags;
+	size_t size;
+	int error;
+
+	*ret_vport = NULL;
+
+	if ( ! fci->f->vport_create)
+		return -ENOENT;
+
+	size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
+	vport = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!vport)) {
+		printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	vport->vport_state = FC_VPORT_UNKNOWN;
+	vport->vport_last_state = FC_VPORT_UNKNOWN;
+	vport->node_name = ids->node_name;
+	vport->port_name = ids->port_name;
+	vport->roles = ids->roles;
+	vport->vport_type = ids->vport_type;
+	if (fci->f->dd_fcvport_size)
+		vport->dd_data = &vport[1];
+	vport->shost = shost;
+	vport->channel = channel;
+	vport->flags = FC_VPORT_CREATING;
+	INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		kfree(vport);
+		return -ENOSPC;
+	}
+	fc_host->npiv_vports_inuse++;
+	vport->number = fc_host->next_vport_number++;
+	list_add_tail(&vport->peers, &fc_host->vports);
+	get_device(&shost->shost_gendev);	/* for fc_host->vport list */
+
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	dev = &vport->dev;
+	device_initialize(dev);			/* takes self reference */
+	dev->parent = get_device(pdev);		/* takes parent reference */
+	dev->release = fc_vport_dev_release;
+	sprintf(dev->bus_id, "vport-%d:%d-%d",
+		shost->host_no, channel, vport->number);
+	transport_setup_device(dev);
+
+	error = device_add(dev);
+	if (error) {
+		printk(KERN_ERR "FC Virtual Port device_add failed\n");
+		goto delete_vport;
+	}
+	transport_add_device(dev);
+	transport_configure_device(dev);
+
+	error = fci->f->vport_create(vport, ids->disable);
+	if (error) {
+		printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
+		goto delete_vport_all;
+	}
+
+	/*
+	 * if the parent isn't the physical adapter's Scsi_Host, ensure
+	 * the Scsi_Host at least contains ia symlink to the vport.
+	 */
+	if (pdev != &shost->shost_gendev) {
+		error = sysfs_create_link(&shost->shost_gendev.kobj,
+				 &dev->kobj, dev->bus_id);
+		if (error)
+			printk(KERN_ERR
+				"%s: Cannot create vport symlinks for "
+				"%s, err=%d\n",
+				__FUNCTION__, dev->bus_id, error);
+	}
+	spin_lock_irqsave(shost->host_lock, flags);
+	vport->flags &= ~FC_VPORT_CREATING;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	dev_printk(KERN_NOTICE, pdev,
+			"%s created via shost%d channel %d\n", dev->bus_id,
+			shost->host_no, channel);
+
+	*ret_vport = vport;
+
+	return 0;
+
+delete_vport_all:
+	transport_remove_device(dev);
+	device_del(dev);
+delete_vport:
+	transport_destroy_device(dev);
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_del(&vport->peers);
+	put_device(&shost->shost_gendev);	/* for fc_host->vport list */
+	fc_host->npiv_vports_inuse--;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	put_device(dev->parent);
+	kfree(vport);
+
+	return error;
+}
+
+
+/**
+ * fc_vport_terminate - Admin App or LLDD requests termination of a vport
+ * @vport:	fc_vport to be terminated
+ *
+ * Calls the LLDD vport_delete() function, then deallocates and removes
+ * the vport from the shost and object tree.
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
+ **/
+int
+fc_vport_terminate(struct fc_vport *vport)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_internal *i = to_fc_internal(shost->transportt);
+	struct device *dev = &vport->dev;
+	unsigned long flags;
+	int stat;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (vport->flags & FC_VPORT_CREATING) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		return -EBUSY;
+	}
+	if (vport->flags & (FC_VPORT_DEL)) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		return -EALREADY;
+	}
+	vport->flags |= FC_VPORT_DELETING;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (i->f->vport_delete)
+		stat = i->f->vport_delete(vport);
+	else
+		stat = -ENOENT;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	vport->flags &= ~FC_VPORT_DELETING;
+	if (!stat) {
+		vport->flags |= FC_VPORT_DELETED;
+		list_del(&vport->peers);
+		fc_host->npiv_vports_inuse--;
+		put_device(&shost->shost_gendev);  /* for fc_host->vport list */
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (stat)
+		return stat;
+
+	if (dev->parent != &shost->shost_gendev)
+		sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+
+	/*
+	 * Removing our self-reference should mean our
+	 * release function gets called, which will drop the remaining
+	 * parent reference and free the data structure.
+	 */
+	put_device(dev);			/* for self-reference */
+
+	return 0; /* SUCCESS */
+}
+EXPORT_SYMBOL(fc_vport_terminate);
+
+/**
+ * fc_vport_sched_delete - workq-based delete request for a vport
+ *
+ * @work:	vport to be deleted.
+ **/
+static void
+fc_vport_sched_delete(struct work_struct *work)
+{
+	struct fc_vport *vport =
+		container_of(work, struct fc_vport, vport_delete_work);
+	int stat;
+
+	stat = fc_vport_terminate(vport);
+	if (stat)
+		dev_printk(KERN_ERR, vport->dev.parent,
+			"%s: %s could not be deleted created via "
+			"shost%d channel %d - error %d\n", __FUNCTION__,
+			vport->dev.bus_id, vport->shost->host_no,
+			vport->channel, stat);
+}
+
+
+/* Original Author:  Martin Hicks */
+MODULE_AUTHOR("James Smart");
 MODULE_DESCRIPTION("FC Transport Attributes");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3d8c9cb..448d316 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1515,7 +1515,7 @@
 	if (!scsi_device_online(sdp))
 		goto out;
 
-	buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
+	buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL);
 	if (!buffer) {
 		sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
 			  "allocation failure.\n");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0c691a6..85d3894 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1842,7 +1842,7 @@
 	int blk_size = buff_size;
 	struct page *p = NULL;
 
-	if ((blk_size < 0) || (!sfp))
+	if (blk_size < 0)
 		return -EFAULT;
 	if (0 == blk_size)
 		++blk_size;	/* don't know why */
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 9ac83ab..adda296 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -395,53 +395,34 @@
 static int stex_map_sg(struct st_hba *hba,
 	struct req_msg *req, struct st_ccb *ccb)
 {
-	struct pci_dev *pdev = hba->pdev;
 	struct scsi_cmnd *cmd;
-	dma_addr_t dma_handle;
-	struct scatterlist *src;
+	struct scatterlist *sg;
 	struct st_sgtable *dst;
-	int i;
+	int i, nseg;
 
 	cmd = ccb->cmd;
 	dst = (struct st_sgtable *)req->variable;
 	dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
-	dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
+	dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
 
-	if (cmd->use_sg) {
-		int n_elem;
+	nseg = scsi_dma_map(cmd);
+	if (nseg < 0)
+		return -EIO;
+	if (nseg) {
+		ccb->sg_count = nseg;
+		dst->sg_count = cpu_to_le16((u16)nseg);
 
-		src = (struct scatterlist *) cmd->request_buffer;
-		n_elem = pci_map_sg(pdev, src,
-			cmd->use_sg, cmd->sc_data_direction);
-		if (n_elem <= 0)
-			return -EIO;
-
-		ccb->sg_count = n_elem;
-		dst->sg_count = cpu_to_le16((u16)n_elem);
-
-		for (i = 0; i < n_elem; i++, src++) {
-			dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
+		scsi_for_each_sg(cmd, sg, nseg, i) {
+			dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
 			dst->table[i].addr =
-				cpu_to_le32(sg_dma_address(src) & 0xffffffff);
+				cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
 			dst->table[i].addr_hi =
-				cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
+				cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
 			dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
 		}
 		dst->table[--i].ctrl |= SG_CF_EOT;
-		return 0;
 	}
 
-	dma_handle = pci_map_single(pdev, cmd->request_buffer,
-		cmd->request_bufflen, cmd->sc_data_direction);
-	cmd->SCp.dma_handle = dma_handle;
-
-	ccb->sg_count = 1;
-	dst->sg_count = cpu_to_le16(1);
-	dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
-	dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
-	dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
-	dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
-
 	return 0;
 }
 
@@ -451,24 +432,24 @@
 	size_t lcount;
 	size_t len;
 	void *s, *d, *base = NULL;
-	if (*count > cmd->request_bufflen)
-		*count = cmd->request_bufflen;
+	size_t offset;
+
+	if (*count > scsi_bufflen(cmd))
+		*count = scsi_bufflen(cmd);
 	lcount = *count;
 	while (lcount) {
 		len = lcount;
 		s = (void *)src;
-		if (cmd->use_sg) {
-			size_t offset = *count - lcount;
-			s += offset;
-			base = scsi_kmap_atomic_sg(cmd->request_buffer,
-				sg_count, &offset, &len);
-			if (base == NULL) {
-				*count -= lcount;
-				return;
-			}
-			d = base + offset;
-		} else
-			d = cmd->request_buffer;
+
+		offset = *count - lcount;
+		s += offset;
+		base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
+					   sg_count, &offset, &len);
+		if (!base) {
+			*count -= lcount;
+			return;
+		}
+		d = base + offset;
 
 		if (direction == ST_TO_CMD)
 			memcpy(d, s, len);
@@ -476,30 +457,24 @@
 			memcpy(s, d, len);
 
 		lcount -= len;
-		if (cmd->use_sg)
-			scsi_kunmap_atomic_sg(base);
+		scsi_kunmap_atomic_sg(base);
 	}
 }
 
 static int stex_direct_copy(struct scsi_cmnd *cmd,
 	const void *src, size_t count)
 {
-	struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 	size_t cp_len = count;
 	int n_elem = 0;
 
-	if (cmd->use_sg) {
-		n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
-			cmd->use_sg, cmd->sc_data_direction);
-		if (n_elem <= 0)
-			return 0;
-	}
+	n_elem = scsi_dma_map(cmd);
+	if (n_elem < 0)
+		return 0;
 
 	stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
 
-	if (cmd->use_sg)
-		pci_unmap_sg(hba->pdev, cmd->request_buffer,
-			cmd->use_sg, cmd->sc_data_direction);
+	scsi_dma_unmap(cmd);
+
 	return cp_len == count;
 }
 
@@ -678,18 +653,6 @@
 	return 0;
 }
 
-static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
-{
-	if (cmd->sc_data_direction != DMA_NONE) {
-		if (cmd->use_sg)
-			pci_unmap_sg(hba->pdev, cmd->request_buffer,
-				cmd->use_sg, cmd->sc_data_direction);
-		else
-			pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
-				cmd->request_bufflen, cmd->sc_data_direction);
-	}
-}
-
 static void stex_scsi_done(struct st_ccb *ccb)
 {
 	struct scsi_cmnd *cmd = ccb->cmd;
@@ -756,7 +719,7 @@
 
 	if (ccb->cmd->cmnd[0] == MGT_CMD &&
 		resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
-		ccb->cmd->request_bufflen =
+		scsi_bufflen(ccb->cmd) =
 			le32_to_cpu(*(__le32 *)&resp->variable[0]);
 		return;
 	}
@@ -855,7 +818,7 @@
 				ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
 				stex_controller_info(hba, ccb);
 
-			stex_unmap_sg(hba, ccb->cmd);
+			scsi_dma_unmap(ccb->cmd);
 			stex_scsi_done(ccb);
 			hba->out_req_cnt--;
 		} else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
@@ -1028,7 +991,7 @@
 	}
 
 fail_out:
-	stex_unmap_sg(hba, cmd);
+	scsi_dma_unmap(cmd);
 	hba->wait_ccb->req = NULL; /* nullify the req's future return */
 	hba->wait_ccb = NULL;
 	result = FAILED;
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index 2ca9505..92bfaea 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -332,8 +332,7 @@
 	int i;
 	unsigned long flags = 0;
 	unsigned char status_reg, pio_int_reg, int_reg;
-	struct scatterlist *sglist;
-	unsigned int sgcount;
+	struct scatterlist *sg;
 	unsigned int tot_trans = 0;
 
 	/* We search the base address of the host adapter which caused the interrupt */
@@ -429,19 +428,15 @@
 			{
 				current_command->SCp.phase = data_out;
 				outb(FLUSH_FIFO, base + COMMAND_REG);
-				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+				sym53c416_set_transfer_counter(base,
+							       scsi_bufflen(current_command));
 				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
-				if(!current_command->use_sg)
-					tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
-				else
-				{
-					sgcount = current_command->use_sg;
-					sglist = current_command->request_buffer;
-					while(sgcount--)
-					{
-						tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length);
-						sglist++;
-					}
+
+				scsi_for_each_sg(current_command,
+						 sg, scsi_sg_count(current_command), i) {
+					tot_trans += sym53c416_write(base,
+								     SG_ADDRESS(sg),
+								     sg->length);
 				}
 				if(tot_trans < current_command->underflow)
 					printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
@@ -455,19 +450,16 @@
 			{
 				current_command->SCp.phase = data_in;
 				outb(FLUSH_FIFO, base + COMMAND_REG);
-				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+				sym53c416_set_transfer_counter(base,
+							       scsi_bufflen(current_command));
+
 				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
-				if(!current_command->use_sg)
-					tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
-				else
-				{
-					sgcount = current_command->use_sg;
-					sglist = current_command->request_buffer;
-					while(sgcount--)
-					{
-						tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length);
-						sglist++;
-					}
+
+				scsi_for_each_sg(current_command,
+						 sg, scsi_sg_count(current_command), i) {
+					tot_trans += sym53c416_read(base,
+								    SG_ADDRESS(sg),
+								    sg->length);
 				}
 				if(tot_trans < current_command->underflow)
 					printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index e7b85e8..73c5ca0 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -457,28 +457,21 @@
 			error = 1;
 		DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
 	/* Map SG list */
-	} else if (pcmd->use_sg) {
-		pSRB->pSegmentList	= (struct scatterlist *) pcmd->request_buffer;
-		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg,
-						     pcmd->sc_data_direction);
-		/* TODO: error handling */
-		if (!pSRB->SGcount)
-			error = 1;
-		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
-			      __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
-	/* Map single segment */
-	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen);
-		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
-						     pcmd->sc_data_direction);
-		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
+	} else if (scsi_sg_count(pcmd)) {
+		int nseg;
+
+		nseg = scsi_dma_map(pcmd);
+
+		pSRB->pSegmentList	= scsi_sglist(pcmd);
+		pSRB->SGcount		= nseg;
 
 		/* TODO: error handling */
-		if (pSRB->SGcount != 1)
+		if (nseg < 0)
 			error = 1;
-		DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle));
-	/* No mapping !? */	
-    	} else
+		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
+			      __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
+	/* Map single segment */
+	} else
 		pSRB->SGcount = 0;
 
 	return error;
@@ -494,12 +487,10 @@
 	if (pSRB->SRBFlag) {
 		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
 		DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
-	} else if (pcmd->use_sg) {
-		pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction);
-		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg));
-	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction);
-		DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
+	} else {
+		scsi_dma_unmap(pcmd);
+		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
+			      __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
 	}
 }
 
@@ -1153,9 +1144,9 @@
     struct scatterlist *psgl;
     pSRB->TotalXferredLen = 0;
     pSRB->SGIndex = 0;
-    if (pcmd->use_sg) {
+    if (scsi_sg_count(pcmd)) {
 	size_t saved;
-	pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
+	pSRB->pSegmentList = scsi_sglist(pcmd);
 	psgl = pSRB->pSegmentList;
 	//dc390_pci_sync(pSRB);
 
@@ -1179,12 +1170,6 @@
 	printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
 		pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
 
-    } else if(pcmd->request_buffer) {
-	//dc390_pci_sync(pSRB);
-
-	sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr;
-	pSRB->SGcount = 1;
-	pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
     } else {
 	 pSRB->SGcount = 0;
 	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
@@ -1612,7 +1597,7 @@
 	if( !( pACB->scan_devices ) )
 	{
 	    struct scsi_cmnd *pcmd = pSRB->pcmd;
-	    pcmd->resid = pcmd->request_bufflen;
+	    scsi_set_resid(pcmd, scsi_bufflen(pcmd));
 	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
 	    dc390_Going_remove(pDCB, pSRB);
 	    dc390_Free_insert(pACB, pSRB);
@@ -1695,7 +1680,7 @@
 			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
 
 	pSRB->SRBFlag |= AUTO_REQSENSE;
-	pSRB->SavedSGCount = pcmd->use_sg;
+	pSRB->SavedSGCount = scsi_sg_count(pcmd);
 	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
 	pSRB->AdaptStatus = 0;
 	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
@@ -1743,7 +1728,7 @@
 		       (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
 	    } else {
 		SET_RES_DRV(pcmd->result, DRIVER_SENSE);
-		pcmd->use_sg = pSRB->SavedSGCount;
+		scsi_sg_count(pcmd) = pSRB->SavedSGCount;
 		//pSRB->ScsiCmdLen	 = (u8) (pSRB->Segment1[0] >> 8);
 		DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
 		pSRB->TotalXferredLen = 0;
@@ -1765,7 +1750,7 @@
 	else if( status_byte(status) == QUEUE_FULL )
 	{
 	    scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-	    pcmd->use_sg = pSRB->SavedSGCount;
+	    scsi_sg_count(pcmd) = pSRB->SavedSGCount;
 	    DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
 	    pSRB->TotalXferredLen = 0;
 	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
@@ -1816,7 +1801,7 @@
     }
 
 cmd_done:
-    pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
+    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
 
     dc390_Going_remove (pDCB, pSRB);
     /* Add to free list */
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 3de08a1..9e8232a 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1111,7 +1111,7 @@
 static void map_dma(unsigned int i, unsigned int j) {
    unsigned int data_len = 0;
    unsigned int k, count, pci_dir;
-   struct scatterlist *sgpnt;
+   struct scatterlist *sg;
    struct mscp *cpp;
    struct scsi_cmnd *SCpnt;
 
@@ -1124,33 +1124,28 @@
 
    cpp->sense_len = sizeof SCpnt->sense_buffer;
 
-   if (!SCpnt->use_sg) {
+   if (scsi_bufflen(SCpnt)) {
+	   count = scsi_dma_map(SCpnt);
+	   BUG_ON(count < 0);
 
-      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
-      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
+	   scsi_for_each_sg(SCpnt, sg, count, k) {
+		   cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+		   cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
+		   data_len += sg->length;
+	   }
 
-      if (SCpnt->request_buffer)
-         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
-                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+	   cpp->sg = TRUE;
+	   cpp->use_sg = scsi_sg_count(SCpnt);
+	   cpp->data_address =
+		   H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+					cpp->use_sg * sizeof(struct sg_list),
+					pci_dir));
+	   cpp->data_len = H2DEV(data_len);
 
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      return;
-      }
-
-   sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
-
-   for (k = 0; k < count; k++) {
-      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
-      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
-      data_len += sgpnt[k].length;
-      }
-
-   cpp->sg = TRUE;
-   cpp->use_sg = SCpnt->use_sg;
-   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
-                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
-   cpp->data_len = H2DEV(data_len);
+   } else {
+	   pci_dir = PCI_DMA_BIDIRECTIONAL;
+	   cpp->data_len = H2DEV(scsi_bufflen(SCpnt));
+   }
 }
 
 static void unmap_dma(unsigned int i, unsigned int j) {
@@ -1165,8 +1160,7 @@
       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg)
-      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+   scsi_dma_unmap(SCpnt);
 
    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
@@ -1187,9 +1181,9 @@
       pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr),
                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg)
-      pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer,
-                         SCpnt->use_sg, pci_dir);
+   if (scsi_sg_count(SCpnt))
+	   pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt),
+				   scsi_sg_count(SCpnt), pci_dir);
 
    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 56906ab..c08235d 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -675,16 +675,15 @@
 
 static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt)
 {
-	struct scatterlist *sl;
+	struct scatterlist *sg;
 	long transfer_length = 0;
 	int i, max;
 
-	sl = (struct scatterlist *) SCpnt->request_buffer;
-	max = SCpnt->use_sg;
-	for (i = 0; i < max; i++) {
-		mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
-		mscp->sglist[i].num_bytes = sl[i].length;
-		transfer_length += sl[i].length;
+	max = scsi_sg_count(SCpnt);
+	scsi_for_each_sg(SCpnt, sg, max, i) {
+		mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset;
+		mscp->sglist[i].num_bytes = sg->length;
+		transfer_length += sg->length;
 	}
 	mscp->number_of_sg_list = max;
 	mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
@@ -730,15 +729,15 @@
     my_mscp->target_id = SCpnt->device->id;
     my_mscp->ch_no = 0;
     my_mscp->lun = SCpnt->device->lun;
-    if (SCpnt->use_sg) {
+    if (scsi_sg_count(SCpnt)) {
 	/* Set scatter/gather flag in SCSI command packet */
 	my_mscp->sg = TRUE;
 	build_sg_list(my_mscp, SCpnt);
     } else {
 	/* Unset scatter/gather flag in SCSI command packet */
 	my_mscp->sg = FALSE;
-	my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
-	my_mscp->transfer_data_length = SCpnt->request_bufflen;
+	my_mscp->transfer_data = isa_virt_to_bus(scsi_sglist(SCpnt));
+	my_mscp->transfer_data_length = scsi_bufflen(SCpnt);
     }
     my_mscp->command_link = 0;		/*???*/
     my_mscp->scsi_command_link_id = 0;	/*???*/
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 30be765..d6fd425 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1091,6 +1091,7 @@
 	unchar *cdb = (unchar *) SCpnt->cmnd;
 	unchar idlun;
 	short cdblen;
+	int nseg;
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
 
 	cdblen = SCpnt->cmd_len;
@@ -1106,28 +1107,29 @@
 	SCpnt->host_scribble = (unchar *) scb;
 	scb->host = host;
 
-	if (SCpnt->use_sg) {
-		struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+	nseg = scsi_sg_count(SCpnt);
+	if (nseg) {
+		struct scatterlist *sg;
 		unsigned i;
 
 		if (SCpnt->device->host->sg_tablesize == SG_NONE) {
 			panic("wd7000_queuecommand: scatter/gather not supported.\n");
 		}
-		dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
+		dprintk("Using scatter/gather with %d elements.\n", nseg);
 
 		sgb = scb->sgb;
 		scb->op = 1;
 		any2scsi(scb->dataptr, (int) sgb);
-		any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb));
+		any2scsi(scb->maxlen, nseg * sizeof(Sgb));
 
-		for (i = 0; i < SCpnt->use_sg; i++) {
-			any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset);
-			any2scsi(sgb[i].len, sg[i].length);
+		scsi_for_each_sg(SCpnt, sg, nseg, i) {
+			any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset);
+			any2scsi(sgb[i].len, sg->length);
 		}
 	} else {
 		scb->op = 0;
-		any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
-		any2scsi(scb->maxlen, SCpnt->request_bufflen);
+		any2scsi(scb->dataptr, isa_virt_to_bus(scsi_sglist(SCpnt)));
+		any2scsi(scb->maxlen, scsi_bufflen(SCpnt));
 	}
 
 	/* FIXME: drop lock and yield here ? */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index a2e0c10..53e1705 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -135,4 +135,24 @@
 extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
 extern void scsi_free_sgtable(struct scatterlist *, int);
 
+extern int scsi_dma_map(struct scsi_cmnd *cmd);
+extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
+
+#define scsi_sg_count(cmd) ((cmd)->use_sg)
+#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
+#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+
+static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
+{
+	cmd->resid = resid;
+}
+
+static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+{
+	return cmd->resid;
+}
+
+#define scsi_for_each_sg(cmd, sg, nseg, __i)			\
+	for (__i = 0, sg = scsi_sglist(cmd); __i < (nseg); __i++, (sg)++)
+
 #endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 68f461b..4a2e490 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -339,12 +339,6 @@
 	enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
 
 	/*
-	 * suspend support
-	 */
-	int (*resume)(struct scsi_device *);
-	int (*suspend)(struct scsi_device *, pm_message_t state);
-
-	/*
 	 * Name of proc directory
 	 */
 	char *proc_name;
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 1e79730..a0d80bc 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -1,4 +1,4 @@
-/* 
+/*
  *  FiberChannel transport specific attributes exported to sysfs.
  *
  *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
@@ -19,7 +19,7 @@
  *
  *  ========
  *
- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
  *    Rewrite for host, target, device, and remote port attributes,
  *    statistics, and service functions...
  *
@@ -62,8 +62,10 @@
 	FC_PORTTYPE_NLPORT,		/* (Public) Loop w/ FLPort */
 	FC_PORTTYPE_LPORT,		/* (Private) Loop w/o FLPort */
 	FC_PORTTYPE_PTP,		/* Point to Point w/ another NPort */
+	FC_PORTTYPE_NPIV,		/* VPORT based on NPIV */
 };
 
+
 /*
  * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c
  * (for the ascii descriptions).
@@ -83,7 +85,26 @@
 };
 
 
-/* 
+/*
+ * fc_vport_state: If you alter this, you also need to alter
+ * scsi_transport_fc.c (for the ascii descriptions).
+ */
+enum fc_vport_state {
+	FC_VPORT_UNKNOWN,
+	FC_VPORT_ACTIVE,
+	FC_VPORT_DISABLED,
+	FC_VPORT_LINKDOWN,
+	FC_VPORT_INITIALIZING,
+	FC_VPORT_NO_FABRIC_SUPP,
+	FC_VPORT_NO_FABRIC_RSCS,
+	FC_VPORT_FABRIC_LOGOUT,
+	FC_VPORT_FABRIC_REJ_WWN,
+	FC_VPORT_FAILED,
+};
+
+
+
+/*
  * FC Classes of Service
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report supported_classes). If you alter this list,
@@ -96,7 +117,7 @@
 #define FC_COS_CLASS4			0x10
 #define FC_COS_CLASS6			0x40
 
-/* 
+/*
  * FC Port Speeds
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report supported_speeds). If you alter this list,
@@ -124,16 +145,114 @@
 };
 
 /*
- * FC Remote Port Roles
+ * FC Port Roles
  * Note: values are not enumerated, as they can be "or'd" together
  * for reporting (e.g. report roles). If you alter this list,
  * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
  */
-#define FC_RPORT_ROLE_UNKNOWN			0x00
-#define FC_RPORT_ROLE_FCP_TARGET		0x01
-#define FC_RPORT_ROLE_FCP_INITIATOR		0x02
-#define FC_RPORT_ROLE_IP_PORT			0x04
+#define FC_PORT_ROLE_UNKNOWN			0x00
+#define FC_PORT_ROLE_FCP_TARGET			0x01
+#define FC_PORT_ROLE_FCP_INITIATOR		0x02
+#define FC_PORT_ROLE_IP_PORT			0x04
 
+/* The following are for compatibility */
+#define FC_RPORT_ROLE_UNKNOWN			FC_PORT_ROLE_UNKNOWN
+#define FC_RPORT_ROLE_FCP_TARGET		FC_PORT_ROLE_FCP_TARGET
+#define FC_RPORT_ROLE_FCP_INITIATOR		FC_PORT_ROLE_FCP_INITIATOR
+#define FC_RPORT_ROLE_IP_PORT			FC_PORT_ROLE_IP_PORT
+
+
+/* Macro for use in defining Virtual Port attributes */
+#define FC_VPORT_ATTR(_name,_mode,_show,_store)				\
+struct class_device_attribute class_device_attr_vport_##_name = 	\
+	__ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * FC Virtual Port Attributes
+ *
+ * This structure exists for each FC port is a virtual FC port. Virtual
+ * ports share the physical link with the Physical port. Each virtual
+ * ports has a unique presense on the SAN, and may be instantiated via
+ * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
+ * unique presense, each vport has it's own view of the fabric,
+ * authentication priviledge, and priorities.
+ *
+ * A virtual port may support 1 or more FC4 roles. Typically it is a
+ * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
+ * roles. FC port attributes for the vport will be reported on any
+ * fc_host class object allocated for an FCP Initiator.
+ *
+ * --
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after receiving the fc_vport structure
+ * via the vport_create() call from the transport.
+ * The transport fully manages all get functions w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+
+#define FC_VPORT_SYMBOLIC_NAMELEN		64
+struct fc_vport {
+	/* Fixed Attributes */
+
+	/* Dynamic Attributes */
+
+	/* Private (Transport-managed) Attributes */
+	enum fc_vport_state vport_state;
+	enum fc_vport_state vport_last_state;
+	u64 node_name;
+	u64 port_name;
+	u32 roles;
+	u32 vport_id;		/* Admin Identifier for the vport */
+	enum fc_port_type vport_type;
+	char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+
+	/* exported data */
+	void *dd_data;			/* Used for driver-specific storage */
+
+	/* internal data */
+	struct Scsi_Host *shost;	/* Physical Port Parent */
+	unsigned int channel;
+	u32 number;
+	u8 flags;
+	struct list_head peers;
+	struct device dev;
+	struct work_struct vport_delete_work;
+} __attribute__((aligned(sizeof(unsigned long))));
+
+/* bit field values for struct fc_vport "flags" field: */
+#define FC_VPORT_CREATING		0x01
+#define FC_VPORT_DELETING		0x02
+#define FC_VPORT_DELETED		0x04
+#define FC_VPORT_DEL			0x06	/* Any DELETE state */
+
+#define	dev_to_vport(d)				\
+	container_of(d, struct fc_vport, dev)
+#define transport_class_to_vport(classdev)	\
+	dev_to_vport(classdev->dev)
+#define vport_to_shost(v)			\
+	(v->shost)
+#define vport_to_shost_channel(v)		\
+	(v->channel)
+#define vport_to_parent(v)			\
+	(v->dev.parent)
+
+
+/* Error return codes for vport_create() callback */
+#define VPCERR_UNSUPPORTED		-ENOSYS		/* no driver/adapter
+							   support */
+#define VPCERR_BAD_WWN			-ENOTUNIQ	/* driver validation
+							   of WWNs failed */
+#define VPCERR_NO_FABRIC_SUPP		-EOPNOTSUPP	/* Fabric connection
+							   is loop or the
+							   Fabric Port does
+							   not support NPIV */
 
 /*
  * fc_rport_identifiers: This set of data contains all elements
@@ -149,6 +268,7 @@
 	u32 roles;
 };
 
+
 /* Macro for use in defining Remote Port attributes */
 #define FC_RPORT_ATTR(_name,_mode,_show,_store)				\
 struct class_device_attribute class_device_attr_rport_##_name = 	\
@@ -278,7 +398,7 @@
 	u64 prim_seq_protocol_err_count;
 	u64 invalid_tx_word_count;
 	u64 invalid_crc_count;
-	
+
 	/* fc4 statistics  (only FCP supported currently) */
 	u64 fcp_input_requests;
 	u64 fcp_output_requests;
@@ -343,6 +463,7 @@
 	u8  supported_fc4s[FC_FC4_LIST_SIZE];
 	u32 supported_speeds;
 	u32 maxframe_size;
+	u16 max_npiv_vports;
 	char serial_number[FC_SERIAL_NUMBER_SIZE];
 
 	/* Dynamic Attributes */
@@ -361,8 +482,11 @@
 	/* internal data */
 	struct list_head rports;
 	struct list_head rport_bindings;
+	struct list_head vports;
 	u32 next_rport_number;
 	u32 next_target_id;
+	u32 next_vport_number;
+	u16 npiv_vports_inuse;
 
 	/* work queues for rport state manipulation */
 	char work_q_name[KOBJ_NAME_LEN];
@@ -388,6 +512,8 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
 #define fc_host_maxframe_size(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
+#define fc_host_max_npiv_vports(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
 #define fc_host_serial_number(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->serial_number)
 #define fc_host_port_id(x)	\
@@ -412,10 +538,16 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->rports)
 #define fc_host_rport_bindings(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
+#define fc_host_vports(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->vports)
 #define fc_host_next_rport_number(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
 #define fc_host_next_target_id(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
+#define fc_host_next_vport_number(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
+#define fc_host_npiv_vports_inuse(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
 #define fc_host_work_q_name(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
 #define fc_host_work_q(x) \
@@ -452,14 +584,20 @@
 	void    (*dev_loss_tmo_callbk)(struct fc_rport *);
 	void	(*terminate_rport_io)(struct fc_rport *);
 
+	void	(*set_vport_symbolic_name)(struct fc_vport *);
+	int  	(*vport_create)(struct fc_vport *, bool);
+	int	(*vport_disable)(struct fc_vport *, bool);
+	int  	(*vport_delete)(struct fc_vport *);
+
 	/* allocation lengths for host-specific data */
 	u32	 			dd_fcrport_size;
+	u32	 			dd_fcvport_size;
 
-	/* 
+	/*
 	 * The driver sets these to tell the transport class it
 	 * wants the attributes displayed in sysfs.  If the show_ flag
 	 * is not set, the attribute will be private to the transport
-	 * class 
+	 * class
 	 */
 
 	/* remote port fixed attributes */
@@ -512,7 +650,7 @@
 
 	switch (rport->port_state) {
 	case FC_PORTSTATE_ONLINE:
-		if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+		if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
 			result = 0;
 		else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
 			result = DID_IMM_RETRY << 16;
@@ -549,6 +687,27 @@
 	wwn[7] = inm & 0xff;
 }
 
+/**
+ * fc_vport_set_state() - called to set a vport's state. Saves the old state,
+ *   excepting the transitory states of initializing and sending the ELS
+ *   traffic to instantiate the vport on the link.
+ *
+ * Assumes the driver has surrounded this with the proper locking to ensure
+ * a coherent state change.
+ *
+ * @vport:	virtual port whose state is changing
+ * @new_state:  new state
+ **/
+static inline void
+fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
+{
+	if ((new_state != FC_VPORT_UNKNOWN) &&
+	    (new_state != FC_VPORT_INITIALIZING))
+		vport->vport_last_state = vport->vport_state;
+	vport->vport_state = new_state;
+}
+
+
 struct scsi_transport_template *fc_attach_transport(
 			struct fc_function_template *);
 void fc_release_transport(struct scsi_transport_template *);
@@ -567,5 +726,6 @@
 	 *   be sure to read the Vendor Type and ID formatting requirements
 	 *   specified in scsi_netlink.h
 	 */
+int fc_vport_terminate(struct fc_vport *vport);
 
 #endif /* SCSI_TRANSPORT_FC_H */